TECH PLAY

株式会社mediba

株式会社mediba の技術ブログ

200

こんにちは。 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業界はスピード重視で攻めの姿勢が非常に重要ですが、脇をつつかれて失速しないように、守りの技術も磨いていかなければなりません。どちらも同じくらい大事ですがそのバランスも大事です。今後も新しい情報や技術があればキャッチアップして公開できればと考えております。 よろしくお願いします。
mediba制作部 メディアクリエイティブグループ所属、フロントエンジニアの土方です。 Webページの制作および成果物の監修を担当しております。 jQueryでAjaxリクエストした際のレスポンスヘッダーについて、getAllResponseHeaders()で取得しようとした時、同一ドメインでは取得でき、クロスドメインの場合には取得できないヘッダーがあります。 今回、この件について紹介させていただきます。 ヘッダーの相違 仮に http://www.example.jp/index.html からAjaxリクエストするものとします。(※jQuery1.8以降の場合のコードです。) 同一ドメインの場合 リクエスト $.ajax({ type: 'HEAD', url: '', cache: false, }).done(function(data, status, xhr) { console.log(xhr.getAllResponseHeaders()); }).fail(function(data, status, xhr){ console.log('error!'); }); 結果 Date: Tue, 27 Oct 2015 05:53:29 GMT Last-Modified: Mon, 17 Jun 2013 10:28:48 GMT Server: Apache/2.2.29 ETag: "2744725-39-4df570fdaf800" Content-Type: text/html Connection: Keep-Alive Accept-Ranges: bytes Keep-Alive: timeout=5, max=19 Content-Length: 57 クロスドメインの場合 リクエスト $.ajax({ type: 'HEAD', url: 'http://api.example.jp/', cache: false, }).done(function(data, status, xhr) { console.log(xhr.getAllResponseHeaders()); }).fail(function(data, status, xhr){ console.log('error!'); }); 結果 Last-Modified: Mon, 26 Oct 2015 04:04:22 GMT Content-Type: text/html Cache-Control: max-age=86400 Expires: Wed, 28 Oct 2015 05:44:37 GMT DATE Server ETag Connection Accept-Ranges Keep-Alive Content-Length クロスドメインの場合には、上記ヘッダーを取得できていないことがわかります。 環境 下記環境について、取得できるヘッダーが制限されることを確認しました。 Xperia Z2 (Android4.4.2 標準ブラウザ) Xperia Z3 (Android5.0.2 標準ブラウザ) Infobar C01 (Android2.3.5 標準ブラウザ) Android版Chrome 46.0.2490.76 iPhone6 (iOS8.1.3 Safari) iPhone版Chrome 46.0.2490.73 Mac版GoogleChrome 46.0.2490.71 Mac版Safari 8.0.8(10600.8.9) Mac版Firefox 41.0.2 記事投稿時点(2015年11月6日)において、事実上全ての環境と考えて差し支えないでしょう。 Ajaxリクエストし、レスポンスヘッダーを取得する場合にはクロスドメインであるかどうかを意識する必要があります。 備考 Javascriptでレスポンスヘッダーを取得する場合とは? 例えばこんな理由が考えられます。 閲覧日時によって表示やアニメーションなどの効果を切り替える 掲示板などで投稿からの経過時間を計算する などの用途で、Javascriptで時刻を取り扱いたいことがあります。 Javascriptはクライアント側で動作するので new Date(); とするとクライアントに設定されている時刻を取得するため、 クライアントの時刻が狂っている 場合には狂った時刻を取得してしまいます。 サーバー時刻であればクライアントの時刻設定に依らないため、これを取得することで正確に近い時刻を使用することができるわけです。 NTPサーバーが提供しているjson(Ex. NICTのjson )から時刻を取得できれば話が早いのですが、一般に公開されているNTPサーバーは負荷に耐えられる保証はありませんし、なにより商業利用はできません。 また予算や工期の都合で、自前でNTPサーバーを用意することが困難な場合があります。 NTPサーバーが使えないのであれば、レスポンスヘッダーからDATEヘッダーを取得すればサーバー時刻を使用できる ということになります。 このような場合、クロスドメインなサーバーへAjaxリクエストしてもgetAllResponseHeaders()でDATEヘッダーの値を取得することは出来ません。 同一ドメインなサーバーへアクセスして取得する必要があります。 ソースコードについて (※)古いVer.では下記。 $.ajax({ type: 'HEAD', url: '', cache: false, success: function (data, status, xhr) { console.log(xhr.getAllResponseHeaders()); }, error: function(data, status, xhr){ console.log('error!'); }, });
まえがき mediba メディアシステム開発部 ポイント開発Gの佐藤禎章と申します。スマートフォン向けのネイティブアプリを構築/運用しています。 今回のエントリでは Apache Cordova の上で Vue.js を利用して Amazon AWS の機能を呼び出してみます。 利用するプロダクトの紹介 Apache Cordova http://cordova.apache.org/ もともと Adobe のプロダクトで、 PhoneGap と言われていました。 Apache に寄贈されて名前が変わりました。 アプリの構築を HTML + CSS + JavaScript で実現してしまおう、というぶっ飛んだ発想ですが、[アプリの中にブラウザを含めてしまい、その中で HTML / JavaScript / CSS を動かす]という手法で実現しています。なので、ブラウザで出来ることは大概、出来ます。 また、マルチプラットフォーム対応も特徴で、 iOS / Android / WindowsPhone / Firefox OS / Blackberry などなど、様々なプラットフォーム向けにネイティブアプリとしてビルドできます。 ネイティブアプリ特有の機能(カメラやGPSなど)については、プラットフォームごとにプラグインという形で実装することで、その差異を吸収しています。 ガチガチのゲームであったりスマートフォンの細かい機能を操作したりするような用途には向きませんが、カバーできる範囲は想像以上に広いです。 Vue.js http://jp.vuejs.org/ JavaScript の MVVM フレームワークです。つい先日、 1.0 がリリースされました。 MVVM とは Model - View - ViewModel という考え方で、 Model はデータそのもの、 View は見た目の定義。 ViewModel のところが、 Model と View の双方を結びつけて管理してくれる、みたいな仕組みです。 Model ←→ ViewModel ←→ View View の側で状態が変わってもちゃんと Model に反映してくれるし、 Model の側で状態が変わっても View の側にちゃんと反映してくれるので、動きを見てて面白いです。 今回、見た目の定義と非同期でのデータ更新に利用します。 AWS SDK https://aws.amazon.com/jp/sdk-for-browser/ みんな大好き Amazon AWS のサービスをプログラム言語から弄るためのキットです。 今回は AWS SDK for JavaScript を使用し、 Cognito と S3 を利用します。 本来ブラウザから動かすものですが、 Cordova でもちゃんと動くのかどうか。 準備 npm が実行できる環境を用意して下さい。 Mac であれば brew install node で npm の環境もまとめて導入できます。 Cordovaのインストール 下記のようにして、 npm から cordova をインストールして下さい。 $ npm install -g cordova これで cordova コマンドツールが利用可能になります。 このコマンドツールを利用して、アプリケーションの骨格作成からビルドまで行います。 アプリのスケルトン作成 まず、ベースを作ります。パッケージ名などもこの時に指定します。 $ cordova create cordovatest jp.mediba.ysato.cordovatest CordovaTest cordova create [ディレクトリ名] [パッケージ名] [アプリケーション名] という指定の仕方です。 指定したディレクトリの下に、こんな感じでファイルが生成されます。 続いて、プラットフォームを追加します。 ここで追加したプラットフォーム分、アプリケーションがビルドされることになります。 $ cordova platform add ios $ cordova platform add android 追加できるプラットフォームについては、下記を参照下さい。 Firefox OS とか Blackberry とかも対象に出来ます。 https://cordova.apache.org/docs/en/4.0.0/guide/support/index.html アプリを実行 実行する時は、コマンドラインから下記のようにします。 $ cordova run cordova run だけで引数を指定しないと、有効になっている全てのプラットフォームにて動かそうとしてくれます。先の例であれば、 Android と iOS ですね。 $ cordova run android などと指定すれば、そのプラットフォームの分だけ、ビルド/実行してくれます。 cordova create しただけの状態でターゲットを iOS として run すると、こんなサンプルが動きます。 ようこそ、 Cordova の世界へ。 JS外部ライブラリをCordovaで使う では早速、アプリを作ってみましょう。 但し AWS 関連についてはちょっと置いておいて、ここでは[誕生日を指定したら、今日から30日後までのバイオリズムをグラフで出力する]というアプリを作ってみます。 グラフ出力には ccchart を使用します。データをJSONで羅列するだけで美麗なグラフを描いてくれる、便利なライブラリです。 コード <script src="./js/vue.min.js"></script><ul id="biorythm"><li>誕生日: <input type="date"></li> <li>身体: {{physical}}</li> <li>感情: {{sensitive}}</li> <li>知性: {{intel}}</li> </ul><canvas id="biograph"></canvas><script src="./js/biorythm.js"></script> // 誕生日設定フォーム部分と更新処理 var biorythm = new Vue({ el: '#biorythm', lazy: true, data: { birthday: '1976-03-30', physical: 0, sensitive: 0, intel: 0, }, methods: { // 今日のバイオリズムデータで更新 // 引数 : 誕生日 update: function(){ birthday = biorythm.birthday; var bio_today = new Bio(birthday,new Date()); biorythm.physical = bio_today.physical; biorythm.sensitive = bio_today.sensitive; biorythm.intel = bio_today.intel; update_chart(birthday); } } }) // DOM変更を検知 biorythm.$watch('birthday', function(value, mutation){ biorythm.update(); }); // ccchart のグラフ定義 // data: に描画する要素を配列で指定する // ccchart.init(キャンバスID, 定義データ) で実際にグラフを描画する var chartdata6 = { "config": { "width": 320, "height": 240, "xScaleFont": "100 6px 'Arial'", "yScaleFont": "100 6px 'Arial'", "hanreiFont": "100 6px 'Arial'", "colorSet": ["#F00","#0F0","#00F"], }, "data": [[],[],[],[]] }; // ccchart グラフデータ(今日から30日後まで)の更新 // 引数 : 誕生日 function update_chart(birthday){ chartdata6.data[0].length=0; chartdata6.data[0].push("日"); chartdata6.data[1].length=0; chartdata6.data[1].push("身体"); chartdata6.data[2].length=0; chartdata6.data[2].push("感情"); chartdata6.data[3].length=0; chartdata6.data[3].push("知性"); for(var i=0;i<30;i++){ var today = new Date(); var dateChart = new Date(today.getTime() + i * 1000*60*60*24) ; var dateChartBio = new Bio(birthday,dateChart.getTime()); chartdata6.data[0].push(dateChart.getDate()); chartdata6.data[1].push(dateChartBio.physical); chartdata6.data[2].push(dateChartBio.sensitive); chartdata6.data[3].push(dateChartBio.intel); } ccchart.init('biograph', chartdata6); } // バイオリズム計算 // 引数 : 誕生日 , 基準日 function Bio(birthday,basedate){ dateDiff = (new Date(basedate) - new Date(birthday)) / 1000/60/60/24; dateDiff = Math.floor(dateDiff); var bioNumer = 2 * Math.PI * dateDiff; this.physical = Math.round( Math.sin( bioNumer / 23 ) * 10000) / 10000; this.sensitive = Math.round( Math.sin( bioNumer / 28 ) * 10000) / 10000; this.intel = Math.round( Math.sin( bioNumer / 33 ) * 10000) / 10000; } // 更新処理を一回走らせてグラフを書かせる biorythm.update(); 結果 DOM 操作やイベントハンドリングまでやる Vue.js や、 Canvas 描画ゴリゴリやる ccchart も、 Cordova の中で問題なく動きました。本当に何の問題も起きなかったので、逆に驚きました。 全く同じファイルを Google Chrome などで表示しても、やっぱりちゃんと実行できます。凄いものですねえ…. Vue.js について 今回 Vue.js には、下記の役割を担ってもらいました。 誕生日を指定するフォームの値を監視し、変更されるたびにイベントを発行する 第一引数に監視する要素、第二引数がコールバックになるので無名関数で処理を書く、みたいな使いかたになります。 vm.$watch('datakey', function(value, mutation){ // codes }); vm という Vue オブジェクトにおいて vm.$watch で datakey を監視させます。 変更が発生すると、 value に値が入り、 mutation には変更に関する情報(method, args, result, inserted, removed)が入ります。 今回は Vue.js の中に書いたメソッドを呼び、更新処理を走らせています。 誕生日の変更によって再計算される[身体][精神][知性]のバイオリズム値を画面に反映する <div id="vm">{{parts}} <script type="text/javascript"> var vm = new Vue({ data: { parts: 0, } } </script> こんな風に定義してあげると、Vue.js が HTML 側の {{parts}} と JavaScript 側の vm.parts を結びつけてくれます。 こうすると、 JavaScript側で vm.parts = 1 などとして値を変更した時に、 HTML 側を自動で書き換えてくれるわけです。 フォームに関してはちょっと特殊で、 <input> などと v-model というディレクティブを使用する必要があります。 ccchart について 解説するような所はあんまりないのですが、 ccchart でグラフを書くためにすることは、ざっくりと下記になります。簡単。 HTML 内にグラフを描画する canvas を用意する グラフの内容とデータを定義した JSON を用意する 描画処理を呼び出す http://ccchart.com/ にはグラフの種類や実際の書き方などについて、サンプルコードと実行例が豊富に並んでいます。 株価情報みたいなチャートを出したりリアルタイムに情報ソースをポーリングしたりと様々なことが出来ますので、まずはサイトの方を覗いてみてください。 AWS SDK for JavaScriptを使う 事前の注意 iOSに限った話なのですが、 ATS(Application Transport Security) という機能がiOS に加わり、その副作用として http アクセスが全部 https に差し替えられるため、 AWS の API アクセスも全て https に差し替わる *.amazonaws.com の証明書がSHA-1なので、セキュリティレベル低いとアクセスをブロックされる という事象が発生します。結果、 iOS 上の Cordova から AWS SDK for JavaScript を使用出来ない状態になります。 https://mobile.awsblog.com/post/Tx2QM69ZE6BGTYX/Preparing-Your-Apps-for-iOS-9 http://dev.classmethod.jp/smartphone/iphone/ios-9-intro-ats/ 回避方法は、 Cordova が生成した iOS 向けビルド用のソース一式の中にある、 info.plist を編集し、当該ドメインのATSを無効にすること。 但し、 Apple が用意したセキュリティの仕組みを迂回する、セキュリティレベルを下げることになるため、よく理解した上で使用して下さい。 NSAppTransportSecurity NSExceptionDomains amazonaws.com NSThirdPartyExceptionMinimumTLSVersion TLSv1.0 NSThirdPartyExceptionRequiresForwardSecrecy NSIncludesSubdomains 前準備 Cordova から外部のリソースにアクセスする際は、 Content-Security-Policy にてアクセス先の指定を行う必要があります。ホワイトリスト形式ですね。 Cordova が生成してくれた HTML には基本的なポリシが既に記載されていますが、外部サーバのリソースなどを利用したい場合は、随時許可を書いてあげる必要があります。 Amazon AWS へのアクセスを許可する場合は、下記のようになります。 <meta content="connect-src https://*.amazonaws.com/"> JQuery などをCDNから読み込むようにする、外部のデータをリソースとして使用する、等の場合にも、 Content-Security-Policy は通るようにしておいてあげないといけません。 Content-Security-Policy の詳細については、下記サイトを参照下さい。 http://content-security-policy.com/ コード <div id="s3list_vue"> <ul><li> </ul></div> <script src="./js/awssample.js"></script> var loginCognito = function(){ AWS.config.region = 'us-east-1'; AWS.config.credentials = new AWS.CognitoIdentityCredentials({ IdentityPoolId: 'us-east-1:xxxx' }); } var getS3Buckets = function(){ var filelist = []; var s3bucketname = 'BUCKETNAME'; var s3 = new AWS.S3({region: 'ap-northeast-1', maxRetries: 15}); s3.listObjects({Bucket: s3bucketname}, function(error, data) { if (error) { console.log("S3 Error : " + error); } else { var targetNode = document.getElementById('s3list'); for(var i = 0 ; i < data.Contents.length ; i++){ var params = {Bucket: s3bucketname, Key: data.Contents[i].Key}; s3list_vue.s3list_vue_parts.push({ url: s3.getSignedUrl('getObject', params) , filename: data.Contents[i].Key , }); } } }); } var s3list_vue = new Vue({ el: '#s3list_vue', template: '{{filename}}', replace: true, data: { s3list_vue_parts: [], }, methods: { onClick: function (getter) { var ref = cordova.InAppBrowser.open(getter, '_blank', 'location=yes'); } } }) loginCognito(); getS3Buckets(); 結果 S3の方に、こんなふうにファイルを設置しておきます。 S3 バケットリスト 画像を InAppBrowser で表示 解説 AWS周り 見ての通りですが、 loginCognito() で AWS の Cognito にログインしています。何のためかというと、S3へアクセスするための Credential を取得するためです。 Cognito 自体の解説については本家の https://aws.amazon.com/jp/cognito/ などから手繰れますが、 Cognito 認証の結果に応じて様々なロールを割り付けられるため、 AWS の各種コンポーネントへのアクセス許可を出すときに便利です。 コレが無かった頃は AccessToken / SecretToken の対で制御してましたね。 で、取得した Credential を使用して、 getS3Buckets() で S3 バケットの中身を取得、表示しています。 listObjects() のコールバックで結果を取得して、 Vue で定義しているモデルに一つ一つ push するだけ。 表示の更新は Vue に任せています。双方向バインディングばんざい。 InAppBrowser また、ファイル名をタップした時に開いているのは、 InAppBrowser という、 Cordova が用意したアプリ内ブラウザです。 Cordova の中でも開けるのですが、先に説明した Content-Security-Policy の制限を受けますので、そういう制限を無くしたい場合は InAppBrowser を使うことが多いようです。 Vue の v-on ディレクティブでタップ時に onClick() メソッドを呼ぶよう定義し、その中で cordova.InAppBrowser.open() にて InAppBrowser を呼び出しています。 open() の第二引数によって、下記のように挙動が変わります。 _self - URL がホワイトリストにある場合は Cordova の WebView で、そうでなければ InAppBrowser で開く (デフォルト) _blank - 常に InAppBrowser で開く _system - 常にシステムの Web ブラウザで開く まとめ スマートフォンでのクロスプラットフォーム開発を検討する際に必ず目にする Cordova ですが、「えー、 JavaScript で制御するとか凄い面倒そう、 JQuery とか DOM とか分かってないとダメなんでしょー」と、食わず嫌いをしておりました。 でも実際にやってみると、 Vue.js というフレームワークの強力さも相まって、すごく簡単にやりたい事を書けるようになってきていることを知りました。食わず嫌いよくない。 もちろんネイティブに比べたら出来ることは限られますが、それでも[一回書いたらどっちでも動く]事を考えると、案件次第では採用するメリットは相当ありそうだぞ、と思っています。 みなさんも、選定の選択肢に1つ、 Cordova 、如何でしょう?
はじめまして。mediba インフラストラクチャー部所属の沼沢と申します。 2015/10/06 〜 2015/10/09 に行われた AWS 最大のグローバルカンファレンス、 re:Invent 2015 に参加してきました。 そこで発表された新サービスや、新機能の紹介をしつつ、弊社でどう活用できるか、どのようなことが期待できるかなどを綴りたいと思います。 公式やブログなど、色んな所で既に紹介されているので今更感ありますが、お付き合いいただければと思います。 Day1 Amazon QuickSight クラウドベースの BI ツールということで新たに登場しました。 データソースを指定するだけで、データの可視化が可能になります。 AWS の BI 対応は以前から噂されていましたが、満を持して登場したというところでしょうか。 多彩なデータソースアクセス Redshift や RDS はもちろん、Kinesis など AWS の各サービスに対応 その他、コネクター経由でサードパーティも指定可能 データを直感的に可視化 SPICE という高速なAWS独自エンジンを採用 S uper-fast, P arallel, I n-memory C alculation E ngine SSD の3倍 の速度性能 フルマネージドで管理不要、スケールも自動 簡単に、低コストでの利用 サードパーティの BI ツールとの連携も可能 Tableau など RDS for Amazon Aurora が東京リージョンで利用可能に これは多くのユーザが待ち望んでいたのではないでしょうか。 基調講演の中では特に語られませんでしたが、今回のイベントに合わせてローンチされたようです。 東京リージョンに来たら移行しようと考えていた方々は、要チェックです。 パフォーマンスは最大で MySQL の5倍の性能で、MySQL 5.6 との完全互換があり、ダウンタイム無しでの移行が可能です。 また、容量は自動で拡張するため、空き容量を監視する必要がありません。 ★ mediba 的観点 AWS で商用稼働しているサービスの中には、RDS for MySQL を利用しているサービスがあります。 昨年の re:Invent で Aurora が発表されてから、RDS for MySQL で稼働しているシステムは Aurora へ移行したいと考えていたため、東京リージョンのローンチは心待ちにしていました。 例えば、弊社が AWS 上に構築/運用しているサービスの中に、RDS for MySQL を利用しているサービスがあり、そのサービス内のとある機能で、結構ハードにレプリカを参照する部分があります。 その機能に関連した訴求のために Push 配信を行うことがあり、その際には参照先のレプリカが高負荷になりがちなため、少し控えめに Push 配信をしているという現状があります。 RDS for MySQL ではレプリカを5個までしか配置できませんが、Aurora では 15 個のレプリカを配置することができるため、Aurora に移行することで、単純に参照性能の向上が見込まれるため、訴求の強化も期待できます。 上記のように、弊社で構築/運用しているサービスにおいて、Aurora へ移行することで改善が見込まれるケースが多々あると考えています。 ただし、Aurora に移行するにはいくつかの注意点があります。 Aurora では InnoDB のみがサポートされているため、MySQL 上で MyISAM を使用している場合は事前に InnoDB に変換する必要がある 現時点で Aurora で選択できるインスタンスファミリーは r3(メモリ最適化)のみで、タイプは large からとなっており、MySQL の同タイプと比べると若干お高いので、コスト面も注意が必要 Aurora を利用するということは、AWSにロックインされるので、そこに関しての考慮も必要 etc.. 今後、導入が実現した際には、ブログで書けたらと思います。 RDS for MariaDB RDS の DB エンジンの選択肢がまた1つ増えました。 今まで MariaDB が無いから移行を決断できなかったアプリケーションやサービスなど、RDS の MariaDB 対応によって、移行を進める企業は多いのではないでしょうか。 AWS Database Migration Service 主に、オンプレミスの DB を AWS に移行することを想定して作られたサービスです。 移行後も同期をとり続けることが可能とのことなので、移行元の DB を運用したまま徐々に切り替えるなどの方法で、ダウンタイムを最小限に移行することが可能だと思われます。 同一の DB エンジン間(MySQL → MySQL等)はもちろん、 AWS Schema Conversion Tool を利用することで、異なるDBエンジンへの移行も実行可能。 AWS Schema Conversion Tool では、DB スキーマやストアドプロシージャ等の移行の手助けをしてくれるそうです。 ★ mediba 的観点 弊社では、オンプレミスで稼働しているサービスもいくつか存在し、それらをクラウドに移行するかどうかはまだ検討段階です。 今後、オンプレミスで稼働中のサーバ群が EOSL を迎えるタイミング等で、AWS への移行が行われることになった場合には、稼働中の DB の移行をする時に非常に手助けになるのではないかと思います。 特に Aurora への移行という要件は少なからずありそうなので、その場合は非常に有用なサービスになります。 Amazon Kinesis Firehose Kinesis Stream に渡したストリーミングデータを、S3, Redshift に直接ロードするためのサービス。 Kinesis に渡したストリーミングデータは、そのデータを操作するワーカーが必要ですが、「S3/Redshiftにロードする」という単純な処理について、ワーカーを用意する必要がなくなったというイメージでしょうか。 これに伴い、従来の「Amazon Kinesis」は「 Amazon Kinesis Stream 」に名称が変更になりました。 ★ mediba 的観点 特に大量のデータが流れる広告事業のサービスにて有用なサービスだと考えられます。 例えば、ユーザの行動履歴のトラッキングをする場合に、トラッキングリクエストの受け口に利用することで、サーバーレスで大量のトラッキングリクエストを受けることができ、更にはコーディングレスで S3 or Redshift にダイレクトで保存が可能になるため、構築/運用の手間が減少し、更にビジネスロジックへ集中することができる=広告商品をより良いものへ昇華させることが期待できます。 Amazon Import/Export Snowball 物理の箱に大容量のデータを格納し、物理的にAWSのDCへの移行を実現するサービス。 “超BigData(数百PB)の移行をより簡単により早くするには?"を考えた結果、作成されたとのことです。 ※画像は Amazon Web Services ブログ より引用 1つあたり50TB 複数台同時利用でPBクラスのデータをおよそ1週間で転送可能 暗号化、改ざんを防止をして安全にデータを出荷し、出荷状況などのステータスを監視でき、非常にセキュアである 従来の1/5のコスト データ変換も自動的にできる(レガシーからオブジェクトなど) 東京リージョンは現時点で予定なし(必要だという声が多ければ実現するかも) AWS WAF 言わずと知れた、WAF(Web Application Firewall)が AWS で登場。 これによって、EC2 に登録しているアプリケーションをより堅牢にガードすることができます。 従量課金制で、お支払いは使った分だけです。 AWS Config Rules 昨年の re:Invent で、AWS の構成(リソース)を管理するサービスとして AWS Config が発表され、構成変更の履歴の管理などができるようになりました。 その AWS Config の新たな機能として発表されたのが、 AWS Config Rules です。 この機能では、AWS の構成変更について、ルールを策定することで、そのルールに沿った構成変更に限定することができます。 例えば EC2インスタンスに適切にタグが付与されていること EIPがアタッチされていること などをルールとすることで、構成変更の抜け漏れを防ぐと同時に、余計な設定をすることを防ぐことにも役立てることができるでしょう。 ★ mediba 的観点 現在、AWS で商用稼働しているサービスは多々ありますが、それらの構成変更には制限がありません。いくらルールを策定しても、権限を持っている IAM ユーザであれば、悪意の有無に関わらず、意図しない構成に変更ができてしまいます。 どう構成を組んだら良いか・おかしな構成になっていないかなどを、システム的に制御できるようになると、より一層、安定して安心な運用が可能になります。 Config Rules の利用で、安心・安全な運用の手助けになることを期待しています。 AWS Inspector 自動化されたセキュリティ診断サービスです。 一般的な脆弱性はもちろん、ネットワークやOS、アプリケーションレベルにおいても、それぞれの観点のセキュリティベストプラクティスをもとに、診断を実施してくれるサービスだそうです。 また、APIを利用することで、開発プロセスに組み込んで自動化することも可能です。 Day2 Amazon API Gateway が東京リージョンで利用可能に こちらも Aurora と同様、基調講演の中では特に語られませんでしたが、今回のイベントに合わせてローンチされました。 これで、東京リージョンでの API 構築が格段に楽なものになります。 ★ mediba 的観点 現在オンプレミスで稼働しているものの中には、アプリ向けに API を提供しているサービスがあります。 オンプレミスではサーバーをスケールするのは容易ではありませんが、API リクエストの受け口として API Gateway を挟み、スロットル機能を活用することで、オンプレミス側の API サーバのバーストを防止でき、安定した API 運用が実現できそうです。 Amazon Kinesis Analytics Kinesis Streams に格納されたストリーミングデータを SQL を利用して簡単に分析することができる、いわゆるストリーミング SQL データベースのサービスです。 EC2 の新インスタンスが追加に x1 インスタンスファミリー 最大 2TB のメモリ、100以上のvCPU t2.nano インスタンス 512MB のメモリ、1vCPU 他の t2 シリーズと同様、バースト機能あり Amazon EC2 Container Registry (Amazon ECR) Docker のコンテナイメージを管理するレジストリのフルマネージドなサービスです。 これにより、高可用性を備えたフルマネージドな Docker レジストリの利用が可能になります。 AWS Lambda の各種アップデート Python 2.7が利用可能に バージョニングとエイリアス機能の追加 VPC Support(まもなく利用可能に) VPC内のリソースへ、インターネットを経由せずにアクセス可能に タイムアウト時間の延長 60 秒 → 300 秒に延長 スケジュール実行が可能に cron 形式で指定 最短のインターバルは5分 Mobile Hub Cognito, SNS, MobileAnalytics, S3, CloudFront など、AWS のモバイル関連サービスにおける実装について、ウィザード形式で選択していくことでベースとなるコードを生成してくれるサービスです。 AWS IoT IoT(Internet of Things)の分野において、センサーなどのデータを収集、処理、分析、結果に応じたアクションを実行するためのサービスです。 以下のような機能群で構成されています。 Device Gateway MQTT, HTTPを用いてセキュアに通信するためのサービス Rules デバイスからのメッセージをルールに基づいて様々なアプリケーションに引き渡すためのサービス Shadow デバイスに対してもコミュニケーションを容易にするためのサービス デバイスが電源Offや故障、オフラインになってしまった場合などに、復旧までデータを蓄積/保持し、復旧したら最新情報を送ることができる Device SDK AWS IoTのための各種SDK(C, JavaScript, Arduino)も同時にリリース まとめ 上記以外にも細々した発表がありましたが、主要なものをご紹介しました。 現時点では、弊社では活用方法のイメージが湧かないものもありましたが、今回発表されたサービスは今後さらに機能追加やブラッシュアップが行われ、非常に強力なものになっていくことでしょう。 今後も AWS から目が離せません。
CTOの山田です。 毎度管理画面に運用向けの集計画面を作るの面倒だなと思って、少し前にre:dashを導入しましたのでご紹介致します。 re:dashとは データベースを可視化するためのpython製オープンソース。データソースはMySQL、PostgreSQLからGoogle BigQuery、Redshiftまで幅広くサポート。githubは こちら Redshiftの パートナー としてオープンソースで唯一(私が見た限りでは)認定されています。 環境構築 AWS上に構築されるのであればAMIが用意されています。 東京リージョンのAMIはap-northeast-1: ami-fae373fa です。 データソースの追加 データソースの追加はサーバで行います。OSはubuntuのためログインユーザはubuntuになります。 ssh ubuntu@ manage.pyでデータソースを追加していきます。mysqlでの例です。 cd /opt/redash/current sudo -u redash bin/run ./manage.py ds new -n <data> -t mysql -o '{"user" : "user name", "passwd" : "password", "host" : "host name", "db" : "db name"}' redshiftはもちろんPostgreSQLで行います。 sudo -u redash bin/run ./manage.py ds new -n redshift -t pg 登録はlistコマンドで確認できます。 sudo -u redash bin/run ./manage.py ds list -------------------- Id: 1 Name: rds Type: mysql Options: {"user" : "mediba", "passwd" : "xxxxxx", "host" : "xxxx.mediba.jp", "db" : "mediba"} -------------------- Queryの追加 今回は開発環境のデータを使って実施しました。 機能はシンプルなので直感的で使いやすいです。 re:dashにログイン  メニューのQueries>New QueryからQuery作成画面を開きます Query作成画面 右カラムにはテーブル一覧が表示されています テキストエリアにSQLを記述 “Execute"でSQLを実行 実行結果が下部に表示されます 結果をグラフで表示させたい場合は「New Visualization」から新規登録します グラフは「Visualization Type」から選択でき、緯度経度があればmapも使えそうです  今回は棒グラフを作成しました 登録したQueryを定期実行させる Refresh Scheduleから実行タイミングを登録します 定期間隔での実行か時間帯指定での実行か選択出来ます ダッシュボードの作成 メニューの「New DashBoard」からダッシュボードの作成画面を開きます タイトル横の+ボタンから「Add Widget」を開き、登録済みQueryを選択します 運用的にはカテゴリ毎にダッシュボードを作り整理するのがいいでしょう。 こんな感じになります。 まとめ サービス運用でデータを集計してグラフィカルに見たい要望が結構あると思いますが、re:dashを活用すれば開発工数を掛けずに実現できます。 queryで登録したデータはCSVとしても吐き出せます。
はじめに はじめまして、medibaのauスマートパス開発部 松本です。 私たちのグループでは、その名前の通り、auスマートパス向けのサービスを中心に開発を行っており、一部自社サービスの開発なども行っています。 これらのサービス群で使われている技術などについては、おいおい紹介していければと思っています。 現在ではWebとアプリを連動させた企画や訴求が非常に多く、新しいサービスの企画時にも、Webとアプリを最初から用意することが当たり前のようになっています。 弊社では現在、アプリ開発を行っていますが、実は昔、こんな名前でアプリをリリースしたりもしていました。 様々な事情により、1年ほどで中止されてしまった幻のプロジェクトです。 Eclipse3.5からAndroidStudioへ移行 社内でのアプリ開発の需要の高まりもあり、数年ぶりに昔のソースを引っ張りだして、最新の環境で動くようにしてみました。 EclipseのADTにて作成したプロジェクトを、AndroidStudioへ移植を行います。 AndroidStudioのメニューよりファイル→New→ImportProjectを選択、オプションとしてGradle-styleを選択しました。 これだけで、~/AndroidStudioProjects 配下のフォルダに、AndroidStudio用のプロジェクトが出来上がり、Gradle 関連のファイルも自動生成してくれます。 app/build.gradleを編集し、sdkのバージョンを当時のものへ近づけました。 defaultConfig { applicationId "jp.mediba.********" minSdkVersion 4 targetSdkVersion 4 } かなり古いですね。ライブラリなどはインポートされませんでしたので、以下のようにlibsフォルダを作成、配置しました。 左ペインのツリー表示部分を「プロジェクト」に合わせ(こうしないと新規→ディレクトリがでてきません)、app配下にlibsフォルダを作成すれば、後は直接ドラッグ&ドロップでjarファイルを配置できます。 配置後、プロジェクトペイン上のjarファイルを右クリックし「Add as Library」を選択することで、AndroidStudio側で自動でbuild.gradleファイルに dependencies { compile files('libs/******.jar') compile files('libs/******.jar') } のように記述してくれます。 これで、ビルドが通るようになりました。 AVD Managerから、テスト用デバイスを作成、ターゲットOSを設定し、そのままでは解像度の問題があるためscaleを2dp on device = 1pc onscreenに変更します。 そして起動。無事エミュレータ上でアプリが起動しました。 5年も前のプロジェクトの移行がこんなに簡単に終わるとは思いませんでした。 Logクラスの活用 いちいちデバッガを起動するまでもない、簡単な動作チェックなどを実施するときは、もっぱらLogクラスで済ませてしまいます。 import android.util.Log; Log.d(“ラベル名:”, it.getStringExtra(“変数名”)); デバッグ用として後から書くのではなく、コーディングの流れの中で書いてしまうと手間が省けます。 記述も簡単ですし、AndroidStudioのlogcatで/dや/vのようにフィルタしておけば、以下のようにまとめて視認するのも楽です。 分岐確認用の文字列まで仕込むようになると、本末転倒になってしまいますが、非常にお手軽なのでおすすめです。
はじめに mediba制作部 メディアクリエイティブグループの今野です。 初回投稿なので、カンタンにグループ紹介からさせていただきます。 当グループは20名強のメンバーがいて、サービスごとにチーム編成されており、デザインとフロントエンドを担当しております。 普段の業務で培ったノウハウや、また、業務以外で、UI/UX、Webの最新技術も研究などもしているので、今後そのネタも記事にしていく予定です。お楽しみに! 次から本題です。 backdrop-filterとは 先日iOS9.0がリリースされました。 iOS9.0では、様々な機能がブラウザに実装されたのですが、追加機能のうちの backdrop-filter プロパティをさっそく試してみました。 backdrop-filter は、背景に filter が使えるようにするプロパティです。 filter は、色相・明度・彩度や、ぼかし、セピアなどPhotoshopでよく使う機能があります。 例えば、以下画像のように、ぼかしである blur() をうまく使えば、すりガラスのような見た目もカンタンに実装できます。 (今までは、通常とぼかした画像を二重にして擬似的に表現しなければならなかったため、ちょっと面倒でした) 実装方法 実装方法はカンタンで、上に被せてるボックスに backdrop-filter を追加するだけ。 以下は、例です。 background-color: rgba(31, 20, 11, 0.5); -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px); 現在、 -webkit- のベンダープレフィックスが無いと動作しません。 なお、上記の書き方だと、対応していないブラウザには、画像左側の見え方になりますので、非対応ブラウザでも問題なく見えます。 さらに、iOS9.0から @supports も対応しており、指定プロパティが対応しているかどうかも条件分岐できるようになったため、非対応ブラウザの表現幅が広がりました。 ちなみに、似たような名前で、 ::backdrop 擬似要素というのがありますが、こちらは、 dialog 要素で生成したモダールウィンドウ以外の背景に装飾するための機能です。 今まで、モーダルウィンドウを一から作成するのは、少々面倒でしたが、今後はHTML、CSS、(JavaScript)でカンタンに実装できるので、こちらの機能も今後要チェックです。 各ブラウザ側の対応はこれからですので、早々に使えるわけではありませんが、最新ブラウザだけちょっと違う見え方というのも面白いと思いますので、ぜひ試してみてください。
medibaでCTOをやっております山田です。 はじめに システム開発がほぼ内製になり、新しい技術も積極的に導入し、また手掛けているサービスの規模も大きく、ナレッジも溜まってきましたので、ブログを通じて外部に公開していこうということになりました。 最初の投稿ですので、少しだけmedibaについても記載させて頂きます。 どんなサービスをやっているか? auスマートパスの各サービス、auヘッドラインやコネタなどのニュースメディア、auWallet、またauドメイン上のweb広告、キャリアメール広告などを展開しています。 auサービス以外にも独自メディア企画も開発中で、au系サービス、非au系サービス、広告事業と幅広く事業を手掛けております。 利用している技術は? PHP/yii frameworkをメイン言語に据えており、最近ではruby on rails、Scalaでの開発も行なっております。medibaが手掛けている事業、サービスは数多くあるため、一つの技術に絞るのではなく事業やサービスによって最適な技術選択をするようにしております。 最近注力している領域はAWSで、AWSサービスを活用して実装量を少なく手がかからないシステム作りを行っております。 medibaで利用されている技術はこちらも参照して下さい。エンジニアを絶賛募集中です! http://www.mediba.jp/recruit/career/engineer/ どんなことを書いていくか? キャリアサービスの裏側にはどういった技術が使われているか、バックエンドだけでなくデザインを含めたフロントエンドの技術情報を可能な限り公開していきたいと思います。 また、ちょっとした技術Tipsや技術調査結果なども合わせて公開していきます。 それでは今後ともよろしくお願いします。