TECH PLAY

株式会社mediba

株式会社mediba の技術ブログ

167

こんにちは! mediba 制作部でデザイナーをしている森本です。 お仕事でイラストを描く場面が多々あるのですが、今までは手描きのラフを Illustratorで読み込み、手でトレースしたりしていました。 細かいことは好きなのでそんなに苦にはならないのですが、やはり時間がかかる… ということで、最近は気が付くと色々なアプリがリリースされているAdobe CCの中から、 Adobe Capture CC というアプリを使ってみましたのでご紹介したいと思います。 まず、Adobe Capture CCとは? iPhoneなどで撮影した画像を取り込み、ベクトル画像に変換し、 シェイプとしてIllustratorやPhotoshopで使用できるというとても便利なアプリです! 手描きしたイラストを撮影し、写真からパスを作成することが出来るので、 今までトレースしていた時間も短縮できますね。 Adobe Capture CCアプリを開きます 使い方はとっても簡単! まずは iTunes App Store や Google Play で、 Adobe Capture CC をダウンロードします。 無償または有償のCreative Cloudメンバーシップが必要です。 使用前にAdobe IDでサインインしてください。 キャプチャをベクターシェイプに変換する 1.イラストを描く 今回は私が大好きなシロクマを描いてみました! 2.Adobe Capture CC へ取り込む SHAPESメニューを選択し、『 + 』アイコンをタップします。 3.イラストを撮影する カメラをイラストに向けると、主なトレースラインが緑色でハイライト表示されるので、スライダーを動かしながら最適な結果になるようコントラストの調整をし、シェイプを保存します。 (右下のアイコンから、カメラロール、Creative Cloud内の画像を選択することもできます。) 4.パスの調整をする 『 パスを削除 』でいらない要素を削除して調整していく。 一度削除しても『 削除を取り消し 』で戻すことができます。 5.プレビューで確認 『 次へ 』をタップするとなめらかな曲線にしてくれます。 6.シェイプを保存する 『 次へ 』をタップし、わかりやすい名前をつけて保存先のライブラリを新規作成もしくは選択。 『 SHAPEを保存 』をタップすると、マイライブラリ内のSHAPES へ保存されます。 続いては、イラストで使うカラーを決めていきたいと思います。 1枚の画像からカラーテーマを作成する 1.カラーテーマ用の画像を撮影する COLORSメニューを選択し、『 + 』アイコンをタップします。 カメラを対象に向けると、アプリが自動的にシーンから5つのカラーを選択。 ポインターをドラッグしてそれぞれのカラースウォッチを調整し、カラーテーマを保存します。 (右下のアイコンから、カメラロール、Creative Cloud内の画像を選択することもできます。) 2.カラーテーマを保存する テーマ名をわかりやすい名前に変更し『 COLOR テーマを保存 』をタップするとマイライブラリ内のCOLORS へ保存されます。 3.Illustratorで読み込む 保存をすると、同期をしているIllustratorのライブラリ内にシェイプとカラーテーマが反映されるので、ライブラリからドラッグでアートボードへ移動し、Illustrator上で編集することができます。 4.Illustrator上でイラストを編集したら完成です! Adobe Capture CCを使ってみて感じたこと ・手描き風などのシンプルなイラストであればそのまま使えるので便利! ・ラフ段階のイラストをデータ化して見せたい時に使える ・線が塗りで取り込まれるので、編集したい場合には少し手がかかる ・そのため手の込んだイラストを描きたい時には結局Illustratorでトレースしたくなりそう… などなど、線で取り込めるようになればこのアプリ、もっと使い方が広がるなぁと感じました。 まだまだ改良中のようですので、今後に期待します! 長い記事を最後まで読んでいただき、ありがとうございました!
アバター
こんにちは、メディアシステム開発部の竹谷です。 私のチームではAWS CodeDeployを使っているのですが、デプロイ結果をSlackに流せないかなと思って調べてみました。 CodeDeployは、デプロイのステータスをAWS SNSに流すことができるので、CodeDeploy→SNS→Lambda→Slackといった流れで実現してみました。 SNSの設定 まずは、CodeDeployのステータスを流すSNS topicを新規作成します。 CodeDeployの設定 トリガーの作成から、デプロイステータスをSNSに送る設定を行います。 作成したSNS topicを指定します。 Lambda functionの作成 次にLambda functionの作成ですが、Lambdaを実行するIAM Roleをあらかじめ作っておきます。 最低限AWSLambdaExecuteが必要です。 Lambda functionを作成します。 今回はPythonで作成します。右下のsns-message-pythonを選びます。 作成したSNS topicを選択します。 Roleには作成しておいたRoleを指定します。 コードは以下のような感じです。 (requests ライブラリを使用していますので、実際にはパッケージ化する必要があります) import json import requests def lambda_handler(event, context): print("Received event: " + json.dumps(event, indent=2)) message = event['Records'][0]['Sns']['Message'] print("From SNS: " + message) messageDict = json.loads(message) if messageDict['status'] == 'FAILED': slackColor = 'danger' slackValue = messageDict['errorInformation'] else: slackColor = 'good' slackValue = messageDict['status'] url = 'https://hooks.slack.com/services/xxxxx/xxxxx' payload = { 'channel': '#deploy', 'username': 'CodeDeploy', 'icon_emoji': ':shipit:', 'attachments': [ { 'fallback': 'code deploy status : ' + messageDict['deploymentGroupName'] + ' : ' + messageDict['status'], 'color': slackColor, 'title': messageDict['deploymentGroupName'] + ' : ' + messageDict['status'], 'text': slackValue } ] } headers = {'content-type': 'application/json'} r = requests.post(url, data=json.dumps(payload), headers=headers) return message CodeDeployを動かしてみる Lambda functionを作成して、実際にCodeDeployを動かすとSlackに流れることが確認できました。 デプロイ開始と成功した場合。 デプロイ失敗した場合。 まとめ デプロイ結果がSlackに流れると便利ですね。
アバター
JAWS DAYS 2016
こんにちは、CTOをしている山田です。 JAWS DAYS2016参加してきました。何と参加者が1100名以上だったようで、すごい盛り上がりでした。 改めてコミュニティの凄さとそれを惹きつけるAWSの魅力を実感しております。また、隅々まで気配りが行き届いた本当に素晴らしいイベントでした。 運営者の皆様お疲れ様でした。 私はユーザートラックの「 ユーザの本音、AWS入れてどうなった? 」というパネルディスカッションにパネラーとして参加してきましたので、そこでお話した内容をまとめます。 このセッションは、これからAWSを導入、もしくは導入間もない方向けに、導入前後の変化や導入後に出た課題、次どういうことをしていくかというディスカッションでした。 まずは自己紹介を交えてお話しした内容です。 導入した目的 ビジネス側から要求を満たすために2つの大きな課題があり、どうしてもインフラがボトルネックになってしまうため、クラウドの採用は必然でした。 開発のアジリティを大きく向上させる必要があった 読めないトラフィックに対応する必要があった 提供されているサービスのカバー領域、情報量、コミュニティの存在、AWSのサポート体制、エンジニアの興味ということでAWSの採用に至りました。 なお、現在もですが、導入当時から クラスメソッド様 にご支援頂いております。 どのように使っているか? AWSを採用して2年になります。 新規サービスはAWS 稼働中のシステムの半分以上はAWS 今後も継続されるサービスもEOSLを迎えるタイミングで移行 スパイクするアクセスのデータ処理はDynamoDB、イベントトリガーが処理する時はLambda、Push通知はSNS、データ集計はRedshift、操作ログ保存ではGlacierといったような、サービス毎の特性、仕様に合わせた使い方をしています。 どういった立場で使っているか? プロダクトオーナーがKDDIの場合でも、medibaがインフラも含めた技術選定から開発、運用までシステムオーナーとして利用しています。 ここからディスカッションテーマになり、私が発言した部分について補足を加えて記載します。 導入後どうなりました?どんな変化がありましたか? 導入後は、アプリ開発の時間軸にインフラがついてこれるようになったのでアジリティが圧倒的に向上しましたし、キャパシティを柔軟に変更できるため読めないトラフィックによるビジネスへの制約を最小限に抑えることができるようになってきたと思います。 また、オンプレですとコストの制約から環境が貧弱だったり、節約のために相乗りさせてごった煮サーバができたりということもありましたし、リリース以降は商用の環境を再現することはできなかったのですが、開発の状況に応じて開発環境を柔軟に作り変えられることができることも非常に大きなメリットです。 では次は?(次へ取り組みことは?) インフラチームのリソースも限られており、AWSにおいてはアプリエンジニア主導で進めてきました。AWSを中心としたクラウドによる技術的な変化もそうですし、フロントエンドもかなり技術的な変化が大きく、サービスを多く抱える弊社では、全員がフルスタックを目指すのは限界が見えているので、分業制を敷き、クラウド専任部隊を作り、ナレッジ、ノウハウを集約しクラウド専任メンバーをPJにアサインしていく組織として推進し始めました。 (専任部隊を置くことが、厳密なタスクの線引をしていくというよりも、どこに専門性を置くかということで、サッカーでのチームプレーに例えるとDFも時には攻め上がりますし、FWも前線からディフェンスもするように、専門的なところに主軸を置きそこだけに縛られずチームの状況に応じて業務を進めていくことを目指しています) コミュニティが自分や社内に与えた影響 弊社メンバーもJAWSにお世話になっており、そこの空気感とか勢いを社内に持ち込んでくれてまして、社内の情報共有の活性化にも繋がりましたし、また社外への貢献していく姿勢ができ、ブログも始めるきっかけにもなりました。 何よりもコミュニティへの参加は楽しいですし、いい刺激になりますね。 最後に medibaでは、今後もAWSに注力していきます。また、AWSだけでなく新しい技術を積極的に取り入れ、多くのお客様にご利用して頂けるサービスを提供していきます。 今回お話したAWSをメインにしたクラウドチーム、それ以外にもauサービス、新規サービス、広告システムと様々ポジションでエンジニアを募集しています。 ご興味がある方は、 募集ページ から応募してしてください。 面談という形で情報交換をするのでも大歓迎です。
アバター
こんにちは。medibaのauスマートパス開発部の小川です。 最近業務でAndroidアプリ開発を行っておりまして、(今更ですが)Drawerlayoutを加工する機会がありました。 その際に、簡単に出来そうなのに実装してみると悩んだ箇所をまとめてみようとか思います。 ちなみにNavigationViewを使ってはいるのですが主にtoolbarとDrawerlayoutへのカスタマイズの話になりますので、マテリアルデザインの話は出てきません。 NavigationViewは2015/5にAndroid Design Support Libraryに追加された機能で、これを使う事と今まで自分でRelativeLayoutをListViewにaddHeaderViewしていた実装を手軽に書く事が出来て便利なのですが、今回はそれより前段の話になります。 今回出てくるお話 概要 before after 変更箇所 toolbarの位置を上から下に変更(色も変更) DrawerButtonを変更 Drawerが閉じた時に開くボタン(ドロイド君アイコン)を表示 コードについて Android Studio(v1.5.1)のNavigation Drawew Activityの自動生成ファイルに対し、修正を行った箇所のみを記載しています。 メインコンテンツのWebViewの挿入はbefore,afterともにonCreate内で実施しています。 詳細 1.toolbarの位置を上から下に変更 デザインとしてはAndroidアプリっぽさが薄れますが、要件によっては下に持って行く必要に迫られる時もあります(した)。 app_bar_main.xmlのtoolbar周りの箇所 <!-- MainActivity用のlayout--> <android.support.design.widget.AppBarLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:theme="@style/AppTheme.AppBarOverlay"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <FrameLayout android:layout_width="match_parent" android:layout_height="match_parent"> <WebView android:id="@+id/myWebView" android:layout_width="match_parent" android:layout_height="524dp"/> <android.support.design.widget.FloatingActionButton android:id="@+id/fab" android:layout_width="wrap_content" android:layout_height="68dp" android:src="@android:drawable/ic_dialog_info" android:layout_above="@+id/custom_toolbar" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:layout_gravity="left|bottom"/> </FrameLayout> <android.support.v7.widget.Toolbar android:id="@+id/custom_toolbar" android:background="@android:color/darker_gray" xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_alignParentBottom="true" android:layout_width="match_parent" android:layout_height="wrap_content" app:popupTheme="@style/AppTheme.PopupOverlay" android:layout_alignParentLeft="true" android:layout_alignParentStart="true"> </android.support.v7.widget.Toolbar> </LinearLayout> </android.support.design.widget.AppBarLayout> こちら、xmlにてLinearLayoutで上下2段に区切ったのち、上段をFrameLayoutで括ったWebViewとFloatingActionButton、下段をToolbarとする事で Toolberを下部に移動させています。 Toolbarは他のViewと同様に扱う事が可能です。 2.DrawerButtonを変更 デザインとしてはAndroidアプリっぽさが薄れますが、要件によっては左上の「開く」ボタン(3本線アイコン)を配置場所、デザインともに変更する必要があります(した)。 今回はDrawerボタンを3本線アイコンからFloatingActionButton(画面左下に浮いている丸いボタン)に変更してみました。 MainActivity.javaのonCreateメソッド内にて // FloatingActionButtonを新たに追加 fab = (FloatingActionButton) findViewById(R.id.fab); fab.setOnClickListener(new View.OnClickListener() { // クリック時の挙動を追加 @Override public void onClick(View view) { // 追加したいImageViewを生成 iv = new ImageView(MainActivity.this); iv.setImageResource(R.mipmap.ic_launcher); // 追加したImageViewの位置を指定 iv.setScaleType(ImageView.ScaleType.FIT_END); FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(android.widget.FrameLayout.LayoutParams.WRAP_CONTENT, android.widget.FrameLayout.LayoutParams.WRAP_CONTENT); lp.topMargin = 1200; lp.leftMargin = 850; addContentView(iv, lp); // 初期は非表示に変更 iv.setVisibility(View.GONE); DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); // クリック時のイベントにドロワーメニューの開閉を追加 if (drawer.isDrawerOpen(GravityCompat.START)) { // ドロワーメニューが開いた際に閉じる画像を非表示にする iv.setVisibility(View.GONE); drawer.closeDrawer(GravityCompat.START); } else { drawer.openDrawer(GravityCompat.START); // ドロワーメニューが開いた際に閉じる画像を表示する iv.setVisibility(View.VISIBLE); } } }); DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); ActionBarDrawerToggle toggle = new ActionBarDrawerToggle( this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close) { @Override public void onDrawerClosed(View drawerView) { iv.setVisibility(View.GONE); } @Override public void onDrawerOpened(View drawerView) { iv.setVisibility(View.VISIBLE); } }; drawer.setDrawerListener(toggle); toggle.syncState(); NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view); navigationView.setNavigationItemSelectedListener(this); // ドロワー開くボタン(三本線)を非表示 toggle.setDrawerIndicatorEnabled(false); 簡単に解説をしますと、 FloatingActionButtonに対しsetOnClickListenerを設定します。 そしてそこでOverrideするonCkickにてDrawerのOPEN,CLOSEを実行するようにします。 また下部でActionBarDrawerToggleとDrawerを紐付けているのはDrawerの状態を取得するonDrawerClosed,onDrawerOpenedを取得したかったためです。 表示上は不要なのでsetDrawerIndicatorEnabledにて3本線アイコンを非表示にします。 3.Drawerが閉じた時に開くボタンを表示 Drawerが画面を覆った際は、グレーアウトした画面右側の覆われていない箇所をタップするとDrawerが再度閉じます。 Drawer自体は既に多くのアプリに取り入れられていますので、UIとしてはかなりメジャーになっていますが 要件によっては明示的に閉じるボタンを表示させる必要があります(した)。 今回はドロイド君アイコンを、Drawarが閉じた際のみDrawarと同じ明るさでグレーアウト箇所右下に表示させています。 コードは↑のMainActivity.javaと共通していますのでそちらをご参照ください。 ここは何でつまづいたか言いますと、まず閉じるボタンをどこに定義するのが良いのかがわかりませんでした。。 予めlayoutファイルに記載しておくと、Drawerが開のいたタイミングでグレーアウトの中に入ってしまします。 かといってDrawerの中に入れると閉じるボタンの意味が半減してしまいます。 下のレイヤーはグレーアウトしつつ、欲しい画像のみ一番上のレイヤーに明るく表示する事が必要でした。 ということで、ここではonClick時に閉じるボタン用のViewを作成しています。 また、Drawerの状態変化に応じて (開→閉)の時→ボタンを表示 (閉→開)の時→ボタンを非表示 と切り替えています。 もう少し細かくDrawerの挙動ステータスを管理すれば、Drawerが動き始めた瞬間に表示を切り替える事も可能です。 感想 今更ながらのDrawerlayoutなのですが細かい部分は都度試行錯誤になりますので、今回に関してももっと綺麗に出来る部分があるのではないかと思います。 基本的には Googleが推奨しているデザイン を踏襲しながらサービス独自のデザインを実現するためには、何が簡単に出来て何が難しいのかを判断をできる様にしておく事が大切だと今更ながらに思います。
アバター
こんにちは、インフラストラクチャー部の沼沢です。 AWS の DNS フェイルオーバーの設定についての記事はたくさん出回っていますが、今回は Sorry ページに特化した設定をご紹介します。 以前、社内で AWS 上にシステム構築していた際に、例えば「急激なアクセス増で AutoScaling が間に合わないなどでユーザのリクエストに対して正常に応答できない状態に陥ってしまった時に “画面が真っ白な状態が続くこと” だけは避けたい」という要望を受け、最終手段的な位置付けで構築した Sorry ページ表示の仕組みについてご紹介させていただきます。 特段目新しい技術や情報ではありませんが、AWS にてサーバレスで高可用性な Sorry ページを構築する方法の参考になればと思います。 DNSフェイルオーバーとは? そもそも、DNS フェイルオーバーとはなんなのかを軽くご説明させていただきます。 ※DNS 自体の突っ込んだ説明はしませんので、ご了承ください。 DNS は、例えば example.com = xxx.xxx.xxx.xxx (Web サーバの IP アドレス) というように、"ドメイン名" と “実体サーバの IP アドレスなど” を紐付けています。 この時に、"xxx.xxx.xxx.xxx (Web サーバ)“ になんらかの問題が生じ、サービスを継続できない状態に陥った場合に、 example.com = yyy.yyy.yyy.yyy (別のサーバの IP アドレス) に自動で変更する仕組みを DNS フェイルオーバー と呼びます。 つまり、とあるドメインへのリクエストを受けているサーバなどで何か問題が生じた場合に、 ドメイン名は変更せずに、そのドメインへのリクエストを受ける先を変更する仕組み のことを言います。 AWS の Route53 には、この仕組みが予め用意されており、画面からポチポチするだけで DNS フェイルオーバーを簡単に設定できるようになっています。 サーバレスで高可用性な Sorry ページの仕組み では本題です。AWS の DNS フェイルオーバー機能を利用し、サーバレスな Sorry ページを構築します。まずは図で見ていただくとわかりやすいと思いますので、以下の構成図をご覧ください。 上図に記載の通り、AWS のサービスは以下を利用しています。 Route53 ELB + EC2など (サービス本体のシステム) CloudFront + S3 (Sorry ページのシステム) Route53 が ELB のヘルスチェックのステータスを確認し、ELB が正常と判断している時には ELB 側のレコード情報を、ELB のヘルスチェックで異常と判断されている時には DNS フェイルオーバーが発動し、CloudFront 側のレコード情報を、それぞれアクセス元に返します。 この構成のメリットとデメリット メリット ・サーバレス 今回のメインのメリットです。サーバレス=自分たちで管理・保守するサーバは存在しません。S3 や CloudFront が動いているサーバの管理・保守は AWS に丸投げできます。 = EC2 で構築する場合よりも、運用コストを大幅に削減できます。 ・高可用性 Sorry ページの HTML 自体は S3 に配置してあり、それを CloudFront でキャッシュさせて表示させるため、 サーバレスな Sorry ページ のシステムとなっています。 CloudFront, S3 の SLA は 99.9%以上 であり、高い可用性を簡単に実現できます。 ・正常時は Sorry ページシステムの維持費がほぼ0 本構成では、Sorry ページのために利用しているAWSのサービスは、 CloudFront と S3 の2つで、これらの料金体系は以下の通りです。(2016年2月現在) CloudFront データ転送量に対しての課金のみ -> 正常時はデータ転送が発生しないので $0 S3 データ保存容量に対しての課金 -> 最高値でも $0.033 データ転送量に対しての課金 -> In は全て $0 、Out は CloudFront への転送は全て $0 GET リクエストに対して課金 -> 正常時は GET リクエストも発生しないので $0 つまり、正常時の Sorry ページシステムだけのコストとしては、 $0.033 だけということになります。 デメリット ・Alias レコードは TTL を変更できない A レコードの Alias で ELB, CloudFront, S3 の何れかを指定した場合、TTL は 60 秒となり、こちらでは変更できません。 そのため、DNS フェイルオーバーが発動する前に、 最大で 1 分間は、絶賛障害発生中の ELB 側にトラフィックが流れてしまう ことに留意しなければなりません。 正確には、ELB が各インスタンスへのヘルスチェックで全台を Unhealthy と判定するまでの時間もプラスされます。 この間だけは、"画面が真っ白な状態” となってしまいますので、サービスの SLA 等をご確認の上、導入する必要があります。 各サービスの設定詳細 では、各AWSサービスの設定について、個々に解説していきます。 ELB + EC2 など (サービス本体のシステム) ELBやその配下のインスタンス等には、特別な設定は一切不要です。 S3(Sorry ページ置き場) S3 では以下の対応を行います。 Sorry ページ用の Bucket を作成 Bucket 名の決まりは特にありません 必ず Sorry ページだけのための S3 Bucket を作成してください (後述) Sorry ページの HTML を Bucket 直下に配置して Publish(公開)する クローラー対策として、以下の内容の robots.txt を Bucket 直下に配置して Publish(公開)する User-agent: * Disallow: / 以下の様な状態になっていればOK。 CloudFront(Sorry ページのキャッシュなど) 次に CloudFront です。 CloudFront では、以下の設定を行っていきます。 新規の CloudFront Distribution を作成 Sorry ページ用の Bucket を Origin に指定 [Alternate Domain Names] に、サービスのドメイン名を指定 今回は “dns-fo.mediba-lab.net” というドメイン名で設定し、設定後検証を行います。 作成した Distribution を選択し、[Error Pages] タブを選択 → [Create Custom Error Response] でカスタムエラーページを以下の通り定義 [HTTP Error Code] 403: Forbidden バックエンド(本構成の場合は S3)からのレスポンスコードが 403 の場合 [Error Caching Minimum TTL] 300 エラーを 300 秒キャッシュする [Customize Error Response] Yes レスポンスをカスタマイズする [Response Page Path] /sorry.html S3 の Sorry ページ HTML へのパス [HTTP Response Code] 503: Service Unavailable ステータスコード 503 でレスポンスする 上記を図で表すと以下の様なイメージです。 こうすることで、本体サイトのどんな URL でアクセスが来ても、Sorry ページを返却することが可能です。 また、Google などのクローラーに対しても 503 を返せるため、一時的なものであると認識させる事ができます。 この仕組の実現のために、前述した Sorry ページだけのための S3 Bucket が必要 となります。 実際に作成した CloudFront のドメインにアクセスすると、どんな URL をリクエストしても、503 で Sorry ページが返ってくることが確認できます。 Route53(DNS フェイルオーバー) 最後に今回のキモ、Route53 で DNSフェイルオーバーを設定します。 正常時のレコードを登録 以下のキャプチャのイメージで、A レコードの Alias で本体サービス側の ELB を指定 [Routing Policy] Failover DNS フェイルオーバーを利用 [Failover Record Type] Primary このレコードが Primary であると定義 [Set ID] Primary 任意の値 [Evaluate Target Health] Yes Alias(ELB)のヘルスチェックを利用する [Associate with Health Check] No 予め定義してあるヘルスチェックの利用有無 今回は ELB のヘルスチェックを利用するようしたので、No を選択 フェイルオーバー先のレコードを登録 以下のキャプチャのイメージで、A レコードの Alias で Sorry ページ用に作成した CloudFront を指定 [Routing Policy] Failover DNS フェイルオーバーを利用 [Failover Record Type] Secondary このレコードが Secondary であると定義 [Set ID] Secondary 任意の値 [Evaluate Target Health] No Alias に CloudFront を指定した場合は、No 固定 [Associate with Health Check] No Secondary 側なので、特にヘルスチェックは入れない 以上の設定で、DNS フェイルオーバーを利用した Sorry ページ対応が完了です。 動作検証 では、最後にこの設定がちゃんと動作するか確認してみます。 正常稼働状態の確認 予め用意してあったトップページ、exmaple ページがステータスコード 200 で正常に表示できました。 DNS フェイルオーバーの確認 では、EC2 上で起動している Apache を停止して、ELB 配下にインスタンスが1台もいない状態を作り、大規模障害が発生したと仮定しましょう。 [ec2-user@ip-xxx-xxx-xxx-xxx ~]$ sudo service httpd stop Stopping httpd: [ OK ] Apache 停止直後は、ELB が 504 を返してきています。 その後、数十秒程度で ELB が 503 を返すようになりました。 さらにその後、待つこと 1 〜 2 分程度で、S3 に置いた Sorry ページが表示されるようになりました! ステータスコードもしっかり 503 になっています。 DNS フェイルバックの確認 最後に、EC2 上で停止中の Apache を起動して、ELB 配下にインスタンスが存在する状態を作り、サービスが復旧したと仮定しましょう。 [ec2-user@ip-xxx-xxx-xxx-xxx ~]$ sudo service httpd start Starting httpd: [ OK ] Apache 起動後、同じく 1 〜 2 分程度で正常系のページが返ってくることが確認できます。 まとめ いかがだったでしょうか。この仕組みを自前で全て構築することを考えた場合に想定されるインフラコストや工数を考えると、かなりのコスト削減&開発期間の短縮に繋がるのではないでしょうか。 また、今回の構成はサーバレスというところが一番のキモで、サービスがリリースされた後の運用面のコストも大幅に削減できると考えています。 少々長くなってしまいましたが、Sorry ページに高可用性を求めている方々の参考になれば幸いです。
アバター
こんにちは。制作部デザイナーの斉藤です。 私の所属しているチームで約1年前から「デザインスプリント」が導入されました。 当時、セミナーなどで聞くようになったデザインスプリント。 短期間で効率的にアイデアがでてすごくいいらしい!との事なので、medibaでも実践してみることにしました。 「でも結構プロセス多いけど、本当に効率化するのかな?」と半身半疑でした。 初期段階のとりあえずやってみよう!というお試し期間を経て、現時点でまだ業務に最適なやり方を模索中ですが、今回は弊社で行っているプロセスをご紹介いたします。 デザインスプリントとは? Googleのベンチャー機関Google Venturesが、投資先に行っているフレームワークで、5日間かけて効率的、かつ高速にプロトタイピングと検証を行う方法論のこと。 詳細については以下をご覧ください。 Design Sprint ガイドブック v2 from Takaaki Umada 参照: THE DESIGN SPRINT 通常の工程はこちら Day0…Preapre(準備する) Day1…Understand(理解する) Day2…Diverge(発散する) Day3…Decide(決める) Day4…Prototype(試作する) Day5…Validate(検証する) 現在実施中のデザインスプリント(短縮版)の流れ 新サービス立ち上げやアプリ開発などはフルで実施するのが望ましいですが、普段私が担当しているランディングページなどページ数が少ないものでは結構な拘束時間となるので、通常5日間のプロセスをかなり短縮し約2日間に分けて行っています。 Day0 Preapre(準備する) 参加メンバーを決める(ディレクター・デザイナー・エンジニア)。 できればプロジェクトに全く関係ない人物やにも参加してもらうのも良いです。 ※制作内容・仕様書などはあらかじめディレクターに準備してもらいます。 必要な道具:コピー用紙、人数分のマジック、ホワイトボード、付箋 Day1 Understand(理解する)/ Diverge(発散する)/ Decide(決める) この3工程を1時間くらいで一気に進めてしまいます。 Understand(理解する) ファシリテーターの進行の元、目的(課題)とターゲットユーザーがどんな人物か具体的に考え、年齢・性別・趣味・目的などを挙げ、詳細なユーザーのペルソナを想像していきます。 そこからユーザーストーリー(4コマ漫画)を書記役の人がホワイトボードに書いていきます。 4コマ漫画について 本来カスタマージャーニーマップなど作成してユーザー動線やストーリーを検証するのが一般的ですが、簡略版のため簡単にみんなが理解しやすいように4コマ漫画にしています。 ここでのポイントは、漫画の面白さでなく、ユーザー体験としてどれが理想かをみんなで認識合わせするのが大事です。 この時は食べ物系特集のアイデア出しだったのですが、男女問わず幅広い年齢層で、美味しいもの好きな人に関心を持ってもらい、同僚に薦めたくなる様な内容を考えました。 Diverge(発散する) 前項で考えた内容を元に、サービスの目的はどうしたら達成されるかアイデアを出します。 通常は8つ捻出するのですが(これがなかなかツライ)、短縮版なので6つにしています。 1案あたり30秒 + インターバル10秒という短時間にアイデアを振り絞ります。 時間に制限があって焦りますが、追い込む事によって思いもよらないアイデアが出る事が多いです。 すべての案を書き終わった後、それぞれ補足説明をしていきます。 他の人の意外なアイディアも聞けるので個人的にはこの工程が一番楽しいです! Decide(決める) サイレント投票(おしゃべり禁止)は厳守です。 ターゲットユーザー・ストーリーとの整合性を確認しながらこれは!という案にペンでチェックを入れる、もしくはシールを貼って1人3つまで投票し、最も数の多かった案を採用します。 この特集の時は 高級感をだす 季節感のある背景をつかう 食材写真を背景にならべる 湯気、炎で美味しそうな効果をつける 人物が美味しそうに食べている写真をつかう おしゃれな雑誌風の写真をメインにつかう などいろいろなアイデアが集まりました。 最終的に一番票を集めたのは、おしゃれな写真をメインに使った、雑誌dancyuのようなイメージの案でした。 Day2 Prototype(試作する) ここからはデザイナーが単独で作業に入ります。 前回決まった案を元に、まずはラフ(手書きでも、デジタルでもイメージ伝わればOK)で プロトタイプを試作し、関係者に展開します。 Prott 、 POP などのプロトタイピングツールを使って実機でも確認します。 なお、ここでお互いにイメージや認識の違いがあった場合は随時調整します。 ラフが完成したら実際のデザイン作業に移り、完成を目指します! もうちょっと時間に余裕のある場合はこの後に Validate(検証する) という工程するのですが、現状なかなか実施できていません。 Validate(検証する)の工程はこんな感じです。 プロトタイプを作成した人が、カンタンに動作説明をする 全員でプロトタイプを触る ターゲットユーザーに近い、第3者に入ってもらうと更に良い Good or Request を3分間(案件によって可変)、付箋に記入 ホワイトボードに貼っていく グルーピングする Requestをどう取り入れるか議論し、本制作に入る 問題や課題が出てきたら、アイディア出し/試作の工程に戻って繰り返す Good or Requestというのは「いいと思うところ」と「こうしたらもっと良いかも」を付箋に書いて貼っていくフローです。(こちらは以前実施した時の様子) まとめ デザインスプリント導入前は、打ち合わせ1回目でメンバー全員の意識合わせが難しく、お互い認識の微妙なズレが生じてしまい、リテイク、もしくは作り直しが起こるという悪循環がしばしばありました。 デザインスプリントをやってよかったのは、プロジェクトに関わるメンバーでアイデアを出すことで閉鎖的にならず、決定も素早く、みんなで作ったという連帯感やプロジェクトに対する愛着が生まれる点だと思います。 さらに、今まで見えずらかったユーザーの姿がより具体的になる事で、情報がユーザーに届く精度もあがるのも素晴らしい点と言えるでしょう。 本来、プロトタイプ完成後にペルソナに近いユーザーテストをするのですが、現状できておりません。 しかし、ユーザーテストをすることで、さらに興味深い発見があったり、違った課題が見えると思うので、ぜひフローに加えて改良していきたいと思います。
アバター
こんにちは。制作部フロントエンジニアの苅部です。 GoogleからCloud Vision APIの提供が始まっていたので、スマートフォンのカメラから利用できるモック画面を作って、APIの画像認識精度を試してみました。 簡単ではありますが、HerokuでのNode.js利用のおさらいと、実際にいくつかの画像を送信した結果を共有できたらと思います。 (Cloud Vision APIは2/18日に 公開ベータ になっています) Cloud Vision APIとは GoogleフォトやSafeSearchで採用されている、Googleの機械学習の画像認識APIです。 画像を載せてAPIコールすることで以下の情報の取得が可能です。 物体検知 OCR 有害コンテンツ検知 顔検知 ロゴ検知 ランドマーク検知 HerokuでのNode.js利用までの流れ APIKEY取得からAPIコールおよび画面実装までの流れをご説明します。 今回は以下の要件で実装しています。 WEBサーバー: Node.js/Express4(Jade) プラットフォーム: Heroku クライアント: jQuery UIパーツ: OnsenUI WEBサーバー側もJavaScriptを利用しているので、フロントエンジニアの方ならDOM操作とちょっとしたAPIの仕様把握だけで短時間で実装ができると思います。 1. Developer Consoleへの登録・APIKEYの取得 GoogleのAPIを利用するにあたり、まずはDeveloper登録が必要になります。 1) GoogleのDeveloperアカウントを持っていない場合は取得します。 https://console.developers.google.com/ 2) 上記DeveloperConsoleからAPIKEY(サーバーKEY)を取得しておきます。 3) 以下URLからdocumentationの閲覧ができます。 https://cloud.google.com/vision/docs/ 2. Herokuへの登録と準備 Node.jsが利用可能で、ドメインも発行されるHerokuをプラットフォームとして選択しました。 MongoDBも簡単に扱う事ができますし、スピード感をもってモック作成するには最適なサービスだと思います。 ・ユーザー登録 Herokuのアカウントを持っていなければ登録します。 https://www.heroku.com/ ・Heroku Tool Beltをインストール Herokuをコマンドラインから利用できるようにします。 https://toolbelt.heroku.com/ ・Herokuへログイン $ heroku login 認証を求められるので、Herokuのid/passを入力してログインします。 ・Gitリポジトリの作成 $ cd my-project/ $ git init $ heroku git:remote -a [projectName] ・Procfileの作成 Procfileという名前で、プロセスの定義ファイルをプロジェクトルートに配置します。 今回の場合 Nodeでapp.jsというファイル扱うため、以下のような内容で設定しています。 node app.js 以上でHerokuを利用する準備が整いました。 3. Node.js側の実装 WEBフレームワークは Express/Jade を利用しています。 Node.jsのスクリプトは以下のような内容で[app.js]としました。 var express = require('express'); var bodyParser = require('body-parser'); var request = require('request'); var app = express(); var server = app.listen(process.env.PORT || 3000, function () { var host = server.address().address; var port = server.address().port; console.log('Example app listening at http://%s:%s', host, port); }); app.set('view engine', 'jade'); app.set('views', __dirname + '/views'); app.use(express.static(__dirname + '/public')); app.use(bodyParser.urlencoded({extended: false, jsonLimit: '3000kb'})); app.get('/', function (req, res) { res.render('index', { title: 'Cloud Vision API Test App' }); }); app.post('/api/cloudvision',function(req,res){ var image = req.body.image.match(/base64,(.*)$/)[1]; var reuestOption = { uri: 'https://vision.googleapis.com/v1/images:annotate?key=[APIKEY]', headers: {'Content-Type': 'application/json'}, json:{ "requests":[ { "image":{"content": image}, "features":[ {"type": "FACE_DETECTION", "maxResults": 5}, {"type": "LABEL_DETECTION", "maxResults": 5}, {"type": "TEXT_DETECTION", "maxResults": 5}, {"type": "LANDMARK_DETECTION", "maxResults": 5}, {"type": "LOGO_DETECTION", "maxResults": 5}, {"type": "SAFE_SEARCH_DETECTION", "maxResults": 5} ] } ] } }; request.post(reuestOption, function (error, response, body) { if (!error && response.statusCode == 200) { res.status(200).json(body.responses) }else{ res.status(200).json({ status: 'err' }) } }); }); — 補足 — jsonLimit: ‘3000kb’ bodyparserのデフォルト値が1MBのため、3MBへ増やしています。 ※ 画像認識の精度を上げるため可能な限り解像度は高い方が良さそうです。 ※ GoogleのAPI側では8MB/request,2MB/imageの制限がかかっています。 requestOptions.uri APIキー[サーバーキー]を含めたGoogle側エンドポイントです。 ※限定プレビューと公開ベータではURIが若干異なります。 requestOptions.json.requests.image base64エンコードした画像です。 requestOptions.json.requests.features 必要になる画像認識機能と件数を任意で設定します。 request.post() requestモジュールを使いGoogleへPOSTリクエストします。 4. クライアント側の実装 Node.js側で設定したURL[/api/cloudvision]に、画像を載せる形でPOSTリクエストを行い、レスポンスのJSONデータを整えて画面に表示します。 コードの記述は省略しますが、実装の要点は以下のようになります。 1) inputタグのaccept属性にcapture=cameraを追加する事で、モバイルブラウザでもカメラ/カメラロールから画像取り込みができるようになります。 <input type="file" accept="image/*;capture=camera"> 2) 取り込まれた画像をリサイズ/圧縮するために(2MB以内に抑えるために)jQueryプラグインを利用しました。 https://github.com/gokercebeci/canvasResize ユーザーがスライダーUIを操作することで、任意で画質のレベル調整ができます。 $('.input-range').change(function(){ var file = $('input[type=file]')[0].files[0] compressImage(file) }) function compressImage(file){ var compressLevel = Number($('.range').val()); $.canvasResize(file, { width: 610, height: 0, crop: false, quality: compressLevel, callback: function(data, width, height) { $(".image-preview").attr('src', data); } }); } 3) UIはOnsenUIを利用しています。(ボタンやスライダーの見た目を整えます) 5.アプリケーションのデプロイ リモート環境にアプリケーションをPUSHして、デプロイします。 $ git add . $ git commit -am "make it better" $ git push heroku master アプリケーションを動かす上で最低限必要なファイルは以下のようになります。 (staticなファイルは除く) ├── Procfile ├── app.js ├── package.json └── views └── index.jade 画面の表示 デプロイが完了したので画面を確認してみます。 iOSではカメラ/カメラロールから添付できることがわかります。 PCであればコマンドラインでブラウザを立ち上げ、アプリケーションを表示する事もできます。 $ heroku open 実際にリクエストを投げてみた結果 では早速手持ちの写真を送信して、Googleが画像をどのように認識しているか試してみます。 ※ ここで表示しているのはサムネイルですので、実際に送信している画像とは解像度や画質が異なります。 ※ レスポンスのJSONは見やすくするため、一部の値を削除しています。 Face Annotations (顔検知) 被写体がどういった表情をしているか、顔のパーツがどこにあるか、といった情報が取得できます。 Image Response “joyLikelihood”: “VERY_LIKELY” , “sorrowLikelihood”: “VERY_UNLIKELY”, “angerLikelihood”: “VERY_UNLIKELY”, “surpriseLikelihood”: “VERY_UNLIKELY”, “underExposedLikelihood”: “VERY_UNLIKELY”, “blurredLikelihood”: “VERY_UNLIKELY”, “headwearLikelihood”: “VERY_UNLIKELY” joyLikelihoodが"VERY_LIKELY"で返っていて、[楽しんでいる]という事が認識できています。 Text Annotations (OCR) 画像に写り込んでいる文字情報について、内容を抽出したり言語判定したりすることができます。 Image Response “textAnnotations”: [{ “locale”: “en”, “description”: “ ABOUT LIFE\n COFFEE BREWERS\n 1-19-8 DOGENZAKA SHIBUYA\n TOKYO JAPAN 150-0043\n TEL 070-5587-5342\n OPEN EVERYDAY 8:30-20:30\n www.about-life.coffee \n ”}] 誤りの無い文字情報が取得できました。 Label Annotations (物体検知) 物体の情報(ラベル)を、数千ものカテゴリの中から分類ができます。 Image Response “labelAnnotations”: [{ “description”: “ auto show ”, “score”: 0.99762589}], “labelAnnotations”: [{ “description”: “ ferrari f430 ”, “score”: 0.997009}] “labelAnnotations”: [{ “description”: “ sunflower ”, “score”: 0.97045457}] “labelAnnotations”:[{ “description”: “ hydrangea ”, “score”: 0.97828537}], “labelAnnotations”: [{ “description”: “ cyclo cross ”, “score”: 0.98051214 }, { “description”: “ cyclo cross bicycle ”, “score”: 0.96340382}], 1枚目の写真では自動車に限らず、[auto show]ということまで認識できました。 2枚目の写真はFerrariだけではなくF430という車種まで認識しました。 3,4枚目では花の種類をしっかり認識しています。 5枚目は自転車だけではなく、[シクロクロス]というところまで認識しました。 この画像でシクロクロスと認識できるのは、なかなか人間の知能に近いように思えます。 Logo Annotations (ロゴ検知) 商品や企業のロゴを検知できます。 Image Response “logoAnnotations”: [{ “description”: “ Lamborghini ”, “score”: 0.3002826, “boundingPoly”: { “vertices”: [{“x”: 72,“y”: 124}, {“x”: 105,“y”: 124}, {“x”: 105,“y”: 161}, {“x”: 72,“y”: 161}]} }], 車体の後方に映っているランボルギーニの猛牛のロゴが認識されました。 ※boundingPolyで位置の特定が可能です。 Landmark Annotations (ランドマーク検知) 自然構造物や位置情報の取得が可能です。 今回は位置情報が返却された画像のみをピックアップしました。 Image Response “description”: “Brooklyn Bridge” , “locations”: [{ “latLng”: { “latitude”: 40.705726, “longitude”: -73.996953}}] GoogleMap “description”: “ Broadway ”, “locations”: [{ “latLng”: { “latitude”: 40.783708, “longitude”: -73.97948}}] GoogleMap “description”: “ BFI Southbank ”, “locations”: [{ “latLng”: { “latitude”: 51.507032, “longitude”: -0.115935}}] GoogleMap “description”: “ Brick Lane ”, “locations”: [{ “latLng”: { “latitude”: 51.520466, “longitude”: -0.071496}}] GoogleMap “description”: “ Camden Lock ”, “locations”: [{ “latLng”: { “latitude”: 51.541274, “longitude”: -0.145536}}] GoogleMap “description”: “ Trellick Tower ”, “locations”:[{ “latLng”: { “latitude”: 51.523163, “longitude”: -0.205928}}] GoogleMap “description”: “ Nagawado Dam ”, “locations”: [{ “latLng”: { “latitude”: 36.132087, “longitude”: 137.719245}}] GoogleMap “description”: “ Hyōgo Prefectural Museum of Art ”, “locations”: [{ “latLng”: {“latitude”: 34.699125099999996, “longitude”: 135.218491}}] GoogleMap “description”: “ Consolidated city-county ”, “locations”: [{ “latLng”: { “latitude”: 35.688879, “longitude”: 139.69056129455566}}] GoogleMap “description”: “Haneda Airport” , “score”: 0.36270857, “locations”: [{“latLng”: { “latitude”: 35.578347, “longitude”: 139.784348} }] GoogleMap “description”: “ Tokyo Bay Aqua-Line ”, “locations”: [{ “latLng”: { “latitude”: 35.463999, “longitude”: 139.874554}}] GoogleMap どの写真でもDescriptionと位置情報が正確に返却されています。 ※アップロードした画像には位置情報に関するEXIFは含まれていません。 2枚目の写真はNYのBanksyのグラフィティですが、Googleは位置情報を正確に理解しているようです。 (GoogleMapのストリートビューでもグラフィティが確認できます) 3,4枚目はロンドンのグラフィティになりますが、これだけの写真でも理解できるようです。 それ以降の写真でも、無機質なダムの写真だけでも奈川渡ダムと判定されたり、らせん状のコンクリートだけで兵庫県立美術館と認識しました。 飛行機の写真は羽田空港と認識されています。位置情報も実際に撮影した場所から近く、どういったロジックなのかとても不思議です。 最後は、夜間の暗い写真ですがアクアラインとして認識される事が可能でした。 もしかすると、Googleは世の中に散らばっている画像やそれに含まれるEXIFの位置情報を照らし合わせて機械学習しているのかもしれません。 もしそうであれば 同じような構図が多く、位置情報が残るデジカメやスマートフォンで撮られているような写真(構図)が、ランドマーク(位置情報)検知されやすいのかも、、しれません。 まとめ 特徴的なレスポンスが返された画像だけを今回ピックアップしましたが、ここまで正確に、細かく認識できるのは驚きました。 RESTで提供されている画像認識APIは他にもMicrosoftの Project Oxford やIBMの Watoson がありますが、物体検知のカテゴリ数や認識精度で比較すると、今の段階ではGoogleの方が一歩進んでる印象があります。 最近Narrative Clip2を購入したのですが、Cloud Vision APIを使って大量の画像データをフィルターしたりなど、いろいろと妄想が膨らみます。 皆様も是非一度、Googleの画像認識のAPIを試してみて、使い道を検討されてはいかがでしょうか!
アバター
こんにちは。 mediba メディアシステム開発部の尾野です。 ついにブログを書く日がやって来ました・・・ 良い機会なので、ここ半年くらい気になっていた「Appium」を取り上げてみたいと思います。 ■Appiumとは? http://appium.io/ 概要 Appiumとは、Selenium作者のJason Huggins氏を中心に開発された デバイステスト自動化を実現するためのテストフレームワークです。 Appiumを使えば、実機/エミュレータを使ってEnd To Endテストが出来ます。 仕組み概要 PC上のテストプログラムを実行    ↓     ↑ PC上のAppiumから実機にリクエスト(Mobile JSON Wire Protocol) ※この時UI Automator用のアプリ等を端末に転送    ↓     ↑ 実機で動作 という流れとなってます。 UI AutomatorはAndroid OS 4.2以降(API Level 17以上)の場合です。 (Android OS 4.1以下の場合はSelendroid) テスト対象OS Android : Ver. 2.3.3以降 iOS : Ver. 6.0以降 特徴 実機テストができる 同じAndroidのバージョンでもメーカーによって微妙に挙動が違うことがあります。 その為多くの端末で検証をしなければならずひと苦労・・・ なんて事も多々あるかと思います。 Appiumでは機械的に実機のブラウザをエミュレートしたテスト出来るので、 人手による多端末検証の労力を抑える事が出来ます。 言語選択肢が多い ヘッドレスブラウズE2E(ex.PhantomJS)やrubyのCapybara等、 OSSのE2Eテストソリューションは沢山ありますが、言語の選択は制限されてしまいます。 Appiumでは執筆(2016/02)時点で以下の言語が使えます。 Java PHP Perl Ruby Python C# Javascript(Node.js) クロスプラットフォーム 実行環境はWinでもMacでもLinuxでもOK テスト対象環境は実機でもエミュレーターでもOK (iOSの場合はXcodeが必須なのでMac限定ですが・・・) Selenium WebDriverのナレッジを活かせる 自動E2Eテストの代表格でもある「Selenium」の拡張版、の様なものなので、 今までSeleniumでE2Eテストやってたという方なら入りやすいと思います。 準備 環境とか PC : Max OS X Yosemite(10.10.5) NodeJS v4.2.1 Homebrew経由でインストール Java(OpenJDK) v1.8.0_60 環境変数 JAVA_HOME 設定済み 実機 : Galaxy Note 3 (Android 5.0) テストコード 言語           :Javascript(Node.js) テスティングフレームワーク:mocha アサーション       :chai + assert(node標準) テストレポーター     :mochawesome 実機側設定 開発者向けオプションの「USBデバッグ」を有効にする必要があります。 開発者向けオプションを表示する方法 [設定] -> [一般] -> [端末情報] [ビルド番号]を7回タップすると「これでデベロッパーになりました!」のメッセージが表示され、開発者オプションメニューが表示されます。 USBデバッグを有効にする [設定] -> [一般] -> [開発者向けオプション] [USBデバッグ]にチェックをつける。 テスト実行中にロックが掛からない様にするため、 [スリープモード非設定]にもチェックをつけておいたほうが良いです。 インストール Android Studio ここからインストールします。 http://developer.android.com/intl/ja/sdk/index.html Configure -> SDK Manager -> System Settings -> Android SDK SDK Platformsタブ Android 5.0.1(対象端末が5.0なので) SDK Toolsタブ Android SDK Build Tools Android SDK Tools Android SDK Platform-Tools 環境変数を設定 $ vi ~/.bash_profile export ANDROID_HOME=[[Android Studioインストール先sdkフォルダパス]] export PATH=$PATH:$ANDROID_HOME/platform-tools/:$ANDROID_HOME/tools/ PCと実機をUSBでつないで、「adb devices」コマンドを実行 $ adb devices List of devices attached [[端末のUDID]] device # -> 識別NGの場合「List of devices >attached」と表示 《tips》Emulatorの作成・起動 今回は使用しませんが、Emulatorで動作確認をする場合には以下の手順で作成・起動します。 前述の「adb device」コマンドで作成したEmulatorのUDIDが表示されれば成功です。 $ android avd Android AVD Managerが起動する -> 「create」 $ emulator -avd [[AVD名]] Android Emulatorが起動する Appium インストールには2つの方法があります。 1)githubからgit cloneする https://github.com/appium/appium 2016年2月現在 v1.4.16 [メリット] Ver.はこちらのほうが進んでる ソフトウェアメンテナンスが容易 複数プロセス起動&実行が可能 [デメリット] git clone後のセットアップに時間が掛かる(mavenやantも必要) CUIベースになるのでコマンド使いはじめるまでに学習コストが掛かる インスペクタ(Nativeアプリの要素解析機能)が無い 2)デスクトップアプリをダウンロードする https://bitbucket.org/appium/appium.app/downloads 2016年2月現在 v1.4.13 [メリット] 必要なコンポーネント群が内包されている GUI付属 インスペクタ付属 [デメリット] Ver.はこちらのほうが遅れている 複数起動が出来ない 今回は2)の方法でインストールしたものを使います。 Appium.appを立ち上げるとこんな感じのツールが立ち上がります。 ①・・・各種設定 (左から) Android設定(後述) iOS設定 Appium本体の設定 開発者設定(Node.jsのパス変更等) Robot Framework用設定 ②・・・インスペクタ Nativeアプリの要素解析用ツール ③・・・appium-doctor Appiumが実行可能かどうかを検査してくれるツール 「✔ All Checks were successful」のメッセージが表示されれば実行可能 実行用設定 Android Capabilitiesブロック 「Platform Name」・・・Android 「Automation Name」・・・Appium 「Platform Version」・・・5.0 Lollipop ※Automation NameはAndroid OSのVer.が4.1以下(API Levelが16以下)の 場合に「Selendroid mode」に変更します。 実行 テスト対象 スマートフォン版スマートパスTOPページを対象にテスト実行してみます。 https://auone.jp/ 1)auone.jpにアクセス出来る事 2)正しくログイン出来る事 を検証してみたいと思います。 Appium起動 右上の「Launch」を押下すると・・・ 起動している感じがする・・・ テストコード(一部抜粋) 1)auone.jpにアクセス出来る事 it("TOPページアクセス", function() { return driver .sleep(10000) // 描画完了まで(念のため)時間とっとく // スクショを撮る .saveScreenshot(saveScreenDir + "TOPページアクセス") //ページタイトルが正しいか? .title() .should.eventually.include("auスマートパス"); }); 2)正しくログイン出来る事 it("TOPページからログインしてみる", function() { return driver // ログイン認可Cookie削除 .deleteCookie("【ログイン認可Cookie】") .elementByLinkText("ログイン").click() .sleep(10000) .saveScreenshot(saveScreenDir + "ログイン") // ログイン画面のタイトル検証 .title() .should.eventually.include("au IDログイン") // ID/PW入力 .elementById("loginAliasId").sendKeys("【ログインID】") .elementById("loginAuonePwd").sendKeys("【ログインPW】") .submit() .sleep(10000) .saveScreenshot(saveScreenDir + "[ログイン済]TOPページアクセス") // TOPに戻ってきた事をタイトルで検証 .title() .should.eventually.include("auスマートパス") // 認可Cookieの存在を確認してログイン済か検証 .allCookies() .then(function (cookies) { cookies.length.should.not.equals(0); for (var iii = 0; iii < cookies.length; ++iii) { if (cookies[iii].name === "【ログイン認可Cookie】") { return driver; } } assert.fail("doesn't exists 【ログイン認可Cookie】 cookie."); }) }); テスト実行 以下のコマンドを実行 レポート出力形式にmochawesomeを指定(–reporter mochawesome) レポートオプションに以下を指定 出力先: ./report/html/以下(reportDir=./report/html/) レポートファイル名:auonejp_test_sample(reportName=〜) レポートタイトル:auonejp_test_sampletitle(reportTitle=〜) 一枚完結ページにするか否か:inlineAssets=true $ mocha –reporter mochawesome \ –reporter-options \ “reportDir=./report/html/, reportName=auonejp_test_sample, reportTitle=auonejp_test_sampletitle, inlineAssets=true” \ appium_app_test.js Appiumコンソールにログが出力されています。 端末上のブラウザも起動し、以下の様に画面遷移してます。 テスト完了 テスト結果がターミナル上に表示 スクリーンショットもちゃんと撮れてます。 mochawesomeレポート html形式で出力されます。 テストケース2件とも成功しております。 詳細は以下参照 http://adamgruber.github.io/mochawesome/ 感想 Appiumはまだ触り始めて間もないですが、そこまで導入敷居も高くない様に感じました。 まだまだ実験段階なので、いつかのテスト自動化運用を見据えつつも、 ツールを過信しすぎない程度に継続的な調査をしていきたいと思います。 また、AWS Device Farmとも連携してみたりするともっと世界が広がりそうですね。 https://aws.amazon.com/jp/device-farm/
アバター
こんにちは。 2回目の登場になります、auスマートパス開発部の松本です。 多様化、複雑化するデータを使ったサービス開発の需要も高まっており、今回は使用感の調査もかねてグラフデータベースを触ってみました。 使用するデータベースは最もポピュラーであろうneo4jです。 書かれている記事も多く、とりあえず触ってみるのにはちょうどいい感じでした。 neo4jにはCypher (サイファー)というめちゃくちゃカッコイイ名前のクエリ言語があり、WEBインターフェースを使ってダイレクトにデータを処理することができます。 今回、何度も初期化を繰り返しながら試行することになるので、データの作成はRubyとneographyを用いることにしました。 初回ということもあり、データをグラフ化することに焦点を置いています。 LINK * neo4j * neography データを作成する ◼接続の確立 まず、接続を確立します。 require 'rubygems' require 'neography' @suma = Neography::Rest.new("http://ユーザ名:パスワード@localhost:7474") ◼ノードの作成 neographyのgithubのWikiを見ながら、ノードを追加していきます。 今回は特に使いませんが、プロパティには趣味(hobby)を持たせています。 node1 = @suma.create_node(name: "M君", hobby: "Video game") node2 = @suma.create_node(name: "A君", hobby: "surfing" ) ・ ・ ・ プロパティはあとから追加、変更できます。 @suma.set_node_properties(node1, {"hobby" => "FootBall"}) @suma.set_node_properties(node2, {"division" => "DevG"}) ノードを削除するのも簡単です。 @suma.delete_node(node1) ◼ラベルの追加 ここで、nodeのラベルに「Engineer」を追加します。 エンジニアをラベルにするかプロパティにするかちょっと悩みました。 ラベルにした場合   「Engineer」テーブルに各ノードが格納されるイメージ プロパティにした場合   ノードに「職業」という「属性」がつくイメージ この辺りは用途というか設計次第となるのでしょうが、今回は全員がエンジニアであることと後の抽出作業を考えて、ラベルにしました。 @suma.add_label(node1, "Engineer") @suma.add_label(node2, ["Engineer","1G"]) ・ ・ ・ ノードの登録が終わったところで、Cypherを用いてグラフ化してみます。 合計8名がノードとして登録されています。 ◼relationships(関係性)の追加 次に、グラフDBのキモである、 relationships(関係性) の記述を行います。 関係性には方向があります。friendsな関係とはいえ、一方通行でないとは限りません。 node2(A君)はnode1(M君)を友達だと思っているので以下のように記述します。 @suma.create_relationship("friends", node2, node1) この時点では、node2(A君)からnode1(M君)への一方向な関係線が引かれるだけです。 このままでは、友達とは言えません。 node1(M君)も、まあnode2(A君)を友達だと思っているので、引数を逆にして同様の記述を行います。 @suma.create_relationship("friends", node1, node2) グラフで見てみるとこんな感じです。 node1(M君)とnode2(A君)の間に「friends」が双方向で存在しています。 全てのノードに対して、関係性を記述していきます。 最終的にこんな形になりました。 これでデータの準備ができましたので、いろいろ抽出してみます。 データを抽出してみる ここまで作成したデータを用いて、いろいろ抽出してみます。 ◼A君を取り巻く人間関係は? A君の周りの全ての関係性を抽出します。 なかなか複雑ですね。 ◼A君「が」友人だと思っている人は? Aくんから出ている「friends」relationshipsのうち、外向きのものを抽出します。(双方向のrelationshipsを含む) ◼A君「を」友人だと思ってくれている人は? Aくんから出ている「friends」relationshipsのうち、内向きのものを抽出します。(双方向のrelationshipsを含む) 同じ 「friends」 という関係性でも、方向が違えば見え方も変わってきます。 この他に、「友達だと思っている人の友達」や「サッカーが好きな友達」なども抽出することができます。 「関係性」 に 「方向」 が加わることによって、 「friends」 という単語だけでは表しきれない関係が簡単に抽出できているのがわかると思います。 まとめ ほんの少し触っただけですが、「方向を表現できる関係性」を持たせられることがすごく便利でした。 「A君の友達の友達で趣味がサッカーの人を検索せよ」。これを例えばMySQLで実装しようとするとちょっと面倒な事になると思います。 (テンポラリ的な「友達テーブル」を作るとか) ◼︎関係性の表現について 今回はfriendsという単一のrelationshipsで方向のみを用いて関係性を表現しました。 ですが、関係性自体にプロパティを記述できるため、単に「知り合い」というrelationshipsを持たせ、そのプロパティに付き合いの深さを記述するやり方も考えられます。 また、方向性ごとに関係性の名前を変えるというやり方もあると思います。 一方通行:知り合い 双方向:friends! など。 どれが最適なのかは、まだまだ検討をしていく必要がありそうです。 今後は、RDBとの比較などもやってみたいと思います。
アバター
こんにちわ、情報システム部 佐藤です。 mediba で提供しているサービスは Amazon AWS のテクノロジ を利用したものが多いのですが、今回は Microsoft Azure を利用して業務系システムのメンテナンスを実施したお話です。 さて、 Azure File Storage が昨年末に一般提供されました。 最大の特徴は SMB 2.1 および SMB 3.0 に対応 していること。 これにより、オンプレからクラウド上の共有フォルダをマウントして利用することが可能です。 Amazon AWS の 場合 S3 バケットを直接マウントしてファイルシステムのように使うツールとして s3fs や goofys などがありますが、ツールを入れるのが躊躇される場合やお手軽に試したい場合に活用されては如何でしょうか? 今回は、PowerShell から Azure File Storage を作成し Windows Server のネットワークドライブとしてマウントして利用するところまでを試します。 準備 Azure アカウントの入手 こちら から入手できます。 PowerShell へのコマンドラインのアップデート こちら からAzure コマンドラインインターフェイスを入手できます。 Azure File Storage の用意 マウントするための共有ディスクを作成します。この作業は PowerShell が入っているクライアント端末であれば実行可能であるため、サーバーとは別の環境であらかじめ実施しておくのがお勧めです。 PowerShell ※ Azure アカウントと紐づけを行います。 PS C:\> Add-AzureAccount ※ サブスクリプションが複数ある場合は固定します。 PS C:\> Select-AzureSubscription -SubscriptionID:'subscriptionid' ※ 作成するストレージアカウントの名前チェックをします。 PS C:\> Test-AzureName -Storage hogehoge 詳細: The storage account named 'hogehoge' is already taken. True ※ True が帰ってくる場合は既に存在するため Flase となる名前を探します。 PS C:\> Test-AzureName -Storage mediba False ※ サブスクリプションで利用可能なロケーションを確認します。 PS C:\> Get-AzureLocation | format-Table -Property Name, storageAccountTypes 詳細: xx:xx:xx - Completed Operation: Get-AzureLocation Name StorageAccountTypes ---- ------------------- East US {Premium_LRS, Standard_LRS, Standard_ZRS, Standard_GRS...} ・・・・ Japan West {Standard_LRS, Standard_ZRS, Standard_GRS, Standard_RAGRS...} Japan East {Standard_LRS, Standard_ZRS, Standard_GRS, Standard_RAGRS...} ※ 利用可能なロケーションが返ってきます。この中から作成するロケーションを決めます。 PS C:\> New-AzureStorageAccount -StorageAccountName -Location 'location name' ※ 'location name'には先ほどの Japan East などを指定 ※ 作成したストレージアカウントにコンテナを作ります。 PS C:\> Set-AzureSubscription -SubscriptionID:'SubscriptionID' -currentStorageAccount 'アカウント名' PS C:\> New-AzureStorageShare 'コンテナ名' ※ 作成したストレージキーをこの後の処理で使いますので出力してメモなどに保存します。 PS C:\> Get-AzureStorageKey 以上で、Azure 側の準備は完了です。 Windows Server 側での共有ドライブのマウント Azure File Storage をマウントするためにはインターネットに向けて TCP 445 が開放されている必要があります。Range などを絞って開放する場合、 こちら の Microsoft の技術情報を参考にしてください。 コマンドプロンプト ※ 指定のドライブに共有フォルダとしてマウントします。 C:\>Net Use 'ドライブレター:' \\'アカウント名'.file.core.windows.net\'コンテナ名' /u:'アカウント名' 'ストレージキー' 以上で、Windows 側の共有フォルダとしてマウントすることができました。 見た目は、通常の共有ドライブと変わりありません。 Format は MAFS という特殊な 5TB の共有ディスクができあがりました。 使ってみた 作成した共有フォルダに早速ファイルをコピーして速度をチェックしてみます。 其の前にインターネットへのアップロード速度を計測しておきます。 現在の環境の上りの回線速度は以下のとおりでした。 20 Gbyte のファイルを移動してみました。 ほぼ、回線の上限値で推移をしていることがみれます。 約 30 分程度で移動をすることができました。 Japan East のロケーションを選択したからか、思った以上に速度がでます。 巨大なファイルを移動する場合は、帯域に注意が必要です。 まとめ ルーターから外部に向けて TCP 445 が開放されていることを確認しよう。 帯域には注意しよう。 Azure 上の仮想環境でも同様にマウントすることが可能です。 ファイルの仮置き、Azure 仮想環境への簡易移動など、ディスクイメージの退避などいろいろな用途で使ってみてはいかがでしょうか?
アバター
こんにちは。mediba制作部の大村です。 2016年1月6日に弊社でパパママ向けキュレーションサイト camily-β版- をオープンいたしました。 camily [キャミリー]|働くママとパパの仕事と育児をもっと自由に そこで制作したサービスロゴを用いて、基礎的な要点を交えロゴタイプの作り方を紹介します。 1. ベースとなるフォントを探す サービスイメージと合うフォントを探す フォントを洗い出したら同じくらいのサイズにして並べ、どれが読みやすいか、狙いと雰囲気が合っているか確認してみましょう。フォントを探すとき留意したい点は サービスイメージと合う ということ。予めサービスの特徴や理念を洗い出し、それを元に考え始めます。 サービス名 camily[キャミリー] ターゲットユーザー(作成当時) 未就学(0〜5歳)の子供を持つ仕事をしているママとパパ 特徴 月齢や年齢に応じて記事を出し分け 理念(サービスの意図) 仕事をしているからこそ出てくる育児の悩みを軽減してもらいたい ※ camily とは carrier[キャリア] と family[ファミリー] を繋げた造語になっており、これらが繋がってバランスが取れていてるイメージ(※課題1)と relief[安心] という意味も込めたい(※課題2)ので優しいイメージを表現したいという課題も。 ポイント 大文字小文字の組み合わせなどでイメージが変わるので、その点も加味して(または活かして)イメージを作成していきましょう。 (今回は先に 全て小文字 でサービス名をFIXしていたので、小文字のみでバランスが良くなるように注意しています。) 2. ロゴの表示サイズを確認 きちんとロゴを見せるために表示サイズを最初に決定する 実際デザインにはめてみると 「読めない!」「見えない!」「見辛い!」 ということが多々有ります。 サービスの対象機種やブラウザを確認し、最小サイズの機種でもきちんと見えるように、また、他のパーツも収まるようにロゴの表示可能領域を 予め確認 しましょう。 (主流と言われている最小サイズ《iPhone 4、4s 3.5インチ(320×480px、Device pixel ratio 2)》を最小とし、 最大シェアの画面サイズは《Galaxy Nexus 5 4.7インチ(360×567px、Device pixel ratio 3)》これをメインに意識します。 Device pixel ratio 3は非常に大きな画像が必要になるため、Webの場合は表示速度が落ちユーザー体験に悪影響を及ぼす可能性があります。 カンプ作成の際には作業効率も考慮しDevice pixel ratio 2(幅720px)に留め制作を進めます。 それを実機で確認できる環境を作り、確認しながらデザイン作成します。 ポイント ロゴを先行で作らなくてはいけない場合は大体のサイズを想定して、後々調整の必要があることをスケジューリングしましょう。 3. 400%にて作成開始 整数値で作成すると滲みの少ない表示になる 端末によってDevice pixel ratioが違うのでピクセルパーフェクトの実現は難しいのですが、極端に太すぎたり細すぎたりしないように実際自分が作りたいイメージを 逆算して作成 します。 整数値の表示になるよう心がけることでかっちりとした印象に仕上がります。実際配置する位置が1px以下でずれている場合多少滲みますが、それを考慮しないにしても意識しない場合と比べると滲みは少なくなります。 400%で作成すると表示サイズは1/4になるので線幅24pxの場合表示サイズは6pxとなります。 400%にした理由 デザイン時に拡大縮小する際に偶数の方が扱いやすい 自分の環境(iMac 27インチ)で角丸の度数などの細部をみたいところまで拡大できる ポイント 最終的にSVGデータ(ベクター形式のデータ)で配置すればかなり綺麗に表示されます。 これからもっと解像度の高い端末が発売されることも見越した施策です。 (ただし、IE8以下、Android2.3以下は対応してないので、対象機種を確認の上実施することをお勧めします。) 4. 文字を知る 読みやすい文字を作るための知識 デザインする際にどんな風に装飾をするか迷うと思います。古来から伝わる文字には様々な 意味や特徴 があり、フォントのどこがどのように特徴を表現しているのかを分析しながら作成することで、読みやすい文字表現を作成することが出来ます。 参考になる文字ルール 《 セリフ (serif) 》 タイポグラフィにおいて文字のストロークの端にある小さな飾りを意味する。セリフを持つ書体をローマン体と呼ぶ。 《 サンセリフ 》 セリフのない書体の総称。 《 永字八法 》 漢字の「永」の字には、書に必要な技法8種が全て含まれているという事を表した言葉。 側(ソク、点)、勒(ロク、横画)、努(ド、縦画)、趯(テキ、はね)、策(サク、右上がりの横画)、掠(リャク、左はらい)、啄(タク、短い左はらい)、磔(タク、右はらい)の八法。 5. 印象に残るロゴを目指す イメージに合わせてモチーフをプラス 「キャリアとファミリーが繋がっている感じ(※課題1)の アイキャッチ が欲しい」というオーダーが入りました。 今回は関係者内で協議の結果「バランスが取れてハッピーになる」というイメージで「やじろべえ」のモチーフを起用することに。 物理的に不自然にならないよう左の丸が大きくなっています。 ポイント モチーフもできるだけ正円を使うなどし、文字部分とのバランスをとりましょう。 6. 配布用データを作成 いつでもどこでも綺麗に表示してもらうために ロゴは媒体に配ったり、どこかに掲出してもらう機会もあり 一人歩きしがち です。 そんな時、カラーなどを明記したドキュメントとガイドラインがあれば是か否かハッキリし、 扱う人も迷わずに済む でしょう。 ロゴが見えなくなったり読めなくなったりしそうなケースは洗い出し、禁則の欄に追加していきましょう。許容を決めておくことも大事です。 まとめ 今回はWebサイトのサービスロゴ(しかもスマートフォンファースト)ということでタイポグラフィーを採用しました。 Webの場合ファーストビューで何が得られるかが重要です。 ファーストビューに説明的な記載があることでユーザーがサービスにたどり着くまでに時間がかかってしまいます。 時間がかかってしまうと離脱につながります。 離脱させないために、説明がなくてもファーストビューで 「読める・分かる」 を軸に制作することが必要なのです。 特にロゴはファーストビューの大部分を占めますので、制作の際は下記の、目的を明確にし、それらが達成できるように心がけることが大切だと私は考えます。 メディア(媒体) 例えば雑誌には雑誌にしか表現できない印刷技術、TVには動きも表現に加わるなど、説明の余地などが媒体によって違います。 ターゲット デザイン要素を大きく左右します。 コンセプト 全体のデザインとマッチさせ、より強固な印象付けを図ります。 ※camilyにおいては、丸みを帯びた優しい印象のロゴタイプに加えUIは柔らかい緑で統一し安心感を表現しています。(※課題2) 以上、「スマートフォンでもキレイに見える!タイポグラフィーから作るロゴデザイン」でした。
アバター
こんにちは、メディアシステム開発部の山浦です。 年が明けたばかりだし、なにか新しいことを始めたいと思いまして、β版から正式版になったAWS IoTを取り上げてみることにしました。 AWS IoTとは 昨年10月のre:Inventで発表され、同年12月に正式リリースされたAWSサービスの1つです。 IoTに特化しており、デバイス同士の接続やAWS SNS、DynamoDBなどと連携することができます。 これまでIoT環境を構築するには、メッセージブローカーの構築やセキュリティ対策などいくつものハードルがありましたが、AWSによってマネージドされたサービスとして提供されたことにより、IoTがより身近なものになりました。 AWS IoTとデバイスは、MQTTまたはHTTPSプロトコルを介して通信を行います。 気になる料金ですが、東京リージョンの場合 100 万通のメッセージあたり 8 USD と設定されています。 IoTとは Internet of Thingsの略です。 世の中の様々なモノがインターネットに接続する技術のことをさし、 第4次産業革命のキーワードともなっている、とてもホットな分野です。 目標 下記のような流れを実装し、AWS IoTがどのようなサービスかを知りたいと思います。 Arduinoで光量をセンシング センシング結果をAWS IoTにパブリッシュ パブリッシュされた結果をAWS SNSでメール送信 Arduinoとは 初心者でも簡単に扱えるマイコンボードのことです。 さまざまなセンサと組み合わせることで、周囲の環境を感知することができます。 開発にはArduinoIDEという開発環境が用意されており、コーディングからプログラムの書き込みまでを一括して行うことができます。 AWS SNSの準備 それでは手始めにAWS SNSの設定から始めたいと思います。 こちらを最初に登録しておく必要があるため、AWS IoTを触りたい気持ちをグッとこらえて設定を行っていきます。 1. Topicの登録 Topicを作成します。AWS IoTでこのTopicを呼び出すことになります。 2. Subscriptionsの登録 Subscriptionsの設定をします。目標がメール通知なので、Protocolにemailを設定し、送り先のメールアドレスを登録します。 以上でAWS SNSの設定は完了です。 AWS IoTの準備 いよいよ本題のAWS IoTを設定してきます。 大きく分けて4つの項目を設定する必要があります。 Thingの登録・・・デバイス自体の登録します。 Ruleの定義・・・デバイスから受け取ったデータを処理するルールを定義します。 Certificateの作成・・・証明書、秘密鍵、公開鍵を作成します。 Policyの作成・・・AWS IoTの各種操作を許可するためのポリシーを作成します。 各設定を順番に行っていきます。CLIから行う方法もありますが、今回はすべての設定をコンソール画面から設定してみます。 1. Thingの設定 Nameを入力し、Createボタンで登録完了です。 Thingの設定はこれだけです。 2. Ruleの定義 まずはRuleの名前を決めます。 次に受け取ったデータを処理するルールを定義します。SQLになっているので直感で理解しやすいのが特徴です。 TopicFilterに設定した【topic/test】を設定した場合、同一のトピック名でパブリッシュされたデータを、次で定義するアクションに受け渡します。 パブリッシュされたデータをどのように処理するか定義します。 SNSとの連携を行いたい場合、【Send message as a push notification】を選択します。 (他にも、DynamoDB、Kinesis、Lambda、S3、SQSと様々なAWSサービスが選択可能です。) 続いて、一番最初に設定をしたAWS SNSの SNS Topic と Role Name を指定したら、Add Action をクリックしアクションを決定します。 最後にCreateボタンをクリックします。 3. Certificateの作成 証明書と秘密鍵と公開鍵を生成します。 既存のCSRから鍵を生成することもできますが、【1-Click certificate】を使用することが推奨されています。 鍵と証明書が生成されるとダウンロードすることができます。 鍵はこのタイミングでしかダウンロードできないので、忘れずにダウンロードしておく必要があります。 4. Policyの作成 デバイスに対して、AWS IoTの各種操作を許可するためのポリシーを作成します。 今回は全ての操作を許可するように設定します。 図の赤枠を入力したら、Createボタンをクリックします。 5. Certificateの有効化とThing、Policyのひも付け 最後にCertificateにThingとPolicyをひも付け、有効化を行います。 この行程を行うことで先ほどダウンロードした証明書と鍵が有効になります。 以上でAWS IoTの設定は全て完了です。 Arduinoの準備 Arduino側の設定は大きく分けて3つです。 回路の作成 Arduinoに組み込むプログラムの作成 Arduinoでセンシングしたデータを受け取りパブリッシュするプログラムの作成 1. 回路の作成 Arduino単体で光量をセンシングすることができないため、外部に回路を作ります。 実際の回路はこのようになりました。赤枠で囲んだものが照度センサです。 センサが受け取った値をアナログ0番ピンで取得できるようになっています。 2. Arduinoに組み込むプログラムの作成 センサの値を出力するプログラムを作成します。 言語はArduino言語という、C/C++をベースにした独自言語で使用します。 serial.ino int val = 0; void setup() { Serial.begin(9600); } void loop() { val = analogRead(0); Serial.println(val/4); delay(1000); } アナログINの0番ピンからデータを受け取り出力します。 ArduinoIDEでコンパイルが通ったら、Arduinoに書き込んでおきます。 3. Arduinoでセンシングしたデータを受け取りパブリッシュするプログラムの作成 AWS IoTにパブリッシュするプログラムです。 MQTTで通信できれば言語の指定はありませんが、今回はRubyで書いてみました。 (Arduinoは単体で通信が行えないため、パブリッシュはPCを介して行います。) 前準備として、serialportとmqttというgemが必要なのでインストールしておきます。 mqttはRubyからMQTTプロトコルで通信を行うためのgem、serialportはシリアル通信をするためのgemです。 $ gem install mqtt $ gem install serialport serial.rb require 'serialport' require 'mqtt' # Arduinoで設定したポート port = '/dev/cu.usbmodem1411' sp = SerialPort.new(port, 9600, 8, 1, SerialPort::NONE) client = MQTT::Client.connect(host: 'YourEndpoint', port: 8883, ssl: true, cert_file: 'certificate.pem.crt', key_file: 'private.pem.key', ca_file: 'rootCA.pem') loop do sensor_val = sp.gets puts "Illuminance = " + sensor_val if sensor_val.to_i Illuminanceの値は、明 40 ~ 250 暗 程度の値を取るので、やや暗いところで実行したことが分かります。 Illuminanceの値が【50】を切った時にAWS IoTにパブリッシュされるので、明示的に光源を照度センサに近づけてみましょう。 値が小さくなっているのが分かるかと思います。 実際にパブリッシュされた文字列がメールで送信されているでしょうか。 届いていました! センシングされた値を基にパブリッシュされ、AWS IoTからSNS経由でメールが送信されたことが確認できました。 まとめ AWS IoTを初めて使用してみましたが、設定から稼働までとても簡単にできました。他のAWSサービスとの連携が予想以上にスムーズに行えたことに驚きました。 今まで時間をとられていた環境構築の悩みをAWS IoTが解消してくれたので、あとはアイディア次第で面白いものを作っていけると思います。 今回はArduinoを使いましたが、もちろん他のIoTデバイスも使用可能なので、今後も色々と試していきたいと思います。 みなさまもステキなIoTライフを!
アバター
明けましておめでとうございます!auスマートパス開発部の新井です。 medibaで提供しているサービスではDynamoDBを利用しているサービスがあります。 Q: Amazon DynamoDB とは何ですか? Amazon DynamoDB は、完全マネージド型の NoSQL データベースサービスであり、高速で予測可能なパフォーマンスとシームレスな拡張性が特長です。 https://aws.amazon.com/jp/dynamodb/faqs/ DynamoDBは、スループット容量を変更することができ必要なときに必要なだけリソースを利用することが可能です。 DynamoDB での制限について ただ、スループット変更にあたっては制限があり増やす場合には日に何回でも可能ですが、減らす場合には日に4回という制限があります。 また、増やしたスループットが適用されるまでにはデータ量やデータ構造によって数分から数時間かかるという注意事項もあります。 Q: テーブルのプロビジョニングされたスループットレベルを変更するにはどのくらい時間がかかりますか? 通常、スループットを減らす場合は数秒から数分、増やす場合は数分から数時間かかります。 追加スループットが必要になった時点でスループットを増加したり増加のスケジュールを立てたりすることはお勧めできません。スループット容量のプロビジョニングは、必要なときに確実に容量を確保できるようかなり前から行っておくことをお勧めします。 https://aws.amazon.com/jp/dynamodb/faqs/ DynamoDB での制限一覧 https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/Limits.html ユースケースに応じたデータストアの使い分け DynamoDBを利用する際には、ユースケースに応じて必要となるスループットが異なるケースがあるため他のデータストアと併用する案の検討が大事かと思います。 例 フロントエンド 訴求などによるスパイクアクセスにより特定の時間帯のみ高スループットが必要である バックエンド 日に一度だけ特定の時間帯に大量データを処理させるために高スループットが必要である 運用者が任意のタイミングで格納されたデータを集計/出力するために高スループットが必要である などなど 上記ケースの場合は、必要なときに都度スループットを変更することにより要求を満たすことは難しい状況となります。 また、バックエンドでのユースケースが実行されるタイミングでフロントエンドで利用しているテーブルのスループットを消費してしまうケースやバックエンドで利用するデータは、RDBMSで管理していたほうがデータを操作しやすいといった状況にもなります。 いつでも高スループット状態を確保できる状況であれば問題ありませんが、高スループット状態を確保しておくことにより費用面で課題が残ります。 そんなときには、DynamoDB Streams を利用することで別のデータストアへデータ同期することによりユースケース別に最適なデータストアの利用が可能となります。 データの流れイメージ DynamoDB と RDS の併用をした際にストリームデータを効率よく処理させるために着目したこと 今回紹介させて頂く事例は、DynamoDB から RDS へデータを同期する際に、DynamoDB Strems と lambda間で効率よく SQS へメッセージを格納する処理にてパフォーマンスをあげるために工夫/検証した内容を紹介します。 Amazon Simple Queue Service(SQS)は、高速で、信頼性が高く、スケーラビリティに優れ、十分に管理されたメッセージキューサービスです。SQS を利用すると、簡単かつコスト効率良く、クラウドアプリケーションのコンポーネントを切り離すことができます。 ※ 具体的な実装方法ではなく、パフォーマンス向上する上で着目したポイントの紹介となります。 ※ lambdaからRDSへ直接連携させるためにはセキュリティグループの開放などが必要となりセキュアではなくなるためSQSを経由しています。 ※ SQSからRDSへ効率よくデータを格納させる方法については触れていません。 着目ポイント1:DynamoDB Streams の Batch sizeについて DynamoDB Stermsを有効にする際には、「Batch size」という項目を指定可能です。 Batch size を 変更することによりパフォーマンスにどのような影響があるのでしょうか。 ※ Batch sizeで指定した値によって、ストリームデータが一度に処理される件数を指定することが可能となります。 着目ポイント2:lambda function から SQS へのメッセージを一度に送信する量について SendMessage と SendMessageBatchを使うことによりパフォーマンスにどのような影響があるのでしょうか。 ※ SendMessageは、一度に1件のメッセージを処理可能です。 ※ SendMessageBatchは、一度に10件までのメッセージを処理可能です。 着目ポイント3:lambda function の割当てメモリ量について lambda function の割当てメモリ量によりパフォーマンスにどのような影響があるのでしょうか。 ※ lambda function のメモリ割当て量を大きくすることで性能は向上するのですが、パフォーマンス検証をしている際に考慮すべきポイントがあったため着目ポイントとして取り上げています。 着目ポイントに焦点を当てたパフォーマンス結果について 以下の結果となりました。 DynamoDBへの書込は100TPS(トランザクション毎秒)にて書込処理を実施し、SQSへのメッセージ処理においても100TPSに近しい値がでることを目的として検証した結果となります。 ※ 利用したDynamoDBのテーブル構造、同期させる対象データ、lambda function等により異なる結果となるため、着目ポイントにおけるパフォーマンスがどのような相関関係となったかとして参照ください。 batch size message type 割当てメモリ量 SQSへの処理性能(TPS) 1 SendMessage 128MB 約6TPS 10 SendMessageBatch 128MB 約45TPS 20 SendMessageBatch 128MB 約50TPS 100 SendMessageBatch 128MB 約65TPS 10 SendMessageBatch 256MB 約77TPS 考えうる全ての組み合わせを試した結果ではありませんが着目ポイントを組み合わせることでパフォーマンスが向上することを確認できました。 まとめ 着目ポイント1:DynamoDB Streams の Batch sizeについて Batch size を上げることにより、一度に処理される件数が増えるためパフォーマンスが向上する。 上記結果には含まれていないのですが、極端にBatch sizeをあげることにより一度に取り扱うストリームデータの量が大きくなりすぎ着目ポイント3の割当てメモリ量を超えてしまい、ストリームデータが取り残されるという事象が発生しました。 ※ メモリ割当て量を増やすことで処理が実施されることは確認しました。 また、同様に極端にBatch sizeをあげることによりlambda functionの一度に取り扱うストリームデータ量が多くなりlambda functionのTimeout制限(デフォルト3秒)に引っかかりストリームデータが取り残されるという事象が発生しました。 ※ Timeout値を伸ばすことにより処理が実施される形となります。 ただし、lambda functionのTimeout制限は最大60秒となるため最大60秒以内に処理が完了するBatch sizeを指定する必要があります。 着目ポイント2:lambda function から SQS へのメッセージを一度に送信する量について SendMessageBatch にすることで、SQSへのメッセージ送信処理においてまとめてメッセージを送信することが可能となるためパフォーマンスが向上する。 注意点としては、batch sizeが 1の場合には、SendMessageBatchを利用したとしても一度に処理されるストリームデータは、1のためパフォーマンス効果はありません。 最低2以上に設定した場合のみ、SendMessageBatchを利用することでの性能向上が期待できます。 着目ポイント3:lambda function の割当てメモリ量について 割当てメモリ量を増やすことで、lambda自体の処理性能があがるため性能が向上する。 上記3つのポイントを処理をさせたい性能に合わせチューニングをすることでリアルタイムに近しい形でSQSへメッセージを格納することが可能かと思います。 最後に 今回紹介したパフォーマンスのチューニングポイントでは、SQSからRDSへもリアルタイムに近しい値でデータを同期させることは考慮できていません。 SQSからRDSへもリアルタイムに近しいデータを同期させるためには、SQSからのデータ取得間隔/Woker数、RDSへの書込性能などを考慮した上でチューニングを実施する必要がありますが、最終的にはDynamoDBにて確保する高スループット以上の書込性能をRDSで実現することは難しいと思われるためDynamoDBは、ユースケースに応じた利用することが大事だと思います。 DynamoDB Stremsについては、詳細な情報が公開されていない部分も多く、手探りで検証した結果となりますので 少しでも性能改善に役にたてれば幸いです。
アバター
新年明けましておめでとうございます。 本年もどうぞ宜しくお願い致します。 さて今回は制作部フロントエンジニアの苅部から、Charles(チャールズ)というアプリケーションをご紹介させていただきます。 このアプリケーションはHTTPプロキシを設定できるソフトで、通信の内容を覗いたり改変したりする事ができます。 日々のデバッグ作業に応用できますのでフロントエンジニアやディレクターの方、是非この機会に活用されてみてはいかがでしょうか。 Charlesを使ってできること デバッグで主に利用する機能は以下の4点です。 通信内容の詳細確認 通信内容の制御 帯域制御 スマートフォン実機でのデバッグ 設定方法 最初に、初期設定についてご説明します。 ※ ここではMacOS利用にて、スマートフォンがMacOSと同じネットワークに接続していることを前提とします。 MacOS CharlesのWEBサイトからダウンロードします。 https://www.charlesproxy.com/download/ Charlesをインストールします。 SSL通信も有効にするためSSLの証明書をインストールします。 SSL証明書の設定についてはオフィシャルのドキュメントを参考にしてください。 https://www.charlesproxy.com/documentation/using-charles/ssl-certificates/ スマートフォン Macと同じネットワークに接続し、HTTPプロキシを設定します。 サーバ/プロキシホスト名にはMacのIPアドレス、ポートはCharlesで設定しているポート番号(デフォルトでは8888)を指定します。 iOSの場合 Androidでの設定 ※ SSL通信を有効にするためには、MacOS同様に端末へ証明書のインストールが必要となります。 ※ 端末からネットワークへ接続するとMacOS側にダイアログで"A connection attempt to Charles…“というメッセージが表示されるので、[Allow]を選択して、端末によるアクセスを許可してください。 ※ Android2系ではプロキシ設定のできる機種が限られているようです。 デバッグ方法 機能ベースではイメージしづらいため、実際の利用シーン別に操作方法をご説明します。 1. スマートフォン実機でデバッグを行いたい 例えばスマートフォン実機/商用環境にて何か問題が発生していて、すぐにデバッグが必要な場合があるとします。 PCであれば、ブラウザの開発者ツールなどを利用してある程度デバッグをすることができますが、実機でのiOS/Android/WEBVIEWではその方法が取れない場合があります。 こういったケースでCharlesを活用をすることができます。 ここでは[Map Local]機能を使い、mediba.jpへのアクセスでアラートウインドウを表示してみます。 1) ブラウザのDeveloper toolなどで任意のURLを拾います ここでは https://www.mediba.jp/includes/js/jquery/jquery.js としました。 2) デバッグ用の代替ファイルを用意します hoge.jsというファイル名にて、alertを実行するscriptを用意しました。 3) Map Localの設定をします [Tool] から [Map Local]を選択します。 [Enable Map Local]をONにして[Add]を押します。 [Map From]の[Host]の箇所に先ほどのフルパスを貼り付けます。 この後、別の項目にフォーカスするとフルパスが個々の項目に分解されます。 [Map To]では先ほど用意した代替のスクリプトファイルを選択します。 以上の手順によって、 * https://www.mediba.jp/includes/js/jquery/jquery.js のレスポンスを * [/Users/hoge.js]の内容で返す といった設定が完了しました。 リロードを行うと、Macのブラウザでもスマートフォン実機でもアラートウインドウでhello worldと表示される事が確認できると思います。 レスポンスとして返ってきているものであれば、img,css,jsなど全てのファイルを書き換えることができます。 これによって"商用環境/スマートフォン実機にて、外部ファイルの影響で問題が起きている"といったような特殊な状況でもすぐにデバッグが可能になります。 location.reloadやlocalstorage、DOM Selectorを利用すれば事象の発生確率の確認くらいはできると思います。 ※マッピングがうまくいかない場合 Charlesによってマッピングされているファイルは独自のレスポンスヘッダーが付与されています。 うまくいかない場合は、対象のファイルにX-Charles-Map-Localヘッダーが付いているか確認してみてください。 2. 非同期のデータ(スタブ)を用意したい 前述の事例と同様にMap Localの機能を利用して、読み込むファイルをJSONなどにしておけば、JSでの非同期処理におけるスタブデータとしても利用ができます。 これにより、例えばバックエンドの実装が終わっていない状態でも、APIの仕様を決めておけばフロントでもある程度先行して実装することができます。 3. 通信のログを確認したい メインのビューには常にログが流れていきます。 実機でもログが取れるため、実際のリクエスト数がどのくらいでそれぞれのレスポンスにどのくらいのコストが掛かっているかわかります。 個々の項目では、Overviewやリクエスト/レスポンスのRAWの表示が可能です。 4. 通信速度をコントロールしたい [Throttle Setting]機能にて帯域を制御できます。 例えば通信速度を極端に下げることによってページローダー的な、ロードの状況に応じて消えてしまう要素を確認することができます。 また実際にどの段階でページが描画されるか、ログと照らし合わせて確認できるためボトルネックの発見に繋がります。 例えば外部ファイルロードによるレンダリングブロックのポイント(クリティカルレンダリングパス)を確認することができると思います。 私自身も過去のプロジェクトで、この機能でデバッグを行いAndroidWEBVIEWのパフォーマンスを改善していた事があります。 帯域設定は[Enable Throttling]をONにして、任意のPreset/帯域数値を指定するだけです。 SIM契約の多様化によって十分に速度が出ないユーザーもいるため、低帯域でのパフォーマンス改善も大切かと思います。 5. ヘッダの内容を変更したい [Rewrite]機能を使うことで、リクエストヘッダやレスポンスヘッダの内容を変更できます。 そのためリクエストでのcookieを変更して認証まわりのデバッグを行ったり、 レスポンスでのCache-controlやExpiresを変更してブラウザのキャッシュ周りのデバッグも可能になります。 ここではリクエストヘッダーのUserAgent変更を例にとって、設定手順をご説明します。 1) Rewrite Settingを表示 [Enable Rewrite]にチェックを入れ、その下の[Add]を押します。 2) ルールセットの名前を設定 任意の名前を設定します。AndroidのUAに変更するため、ここでは"Android UA"としました。 3) Locationsの設定 今回はワイルドカードで設定しました。全てのURLで有効になります。 4) Rulesの設定 Rewriteに関する細かい指定を行います。 [Type]: Rewriteの振る舞いを選択します。 今回は既存のヘッダの変更となるため[Modify Header]を選択しますが、ヘッダー追加/削除,クエリパラメータの変更/追加/削除も可能です。 [Where]: Requestを選びます(リクエストヘッダー) [Match]: NameにUser-Agentを入力し、全ての値を対象とするため[Match whole value]のチェックを入れます。 [Replace]: NameにUser-Agentを入力し、Valueに任意のUA Stringで設定します。 ここではAndroidのUserAgentを入力しました。 この設定により、[iPhoneやPCでアクセスしていてもUserAgentは一律Android]となります。 この状態で試しにGoogle検索をしてみます。 UAがiOSの場合の検索結果 UAがAndroidの場合の検索結果 Androidに変更した状態では、検索結果のアプリ一覧にAndroidアプリが出てきているので Rewriteがうまくいっている事がわかります。 注意点 Charlesはシェアウェアですが、起動してから30分間は通常利用ができます。 30分経過するとアプリケーションが強制終了しますが、再起動してまた30分間使うことが可能です。 通信のログは止めない限りは残り続けるため、継続して使うとメモリが圧迫されてCharlesが落ちることがあります。 まとめ これまで紹介したようにCharlesは簡単なGUIに必要十分な機能が備わっており、誰でも気軽にデバッグができるソフトだと思います。 用意されている機能を応用することで通常では難しいデバッグも簡単にできます。 また、問題の切り分けにかかる時間が短縮されるため、業務効率の向上に繋がります。 ライセンスも$50以下ですので、機能から考えるとコストパフォーマンスはとても高いように感じます。 https://www.charlesproxy.com/buy/ Charlesは新しいソフトではありませんが(私自身も3年くらい使っていますが)、もしまだ使われていなければ一度触ってみることをお勧めします!
アバター
こんにちは!メディアシステム開発部の杉本です。 今回は、11月末にトライアルリリースをしたauスマートパスアプリ向け検索連動広告で利用しているElasticsearchのCluster機能の設定について紹介をさせてもらいます。 Cluster機能を利用することで、可用性の確保、レイテンシの低減が期待できます。 Elasticsearchでは標準でmulticastの設定となっており、Cluster機能を使うのはさほど難しいことではありません。 ただし、AWSはmulticastに対応していないため、AWS上のMulti-AZ構成でCluster機能を利用するのには少し工夫が必要です。 その前に注釈 10月にリリースされたAmazon ESのお話はないです。 もう少し早く発表されてたら検証し採用してたかもですが今回は見送りました。 kibanaも関係ないです。 最近はElasticsearchの情報検索してもkibana情報が多くて閉口しちゃう。 まずは、簡単に広告商品の紹介 auのAndroid端末にプリインストールされているスマートパスアプリ向けの検索連動型広告です。ナンノコッチャ ですね。 こうして、こうするとでてくる、これです。 ※ 画面イメージは2015年12月時点のキャプチャとなります。 ※ 掲出される広告は検索ワードや案件状況によりかわります。 ※ iPhoneユーザーは Appleストア からダウンロードしてみて下さい。 広告品質やユーザーと広告との接触状況、キーワードとの広告コンテンツの適合度などなど様々な情報を元に掲出する広告を決めているのですが、このプロダクトでは「キーワードとの広告コンテンツの適合度」の判定にElasticsearchを利用することにしました。 ElasticsearchでのClusterの設定 前置きが長かったですね。それでは本題。 流石に本番環境は披露できないので、似たような環境をブログ用に用意してみました。 環境 AWS EC2 t2.micro インスタンス * 4台 Amazon Linux Elasticsearch 1.7 plugin elasticsearch-cloud-aws 2.7.1 (今回のキモとなるプラグイン) elasticsearch-kopf (確認用 head等でも可) Clusterの設定手順 ロールの準備 インスタンスの準備 Elasticsearchのインストール elasticsearch.ymlの設定 確認 ロールの準備 { "Statement": [ { "Resource": [ "*" ], "Action": [ "ec2:DescribeInstances" ], "Effect": "Allow" } ], "Version": "2012-10-17" } まずは、AWS上で上記インラインポリシーを持ったロールを作成して下さい。 自分は”EsDescribeInstancesPolicy”という名前のpolicyにしました。 インスタンスの準備 最終的には4台構成としますが、 まずはt2.microインスタンス1台を用意しAMIを取ります。 インスタンス作成時に気をつけなければならないのは、先ほど作成したロールを割り当てるのを忘れないようにする事ぐらいです。それ以外については、ポチポチしながら作成していって下さい。 セキュリティグループを設定するのであれば9200番ポートを開けるのを忘れずに。 Elasticsearchのインストール インスタンスが用意できたので、SSHでログインし、Elasticsearchをインストールしていきます。 今回はサービス化していくためにrpmでインストールしています。 rpm --import https://packages.elastic.co/GPG-KEY-elasticsearch vim /etc/yum.repos.d/elasticsearch.repo リポジトリの登録 [elasticsearch-1.7] name=Elasticsearch repository for 1.7.x packages baseurl=http://packages.elastic.co/elasticsearch/1.7/centos gpgcheck=1 gpgkey=http://packages.elastic.co/GPG-KEY-elasticsearch enabled=1 インストール yum install elasticsearch chkconfig --add elasticsearch clusterの利用とその確認に辺りプラグインを追加 Kopf(環境確認) /usr/share/elasticsearch/bin/plugin --install lmenezes/elasticsearch-kopf/master Elasticsearch-cloud-aws(自動clustering aws対応) /usr/share/elasticsearch/bin/plugin -install elasticsearch/elasticsearch-cloud-aws/2.7.1 elasticsearch.ymlの設定 設定ファイルはelasticsearch.ymlです。 通常であれば下記にあると思います。 vim /etc/elasticsearch/elasticsearch.yml clusterを利用するために必要な項目については下記です。 cluster.name: aws-cluster # node同士でクラスタ名は同じにする discovery: zen.ping.multicast.enabled: false type: ec2 cloud: aws: region: ap-northeast node.auto_attributes: true cluster: routing: allocation: awareness: attributes: aws_availability_zone 設定については以上です。 下記コマンドでElasticsearchを起動し service elasticsearch start http://xxxx.xxxx.xxxx.xxxx:9200/ へアクセスして、起動を確認してみてください。 ロールを設定することで、設定ファイルにsecret_keyを記載する必要もないのでよりセキュアな状態で構築できます。 1インスタンスでの設定を確認できたら、AMIを作成し、作成したAMIを元に4台のインスタンスを起動させて下さい。 確認 正常に設定が完了していれば後は確認するだけです。 http://xxxx.xxxx.xxxx.xxxx:9200/_plugin/kopf/ へアクセスをすると、下記のような画面が確認できるかと思います。 キャプチャから確認いただけるようにサンプルでは5つのshardに3つのreplicaをもたせる形でindexの作成を行いました。 設定については以上となります。 試しに、インスタンスを1台停止させてみてください。 下記のようにすぐにindexが再分配され、Cluster全体として問題なく動作していることが確認できるかと思います。 また、インスタンスを再起動させれば自動で対象のインスタンスを見つけ出し、indexが再分配がされたことを確認できるはずです。 このようにElasticsearchでは簡単にClusteringが行えるので、可用性の確保のためにも積極的に利用していきたいですね。
アバター
こんにちは。auスマートパス開発部の子安です。 最近すっかり寒くなりましたね。冬といえばコタツです。そしてコタツといえば双六。双六 -> サイコロ -> Redis。 ・・・はい、やっとたどり着きました。今回はRedisの話です。 全てのレコードを吐き出したい 今やKVSの代名詞と言えるほど使われているRedisですが、一つ困ったことがあります。 というのも、レコードを全てダンプするようなコマンドがないのです! みなさんどうしていますか? 素直なやり方 最初に思いつくのは、KEYSしてMGETかもしれません。 # export_by_keys.py r = redis.StrictRedis(REDIS_HOST) res_keys = r.keys() # KEYS if res_keys: res_mget = r.mget(res_keys) # MGET for key, val in zip(res_keys, res_mget): print(utf8(key), utf8(val)) >> 完全なコード これは手軽なのですが KEYS * は全てのキーを返しますので、レコードが多くなっていくとサーバ、クライアントともに問題が起きてきます。公式ドキュメントにも「普段使いは意図してないよ」とありました。 http://redis.io/commands/KEYS Don’t use KEYS in your regular application code. このドキュメントの続きにもある通り、こういった場合にはカーソルによって少しずつキーを取得していくSCANを使うのが作法です。 つまり次の手として考えられるのは、SCANとMGETですね。 # export_by_scan.py r = redis.StrictRedis(REDIS_HOST) next_cur = INITIAL_CUR while True: res_scan = r.scan(next_cur) # SCAN next_cur = res_scan[0] if res_scan[1]: res_mget = r.mget(res_scan[1]) # MGET for key, val in zip(res_scan[1], res_mget): print(utf8(key), utf8(val)) if next_cur == INITIAL_CUR: break >> 完全なコード このコードは問題なく動作します。が、SCANとMGETで2回ネットワーク越しにリクエストしているところが気になります。取得したキーをそのまま投げ直しているわけですから、ここは一括して処理できないものでしょうか。 Luaを使う そうかLuaを使えるじゃないか、と思って書いてみたのがこちら。 # export_by_lua.py r = redis.StrictRedis(REDIS_HOST) with open('scan_with_value.lua', 'r') as f: lua_script = f.read() scan_with_value = r.register_script(lua_script) # SCRIPT LOAD next_cur = INITIAL_CUR while True: res = scan_with_value([next_cur]) # EVALSHA next_cur = res[0] if res[1]: for key, val in res[1]: print(utf8(key), utf8(val)) if next_cur == INITIAL_CUR: break >> 完全なコード この中で読み込んでいるLuaスクリプトはこちら。 -- scan_with_value.lua local t_scan = redis.call('SCAN', KEYS[1]) if next(t_scan[2]) then local values = redis.call('MGET', unpack(t_scan[2])) return {t_scan[1], zip(t_scan[2], values)} else return {t_scan[1], {}} end >> 完全なコード やってることは同じくSCANしてMGETなのですが、Luaスクリプトはサーバサイドで動作しますので、クライアントからは一度のリクエストでキーと値のリストを取得できることになります。 比較してみる 1,000,000レコードを保持したRedisに対して実行してみます。 $ time python3 export_by_scan.py >/dev/null real 0m42.267s user 0m34.564s sys 0m2.384s $ time python3 export_by_lua.py >/dev/null real 0m46.726s user 0m35.100s sys 0m1.844s これは実はローカルに立てたRedisへ接続しているのでした。ローカルだと流石にあんまり変わらないですね。むしろ少し遅いぐらいです。 そこでリモートに同じく1,000,000レコードを保持したRedisを立てて、接続してみると・・・ $ time python3 export_by_scan.py redis-remote-host >/dev/null real 1m38.121s user 0m35.844s sys 0m2.780s $ time python3 export_by_lua.py redis-remote-host >/dev/null real 1m14.163s user 0m38.488s sys 0m1.864s 3/4程度の時間で処理を完了しました。ネットワーク次第とはいえ、充分有意な差が出たと思っています。 (おまけ)大量レコードの登録 吐き出すのではなく逆に投入する — 大量のレコードを登録する手順については、公式ドキュメントにガイドがあります。 http://redis.io/topics/mass-insert the preferred way to mass import data into Redis is to generate a text file containing the Redis protocol, in raw format, in order to call the commands needed to insert the required data. 要はプロトコルを流し込む仕組みがあるということですね。公式はRubyで書いてあったのですが、ついでなのでPythonで書きなおしてみました。 # to_redis_protocol.py def to_redis_protocol(*cmd): protocol = '' protocol += '*{0}\r\n'.format(len(cmd)) for arg in cmd: protocol += '${0}\r\n'.format(len(bytes(arg, 'utf-8'))) protocol += arg + '\r\n' return protocol >> 完全なコード まとめ 正直な話、全レコードをダンプする要件があるとしたら(そしてレコードが大量になるとしたら)、それは要件を考え直した方が良いかもしれません。なぜならその処理は必ずシリアルになり、スケールしないからです。SETイベントを通知して何らかの処理を入れるとか、Lua拡張で更新処理とともに何らかの処理を入れるなどの代案を検討すると良いでしょう。 それとLua拡張は面白いですよね。工夫次第でいろんなことができるので遊んでみてください。Luaの言語仕様もそれほど大きなものではありませんし、気軽に書けると思います。 今回使ったもの Redis 3.0.5 Lua 5.1.4 Python 3.4.3 / redis-py 2.10.5
アバター
こんにちは! mediba 制作部 メディアクリエイティブグループでデザイナーをしている高柳です。 最近、Webサイトやスマートフォンアプリの開発・改善を行うときのUIデザインツールとして、Photoshopやillustratorより Sketch を使うことが多くなってきているようです。 参考データ 2015 Subtraction.com Design Tools Survey 私も使い始めているのですが、便利機能が多くて使い易いのが魅力です。 今回は、そんなSketchについてご紹介したいと思います。 その1:デバイスに合わせたアートボード iPhone6を選択すると上の図の通り、アートボードが作成されます。 iPadやAndroid用アイコンを選択した場合は、それぞれ選択したデバイスに合ったサイズのアートボードが作成されます。 また、種類が多いためかAndroid画面サイズのアートボードはないですが、自由にサイズ登録して使うことができます。 その2:図形やテキストのスタイルを登録、シンボル化できる 図形やテキストのスタイルを登録して使い回せる テキストであれば、フォントの種類・色・サイズなどのスタイルを名前を付けて登録、管理できます。もちろん図形に関しても同様です。 登録してあるスタイルを図形やテキストに適用することで、一括でスタイルを変更することができてとても便利です。 よく使うアイコンやテキストたちをシンボル化 上記のスタイル登録と似た機能ではありますが、こちらはアイコンとテキストをまとめて管理できます。 例として、ページ下部のタブバーをシンボル化しました。 違うページを何枚もデザインしていると同じタブバーを繰り返し使うことになります。シンボル化することにより、デザインの変更が各ページに一括で反映されます。 その3:デバイスごとのパーツ書き出し機能 iOS解像度(dpi)ごとのパーツ書き出しが便利 スマートフォンアプリの場合、解像度(dpi)ごとにデザインパーツを書き出さなければならず、これがとても面倒です。 ですが、この機能を使うと2倍・3倍などの倍率を指定するだけで一瞬で書き出すことができます。 プラグインを使うとAndroidも書き出しも可能 Sketchのデフォルト機能にはAndroid用がないため、プラグインをインストールすると便利です。 iOSよりもAndroidの方が解像度の種類が多いので、ぜひプラグインを入れて使ってみてください。 その4:ダミーデータを入れるプラグイン 画像やテキストのダミーデータを入れるのは意外に面倒だったりします。 でも本物っぽいデータを入れてみないとイメージが湧かない・・・という時におすすめです! このプラグインを使えば、サムネイル用のシェイプや文章用のテキストエリアを作成すると、ダミーデータを挿入してくれます。英語だけでなく、日本語も対応しています。 その5:iPhoneに専用アプリを入れると作成中の画面を実機で確認できる Webサイトやスマートフォンアプリのデザインをしていると、実機ですぐに確認したいと思うはずです。 ですが、通常はデザインしたデータを書き出して、プロトタイピングツールなどにアップして・・・など少し手順が面倒だったりします。 しかし、このアプリは作成中のデータをリアルタイムに同期してくれるため、専用アプリをインストールしたiPhoneを用いることですぐに確認ができます。 その6:Prottと連携するプラグイン その5で紹介した専用アプリは有料です。 そこで、この専用アプリの代わりをしてくれる Prott との連携がとても便利です。 ほぼ便利機能その5と同じくリアルタイムに同期してくれる機能があり、そのままProttを使ってプロトタイプを作ることもできます。 Sketchを使ってみた感想 Sketchには下記のメリットがあります。 Adobe製品に比べるとお手頃価格 ¥11,800(2015年11月17日現在:App Storeでの金額) プラグインが充実している スマートフォンアプリ用パーツの書き出しが圧倒的にラク psdデータに比べるとデータが軽く、動作がスムーズ CSS で出来る装飾しかSketchで作れないという機能制限があるが、逆に実装できないデザインにならずに済む Adobe製品も最近はSketchのような機能を追加してきていますし、Adobe製品にしかできないこともまだまだあります。 ただ、使ってみた結果、 SketchはUIデザインに特化したツール だと感じました。 特にスマートフォンアプリのUIデザインをするならば、Sketchが便利ですので、みなさんもぜひお試しください!
アバター
はじめまして。 medibaメディアシステム開発部の原と申します。 現在はPHPフレームワークを活用して新メディアの開発を行っておりますが、以前はモバイル向け広告配信システムの開発や運用を行っていました。 今回は、広告運用の中でよく出てくる課題について、Chrome Extensionで解決する方法をご紹介したいと思います。 掲載期日より前に、表示した状態のイメージを確認したいんだけど? 広告運用でよくある課題として、 掲載開始前にプレビューできない ということがあります。 広告クリエイティブには世の中に出していない情報が含まれていることがあるため、モックと一緒にどこかにアップして確認という手段は採れないことが多いです。 ステージング環境もあるのですが、そもそも広告クリエイティブは直前まで差し替えが入ることもあるので、その度にいちいちステージング入稿して確認、では運用コストがかかり過ぎます。 そうだ、Chrome Extensionで本番環境の広告をローカル画像ファイルで(見た目だけ)上書きしよう! 前置きが長くなってしまいましたが、Chrome Extensionを使えば、画像ファイルをアップすることなく、さも掲載が開始されたかのような見た目を作れますよ、それで確認しちゃいましょう!というのが本稿の趣旨です。 Extensionの作成方針 さて、ではどのようなExtensionが必要でしょうか。 画像をどこかにアップする仕組みは使わない 本番環境なのでローカルに用意したスクリプトだけで実行可能 誰でも使えるようなインターフェース といったあたりが要件になってくると思います。 そこで、 popupでファイルをアップするフォームを提供 Web APIのFileReaderオブジェクトを利用してURLを作る 広告のsrcを、作ったURLで書き換えて見た目の上書き という設計方針を立ててみました。 ここまで決まればあとは作っていくだけです。 manifest.json { "name": "auスマートパス バナーシミュレーター", "version": "1.0.0", "manifest_version": 2, "description": "auスマートパスのTOPバナーをプレビューするためのツールです。", "permissions": [ "tabs", "http://*/*", "https://*/*" ], "browser_action": { "default_title": "バナーシミュレーター", "default_popup": "popup.html" } } ここでは特別なことはしていません。 ExtensionのポップアップHTMLから、元ページのソースを操作するのでpermissionsに"tabs"を設定していることと、アップロードフォーム用に"browser_action"の"default_popup"を設定していることがポイント。 画像アップロードフォーム(popup.html) <div class="cmenu" id="banmenu">バナーファイル選択</div> <div class="cbody"> <input type="file" id="newbanner"></div> <div class="preview" id="preview"><div class="innerpreview">preview</div></div> <div class="bottom"> <button id="sButton">変更する</button> </div> <script src="doPreview.js"></script> CSSとかは割愛。 バナーを選択するためのinput要素と、プレビュー領域(divが2重になっているのは枠線を描くためで深い意味はありません)を用意しています。 最後に処理本体を記述するスクリプトをコールして終了。 本体Script(doPreview.js) document.getElementById('newbanner').onchange = function() { var files = this.files; var imageType = /^image\//; for ( var i = 0; i = 0; i-- ) { previewImg.removeChild(previewImg.childNodes[i]); } previewImg.appendChild(img); var reader = new FileReader(); reader.onload = ( function(aImg) { return function (e) { aImg.src = e.target.result; }; })(img); reader.readAsDataURL(obj); } document.getElementById('sButton').onclick = function() { if ( document.getElementById('newbanner').value.length != 0 && !(!document.getElementById('banner'))) { changeTopBanner(document.getElementById('banner').src); } } function changeTopBanner(url) { chrome.tabs.executeScript(null, { "code": "var newBannerUrl = '"+url+"';" },function(){ chrome.tabs.executeScript(null, { "file": "changeBanner.js" }); }); } 長いですね。 内容的にはそれほど難しいことはしていないので、function単位で簡単に。 document.getElementById('newbanner').onchange = function() { var files = this.files; var imageType = /^image\//; for ( var i = 0; i = 0; i-- ) { previewImg.removeChild(previewImg.childNodes[i]); } previewImg.appendChild(img); var reader = new FileReader(); reader.onload = ( function(aImg) { return function (e) { aImg.src = e.target.result; }; })(img); reader.readAsDataURL(obj); } 今回のキモその1。 渡された画像ファイルについてWeb APIのFileReaderオブジェクトを使って動的にプレビューする機能を提供しています。 FileReader.readAsDataURL()メソッドを利用して、画像ファイルのバイナリから、base64 エンコーディングされた data:URL文字列にすることが出来ます。 どこにもアップせずに画像ファイル自体を文字列としてimgタグのsrc属性にセットすることが出来るわけです。 参考 developer.mozilla.org document.getElementById('sButton').onclick = function() { if ( document.getElementById('newbanner').value.length != 0 && !(!document.getElementById('banner'))) { changeTopBanner(document.getElementById('banner').src); } } ここは特記することはありません。 フォームのボタンを押したら元ページの画像差し替えFunctionを叩くよ、というだけ。 function changeTopBanner(url) { chrome.tabs.executeScript(null, { "code": "var newBannerUrl = '"+url+"';" },function(){ chrome.tabs.executeScript(null, { "file": "changeBanner.js" }); }); } 今回のキモその2。 ExtensionのpopupからロードされるScriptでは、元ページの要素にアクセスしたり操作したりということが出来ません。 そうした操作を行いたい場合はchrome.tabs.executeScriptメソッドを使います。 chrome.tabs.executeScriptを使用するとき、"code"で生JavaScriptを直接書くことも出来ますし、複雑な処理をしたい場合は、別ファイルにまとめて"file"で呼び出すことも出来ます。 またそれらを入れ子にすることで、元ページにJavaScript変数を定義した上で、外部ファイルで実行されるScriptから参照する なんてことも可能です。 今回はパラメータとしてURLを渡す必要があったのと、こういう書き方ができるよ、という意味合いでこの入れ子構造で書いてみました。 参考 developer.chrome.com 元ページ側で実行されるScript(changeBanner.js) var d = document.getElementById('banner'); d.src = newBannerUrl; 差し替えたいバナーのDOMを取得する。 事前に渡した変数でsrc要素を書き換える。 以上! 今回の処理内容の場合、先ほどのchrome.tabs.executeScriptに直接コードを書いてしまってもいいのですが、例えばif文やループなどを使用したい場合は、ファイルに記述する必要がありますので覚えておくと便利です。 ともあれこれで完成です。 では実際に動作させてみましょう。 実行してみる 作ったExtensionをChromeに読み込ませる 「Chrome設定」→「拡張機能」→「デベロッパーツール」のチェックをオンにして先ほど作ったExtensionを読み込みます。 Extensionの導入にはセキュリティ上制限がある環境も多いかと思いますので、ここは皆様自身の環境のポリシーと相談してから実施してください。 ページを表示してExtensionを起動 プレビューしたいページをChromeに表示させてから、Extensionのアイコンをクリックして立ち上げます。 今回はアイコンを定義していないので、デフォルトのパズルピースですね。 フォームから画像を選択 プレビュー領域を確認し、差し替えを実行 フォームから画像を選択すると、プレビュー領域が自動で書き換わりますので、間違いないか確認した上で、「変更する」ボタンで差し替えを実行します。 ちなみにこの時Chromeデベロッパーツールで画像のソースを確認すると…… data:URL文字列で画像が表示されていることがわかります。 差し替えの確認 変更し、Extensionを閉じると…… このとおり、バナーが差し替わりました。 バナーの色味はイメージ通りでしょうか? 広告として適切な目立ちかたになっていますか? 思う存分プレビューしてください。 注意事項 上に紹介した各APIについて、ブラウザのバージョンによっては(といっても相当古いブラウザでもサポートしていますが)サポートされていなかったり動作しない可能性があります。 各リンク先に対応ブラウザのバージョン記載がありますので念のためご確認ください。 なお、本稿執筆にあたって動作確認をしたブラウザはChromeバージョン 46.0.2490.86になります。 また、FileReaderオブジェクトの仕様は現在W3C標準化過程のWorking Draft(WD, 草案・草稿の)の段階です。 今後仕様が変わることは十分にありえますのでご注意ください。下記に本稿執筆時点の最新ドラフトドキュメントをご紹介します。 参考 http://www.w3.org/ 終わりに 今回の記事について、お気づきになった方もいるかと思いますが、スマートフォンの実機では利用できない仕組みになります。 というかモバイル版ChromeではExtension機能自体が実装されていませんし、その予定もないとのこと。 ですが、data:URL文字列でどこにもアップされていない画像を扱う、というキモだけおさえておけば、例えば画像をdata:URL文字列に変換するツールと、GETパラメータで画像のsrc属性を書き換えるJavaScriptを仕込んだモックを組み合わせることでスマートフォン実機でのプレビューも可能です。 結構面白い仕組みだと思うのでぜひ色々な活用の仕方を模索してみてください。
アバター
こんにちは。auスマートパス開発部の曽根です。 エンジニア採用の面接をさせていただく機会があるのですが、よく質問いただく内容として、 ・組織の技術力を上げるためにどんな取り組みをしているか? ・エンジニア同士のコミュニケーションや、知識の共有を促進する取り組みは? といったようなものがあります。 働く場所の一候補としてこのブログに興味を持ってくれる方もいるかと期待し、今回はmedibaでのエンジニア活性化の取り組みのひとつを紹介させていただきます。 Developer’s Community 毎週2回(30分)の時間を取り、「なにか発表したい人が発表する」場です。 登壇者も参加者も自由。 題材も ・こんなの使ってみた ・作ってみた ・セミナーに参加したので内容共有 など様々です。 私は先日過去のシステムと現在のシステムをいくつか比較しながら、主にキャッシュの使い方に関する変遷をまとめ発表しました。 こんなことも それなりにがんばって準備をし、発表もまずまず上手くできたかなよかったな、などと思いつつ胸を撫で下ろし安心していた発表の翌日でした。 弊社のCTO、山田からのメッセージが。 「昨日の発表なかなかよかった。今度社外で勉強会やるから登壇してみない?」 あ、これは断れないやつだ。そう思いました。 というわけで、やってきました。 参加した企業は、 ・ScaleOut ・CYBIRD ・connehito ・innova ・TSUMIKI ・Lancers ・eureka ・mediba (敬称略) 場所はサイバードさんのかっこいいシアター。 社長やCTOもいる豪華な登壇者。緊張しました。 いいたかったこと 嫌々やらされたように書いていますが、「やってよかった」と思ってます。 「うまくしゃべれた」とは思っていません。 「新しい自分が〜」ともまだ思えません。 それでも資料を作りながら、ああでもないこうでもないと考えたり、ここはこう話そうとシュミレーションしてみたり、貴重な経験ができました。 自分が担当しているシステムを他の人にわかるようにまとめることで、あらためて見えてくる課題や発見もありました。 普段は画面とにらめっこ、または会議をしていることがほとんどですが、たまには違う視点で仕事をしてみることもいいことです。 medibaでは、「エンジニアよ外に出ろ」のモットー(今考えました)の元、様々なコミュニティやセミナーへの参加を推奨しています。 スキルを伸ばしたいエンジニアの方々に少しでも興味を持っていただければ幸いです。
アバター
はじめに mediba インフラストラクチャー部の杉山です。 AWS WAFについて軽く触れてみたので簡単なレビューを行いたいと思います。さらに攻撃や防御の手法なども踏まえ、WAFが生まれた背景についても触れてみます。 攻撃手法 便利なインターネットですが残念ながらこの界隈には悪意ある人がたくさんいて、 黎明期より彼らから身を守る技術が培われてきました。まずはどんな攻撃方法があるのかを列挙します。 XSS(クロスサイトスクリプティング) フォースフル(強制的)ブラウジング インジェクション(SQL、メタキャラ、OSコマンド) パラメータ改ざん HTTPレスポンス分割 セッション管理情報改ざん バッファオーバーフロー バックドア、デバッグオプション エラーコード参照 ユニコード及びURLの符号化による検知回避 詳しい説明は避けますが、直接機密情報を閲覧、改ざんするもの、誤動作でそれらを実行できるようするものがあります。エラーコードですら攻撃者にぜい弱性を推測される情報となったりします。 防衛手段 上記攻撃から身を守る術をまとめます。と言っても選択肢は多くなく、地道にコードや実行ファイルの修正を行うしかありません。オープンソースなコードであればサードパーティや有志が作ったセキュリティパッチを適用することで回避できますが公的な意味ではコードの修正と同義です。 すべてのぜい弱性に対してリアルタイムに対応することは出来ないので多くは下記のようなプロダクトを使います。 Firewall IPS WAF アンチウイルス/マルウェアソフト Firewall, IPS, WAFの違い アンチウイルス/マルウェアソフトを除けばどれも似たような機能を持っていますが違いを説明します。 Firewall 通過するリクエストの送信元や送信先のIPアドレス、プロトコルを見てリクエストを制御します。古くからある技術ですが、アプリケーション層の情報を見ることはできない為、XSSやSQLインジェクション等の攻撃を防ぐことはできません。 IPS Firewallの穴を埋める技術としてIPSが生まれました。IPSは定義された検出パターンに基づいて様々な攻撃を検査することができます。しかし、これでもパラメータやセッション管理情報の改ざんなどWebアプリケーションに特化した攻撃を防ぎきることができません。 WAF そこでWAFの登場です。WAFは、IPSと非常に動きが似ていますが、Webアプリケーションの動作を理解しているため、より細かい防御が可能なことと、SSL通信の中身を見ることができるのでSSL通信に隠ぺいされた攻撃も防ぐことができます。 そんなWAFも先日、ついにAWSで利用できるようになりました。少し触ってみましたのでその情報をまとめます。 AWS WAFの概念 AWS WAFは[condition], [rule], [ACL]という3つの概念があります。conditionが最小概念で、そのうちのいくつかがまとまってruleが構成され、出来上がったruleをどう処理するかをACLで定義します。最小概念であるconditionから説明します。 condition 条件です。「このIPアドレスからの接続」, 「User-Agentに○○が含まれている」などの条件を指定します。 rule 複数のconditionをand条件で指定します。上記conditonで例えれば「このIPアドレスからの接続」且つ「User-Agentに○○が含まれている」というようなルールを作成できます。 ACL 作ったruleに対してどういう処理をするのかを定義します。[Allow], [Block]. [Count]が指定できます。またruleにマッチしなかったリクエストをどうするのか(全許可か全拒否の二択)を指定します。 作成例 [medibaのGatewayアドレス]、且つ[ブラウザがChrome]からの接続のみ許可するというACLを作ってみましょう。 AWSのサービス一覧から[WAF]を選択し、[Get Started]をクリックします。 ウィザードに従い、まずはACLを作成することになります。適当なACL名を入力して[Next]をクリックします。 conditionの作成は一旦スキップします。何もせずに[Next]をクリックしましょう。次にruleを作成します。[Create rule]をクリックすると以下の画面が表示されますので適当なrule名を入力して[Create]します。 あとでruleの詳細を設定しますが、ruleにマッチしたリクエストは許可(Allow)し、マッチしないものは拒否(Block all requests that don’t match any rules)します。 [Confirm and create]をクリックします。 conditionを設定します。まずはIPアドレスから。[IP Addresses]をクリックし、[Create Condition]をクリックします。 適当な名称を入力してIPアドレスを指定し、[Create]をクリックします。medibaのゲートウェイアドレスを指定するわけですが、この画像の情報はダミーです。 次に[ブラウザがChrome]という条件を定義します。[String matching]をクリックし、[Create condition]をクリックします。 適当な名称を指定し、上から順に、[Header], [User-Agent], [Contains], [None], [Chrome]を指定します。その後[Add anoher filter]をクリックし、[Create]をクリックします。 ruleにconditionを組み込みます。[Rules]を選択、冒頭で作成したRuleをクリックし、[Edit rule]をクリックします。 先ほど設定したconditionを以下のように組み合わせ、[Update]をクリックします。 これでACLが完成しました。CloudFrontに組み込んでみましょう。なお、S3とCloudFrontの設定は割愛します。 条件を満たさない状態でアクセスすると以下のようにリクエストがブロックされたことが分かります。 AWS WAFを触ってみて WAFはCloudFrontのオプションとして動くので、セキュリティグループとは違います。セキュリティグループはEC2上で動くソフトウェアFWという位置づけで、FWとWAFの違いは上記で述べた通りです。 AWS WAFの機能は割とシンプルなので、少し触ればすぐに理解できるようになると思います。オンプレミスのWAFは高価なので、AWSのマネージメントコンソールから気軽に触れるようになったというのは、取っ掛かりとしては非常に良いと思います。 ただ、その分細かい制御はできない(特にマッチ/アンマッチしたルールをリダイレクトできないことは確認済み)ので、現段階では、WAFの機能を最大限に利用したいならサードパーティ製品を考えた方が良いかもしれません。 AWSは常に進化しているので、利用者が増えればその意見を反映し、いずれその性能差は埋まっていくのではないかと思いますのでそこに期待です。 セキュリティのトレンド 本検証の過程で、とあるセキュリティベンダに以下のようなことを伺いました。 マルウェアは年々増加の一途を辿り、マルウェア作成ツールまで出て、知見のない人でも簡単に作れる 昔はWindows主流だったが、今ではLinuxが主流(個人を狙うよりもある程度の規模のサイトを狙った方が影響範囲が大きく、攻撃者にとっては都合が良い) なので、冒頭でも触れましたが、PCでは主流のアンチウイルス/マルウェアソフトを現在はサーバ機にも入れることがトレンドになりつつあるらしいです。WAFすら通り越してしまった攻撃を本当の瀬戸際で防ぐというわけですね。こちらはオンプレに限らずAWS(のEC2)にも対応しているとのこと。会員情報を格納しているサイトや決済サイトでは必須になりつつあるのかもしれません。 おわりに Web業界はスピード重視で攻めの姿勢が非常に重要ですが、脇をつつかれて失速しないように、守りの技術も磨いていかなければなりません。どちらも同じくらい大事ですがそのバランスも大事です。今後も新しい情報や技術があればキャッチアップして公開できればと考えております。 よろしくお願いします。
アバター