みなさん、こんにちは。 先月は連休が多かったので、家族サービスを程ほどに以前から興味があったAWSを一から勉強していました。時間に余裕のある中でまったり勉強するのも、たまにはいいものですね。 今回は、AWSに触れてみて思ったことや試してみたことについてお話ししたいと思います。
AWSに触れてみて
まず最初は、以前購入した本や、動画で説明をしてくれるサイトを参考に、EC2(仮想サーバ)、RDS(RDBMS)、S3(ストレージ)を立ち上げてみました。
昔冷房がガンガン効いたデータセンターで凍えながら構築したような環境が、今ではコーヒーでも飲みながらブラウザでポチポチとボタンをクリックするだけで立ち上がるのは、知ってはいましたが実際に体験すると素直に感動します。
また、今更な話しだとは思いますが、一通り構築した環境に対していつでも復旧できるようにと、各サーバの中身を何本ものテープにバックアップしてたのも、スナップショットを取ることで簡単にバックアップもとれるようですし、かなり苦労して実装した障害検知の仕組みも普通に用意されているようで、もう何か至れり尽くせりです。
各サービスの構築や調整はManagementConsoleで行います。 画面は全て英語ですが、比較的シンプルなページ構成になっているので、英語が苦手な私でも何とか理解できました。 ただ、RDSを立ち上げようとした際、英語に対する拒絶反応がでてきて、デフォルトの設定にしておけば無料だよね、とあまり深く考えずポチポチと設定していったところ、どうやら誤った選択をしてしまったようで、途中から本番環境用の設定画面に進んでしまいました。 そして「DB Instance Class」にデフォルトで選択されていた「large」で立ち上げてしまった結果、タバコ一箱分ほど課金されてしまいました。
まあでも課金に気を付けさえすれば、サービスは限定されますが無料枠で色々と試せるのはやはり嬉しいです(EMRやRedShiftも無料枠で利用可能になるともっと嬉しいのですが・・・) EC2、RDS、S3と触れてみて基本的な操作や仕組みについてはある程度理解できたので、次はどのサービスを立ち上げようかな~なんて考えていた時、Salesforceとデータ連携してみたい、という思いがふつふつと湧いてきたので、ちょっと試してみました。
データ連携の概要
SalesforceとAWSでデータ連携するにあたり、まず連携方向から考えてみましたが、まだあまり分かっていないAWSを連携元にするには少し敷居が高そうに思えた為、連携元はSalesforceとし、連携先はAWSとしました(一方通行です) 次に連携先のサービスはどれがいいかなと、データベースやストレージのサービスを物色した結果、NoSQLのサービスAmazon DynamoDBにしました(NoSQLは恥ずかしながらまだ触った事すらないので無謀なのですが・・・) 選定理由としましては、DynamoDBは無料枠で利用できるデータベースのサービスというのがまず一つです。そして、API(REST)が提供されていてお手軽にデータ連携を試せそうでとても都合がよさそうだったからです。 ちなみにRDSも候補になるのですが、例えば中継用のWEBサービスをEC2上に構築したり等する必要がありそうで、これまた手間がかかりそうです。 また、EAIツールやDataLoaderを使用してS3にファイル連携するのでもよいのですが、それはそれで何かシンプル過ぎて面白味に欠けたので、あえてプログラムを書く必要がありそうなDynamoDBを選択しました。 データ連携の概要を簡単に纏めますと下記の通りです。 連携方向:Salesforce ⇒ AWS 連携先(サービス):DynamoDB プロトコル:HTTP 言語:Apex ?
SDK探し
連携の概要がざっくりまとまったので、次に実装をサポートしてくれるSDKはどのようなものが提供されているのか調査してみました。
SalesforceからDynamoDBのAPIを叩くとなると、Apex(サーバーサイド)かJavascript(クライアントサイド)の何れかだと思ったので色々と探してみたのですが、どうやらJavascriptのSDKしか存在せず、ApexのSDKは見つかりませんでした(当然と言えば当然でしょうか) ちなみにAWSで提供しているのは下記言語のSDKのようです
- Java
- JavaScript
- モバイル(Android,iOS)
- PHP
- Python
- Ruby
- Windows & .NET
JavascriptからAPIを叩くのでもよかったのですが、軽くウェブでサンプルを検索してみると結構簡単に実装できそうで面白味に欠けたので、あえてSDKのないApexからAPIを叩いてみることにしました。
実装
SDKは使用しないことにしたため、当たり前ですが自分でいろいろ実装する必要があります。 その為、まずはDynamoDBのAPIについてのリファレンスを探したところ、どうやらこちらに記載されているようです。
ただ、また英語です。 大人しくJavascriptのSDK使おうかな、と心が折れかけました。 ですが、落ち着いて内容をよく確認してみると、HTTPリクエストのサンプル等があり結構シンプルに纏まっているので、翻訳サイトを利用したり、時にはJavascriptやJavaのSDKの実装を参考にしながらリファレンスを読み解いてみました。
リファレンスの内容をざっくり纏めますと、リクエストヘッダに接続先のサービスに関する情報と認証情報を設定して、リクエストのボディに登録するデータやクエリの条件や抽出項目等をJSON形式で設定するようです。 なんだ、簡単じゃないかと思ったのですが、実際に実装していくと、リクエストヘッダに設定する認証情報を生成するのに手こずりました。
DynamoDBのAPIを叩く際に設定する認証情報ですが、AWS 署名バージョン 4(Signature Version 4 Signing Process)という方式で暗号化した文字列を設定する必要があるようです。 詳細はリンク先のページをご覧頂きたいのですが、簡単にまとめるとAPIを叩くのに必要な情報(接続先サービス、バージョン、シークレットアクセスキー、POSTするボディのデータ等)を
AWSが定めたルールに則って最終的に16進数の文字列にした上で、リクエストヘッダに設定する必要があります。 恐らくAWS側ではリクエストを受けた後、同様に認証情報を生成し、リクエストヘッダに設定されている認証情報と比較してリクエストの妥当性をチェックしているのではないでしょうか。
ちなみに下記が認証情報を生成する処理を実装したクラスとなります。 ぱっと見た感じ分かり難いかもしれませんが、認証方式の説明ページのプロセスとリンクする形でコメントを記載しましたので、併せてご参照頂ければと思います。
余談ですが、ちょうどこの記事を書いている時に、Salesforce社が開催していたCanvas機能のWebinarに参加しました。 Canvasから外部サーバにアクセスする部分の説明でも、全く同じではないですが、かなり似たような方式で認証情報を生成してリクエストに設定されていたのを見てとても印象的でした。 最近はこのような認証方式が一般的なんでしょうか(認証系の実装経験が乏しいな・・・)
これで認証情報を生成する処理は実装できましたので、次はAPIを叩く処理の実装ですが、今回はItem(レコード?)1件の登録or更新を行うPutItemを叩く部分を実装してみました。 ※ちなみに、現在DynamoDBで提供されているAPIはこちらになります。
PutItemは指定したキーが存在しなければ登録、存在すれば更新という、ApexのUpsertに近いものだと思います。 リクエストのヘッダにAPI名やAPIのバージョン等の必要な情報を設定し、リクエストのボディに登録するデータをJSON形式で設定するようです。
そして下記がDynamoDBにアクセスする際に使用するクラスとなります。14行目がPutItemを叩く部分の実装です。 引数にリクエストのボディに設定する文字列を受け取り、HTTPコールアウトにてDynamoDBにリクエストを行い、レスポンスを戻り値として返します。
参考までに載せますが上記クラスは下記クラスを継承しております。 認証情報の生成処理等、DynamoDB以外の他のサービスのAPIを叩く処理を実装する場合でも、恐らく同様の処理を行う必要がありそうなので、何となく抽象化してみました。
これでひとまずSalesforce側の準備は完了しましたので、次は連携先のDynamoDBの準備です。
DynamoDBの準備
DynamoDBについての概要はここをご参照ください。 今回はとりあえず、東京リージョンで「order」というテーブルを作成してみました。
テーブルの作成時はハッシュキーのみで一意にする方法と、ハッシュキーとレンジキーの組み合わせで一意にする方法の何れかを選択するのですが、今回はシンプルな前者にしています。
その他の設定はCloudWatchのアラームの設定や、性能の選択等です。 ハッシュキー以外の属性はItemの登録や更新時に好き勝手に設定してください、という所謂スキーマレスとなっているようです。 ひとまずこれでDynamoDBの準備は完了しましたので、次は実際に実行してみたいと思います。
実行
それでは、上で紹介しました「DynamoDBClient」を使用して開発コンソールからPutItemを叩いて見たいと思います。 データ連携と言うならば本当は固定の文字列ではなく、オブジェクトのレコードをJSON形式に動的に変換して実行できるようにしたかったのですが、時間の関係上それは叶わなかったので、今回は固定の文字列で実行します。
実行したところ特にエラーも発生しなかったようなので、DynamoDBに正常に登録されているかManagementConsoleから確認してみます。
どうやら正常にitemが1件登録されたようです。 特に意識しなかったのですがマルチバイト文字も問題なさそうですし、テーブルの登録時に設定した性能通りのパフォーマンスが出ておりitem1件の登録で1秒前後でした。 ちなみにこの後、同じキーで属性値を変更して再度実行したところ、先程登録したデータが正常に更新されました。
時間があれば今回出来なかったオブジェクトのレコードからJSON形式の文字列に変換する処理の実装や、逆にDynamoDBから取得したデータをSalesforceの画面で表示したり等いろいろ試してみようと思います。
最後に
今回はAWSに触れた感想から始まり、SalesforceからDynamoDBへのデータ登録を試した事について書いてみました。 いくつかのサービスに触れていく中で、サービス名とサービス内容が段々頭の中でリンクするようになってきたように思えます(まだこんなレベルです) これからも何とか時間を作ってAWSは勉強していく予定ですので、機会があればまたOUTPUTしていきたいと思います。
ただ、今回試したこの内容、実用する機会があるのかどうか正直まだよく分かっておりません。 例えば、Salesforce上のデータ量が想定以上に増えてしまい、あまり参照されなくなった「大量」の過去データをどこかに退避したいが、その退避した「大量」の過去データと直近のデータを使用して複雑な分析を行いたい、といった要件等では、下の図のように応用できたりするのでしょうか(EMRの部分はまだ触れていないのでぼやけております)
こんなことをしなくても、MotionBoardを利用すればさくっと実現できたりするのかな・・・