Java 開発 2.0: Elastic Beanstalk という伸縮自在な豆の木に登る

Amazon の限りなく柔軟な PaaS によるクラウドのスケーリング

自分が使っている環境をより自由に制御したい一方、PaaS のプラグ・アンド・プレイ的なスケーラビリティーも気に入っている人々にとって、Beanstalk は Google App Engine に代わる絶好の手段となるはずです。Andrew Glover が案内するこの Beanstalk のツアーでは、位置情報を利用したモバイル・アプリケーションを Play フレームワークと MongoDB を使って構築するところから始め、このアプリケーションを Beanstalk 環境に移植する手順を具体的に説明します。Beanstalk を構成するのは、簡単かつ実りのある作業です。著者が言うように、Beanstalk には、GAE が提供する以上の選択肢と柔軟性があるからです。

Andrew Glover, Author and developer, Beacon50

Andrew GloverAndrew Glover は、ビヘイビア駆動開発、継続的インテグレーション、アジャイル・ソフトウェア開発に情熱を持つ開発者であるとともに、著者、講演者、起業家でもあります。また、easyb BDD (Behavior-Driven Development) フレームワークの創始者、そして『継続的インテグレーション入門 開発プロセスを自動化する47の作法』、『Groovy in Action』、『Java Testing Patterns』の 3 冊の本の共著者でもあります。詳細は彼のブログにアクセスするか、Twitter で彼をフォローしてください。



2011年 2月 22日

約 2 年前にこの連載を開始したとき、Java™ 開発 2.0 は主に 2 つの (非常に興味深い) 傾向による結果であると説明しました。その傾向とは、(1) 開発者がオープンソースのツールとフレームワークを利用してアプリケーションをまるごと構築するようになっていること、(2) アプリケーションのデプロイメントおよび実行を含め、あらゆるレベルでソフトウェア開発のライフサイクルを管理するために必要なアプリケーション・インフラストラクチャーを貸し出す (または借りる) ようになっていることです。

この連載について

Java 技術が初めて登場してから現在に至るまでに、Java 開発の様相は劇的に変化しました。成熟したオープンソースのフレームワーク、そしてサービスとして提供される信頼性の高いデプロイメント・インフラストラクチャーを利用できる (借りられる) おかげで、今では Java アプリケーションを短時間かつ低コストでアセンブルし、テスト、実行、保守することが可能になっています。この連載では Andrew Glover が、この新たな Java 開発パラダイムを可能にする多種多様な技術とツールを詳しく探ります。

連載の最初の頃に、Java による Web 開発用のクラウド・プラットフォームとして Google App Engine と Amazon EC2 の 2 つを取り上げました (「参考文献」を参照)。この 2 つは、それぞれ独自の方法で Java 2.0 の可能性を具現化しています。GAE は PaaS (Platform as a Service) オファリングですが、EC2 は IaaS (Infrastructure as a Service) です。EC2 はいわば、オンデマンドの仮想環境であり、ここには好きなものを何でもインストールすることができます。GAE はそれよりも好みにうるさく、Python および Java による Web アプリケーション開発専用にセットアップされています。

EC2 に比べ、GAE はこれまでクラウド・ベースのアプリケーションをより短期間で簡単に開発するための手段となってきました。しかし、ここ数年の間、PaaS 市場の動きが非常に活発になっています。PaaS の概念が広く採用されるようになっているなか、そろそろ PaaS の人気が爆発する頃だと言っている人もいます (「参考文献」を参照)。そんな中、Amazon が近頃 Elastic Beanstalk という独自の PaaS を発表したのも当然と言えるでしょう。

Amazon の Beanstalk

GAE と Beanstalk は、どちらも Java アプリケーション開発用に調整されたクラウド・プラットフォームです。GAE と同じく、Beanstalk では一定の形を持たない極めてスケーラブルな環境 (Beanstalk の場合は EC2で駆動された環境) に、開発者が WAR ファイルをデプロイします。けれども GAE とは異なり、Beanstalk では開発者がアプリケーション環境をカスタマイズすることができます。この点が、ソフトウェア開発者にとって確かな魅力 (そして多くの場合は実用にかなった魅力) となっています。

例えば、Beanstalk では GAE とは違って、アプリケーションをホストするノードの数を自由自在に制御することができます。そのため、水平スケーリングを簡単かつ効率的に実施することができます。しかも、どの Java ライブラリーを使用することもできます。Java ライブラリーに関しても、GAE では選り好みが激しくなっています。汎用の PaaS タスクに関しては、Beanstalk はノード間のロード・バランシング、デプロイメント成果物のバージョン管理、さらにはリモート端末から EC2 インスタンスへの下位レベルでのアクセスも行えます。レポート作成機能が組み込まれているので、アプリケーション環境の正常性およびパフォーマンスは随時チェックすることができます。


Beanstalk と GAE のどちらを選ぶか

GAE に勝る Beanstalk の利点は、根本的に異なるクラウド・ベースのサービス・モデルに根差しています。GAE は現在、厳格な PaaS であり、GAE を使用することにした場合、開発者が決めなければならないことはそれほどありません。これは、シナリオによっては良い結果となります。GAE で選択できるデータストアは 1 つ (Bigtable) だけで、Java ライブラリーの選択肢もわずかな数です。将来的には変わってくる可能性がありますが、現時点では、例えば Hibernate を使って Web アプリケーションを構築することはできません (「参考文献」を参照)。また、Web アプリケーションをいったんデプロイすると、アプリケーションの制御の自由がかなり限られてきます。実際、クラウドのスケーリングという点では一切制御することができません。基本的に GAE では、スケールアップを Google に一任することになるからです。この分野での Google の専門技術を考えれば、これはある意味当然と言えますが、開発者や企業によっては、アプリケーションをもっと制御できるようにする必要があります。しかもそれは、クラウド内での制御です。

データ機密性の保護措置が欠けていることも、一部の人々にとっては不満の種となります。GAE Web アプリケーションを構築するときには、データがどこに置かれるかは不明です。データに絶対的な重要性があるドメインや、データの機密性が最重要事項となるドメインでは、Bigtable の架空の抽象化に送信するだけでは安心とは言えず、問題がないとも言えません。場合によっては、まさにこの理由だけで GAE が選択肢から外されることさえあります。


Magnus と Beanstalk

Beanstalk の詳細を探るには、その機能のデモンストレーションをするための Web アプリケーションが必要です。そこで、これから Magnus という名前のアプリケーションを構築します。Magnus はモバイル機器から位置情報データを取得して、そのデータをデータストアに永続化するアプリケーションです。一度に何百万ものモバイル機器が接続することを前提に、Magnus はその人気の急増に応じて素早く簡単にスケーリングできるようにしなければなりません。そこで、水平スケーリングを使用して、アプリケーションのインスタンスが必要なときに、すべてのインスタンスを確実に使えるように Beanstalk を微調整します。

AWS にサインアップしてください

Beanstalk を使用するには、まずその前に Amazon Web Services にサインアップする必要があります。Beanstalk では現在無料のプランを提供していますが、スケーリングによって追加のリソースと帯域幅を使用するようになると、もちろん使用料が発生します。

アプリケーションの構築はこの記事の論点ではないので、手早く片付けます。まず Java ベースの Play フレームワークを使って単純な REST エンドポイントを構築します。このエンドポイントに、モバイル機器の位置を示す地理的座標を記述した JSON 文書をモバイル機器自らが送信することになります。Play は自らのことを、「肥大化したエンタープライズ Java スタック」に置き換わるフル・スタックであると謳っています。このフレームワークを迅速にセットアップして稼働状態にするのは容易です。私は、そのシンプルなルーティング・システムも気に入っています。ステートレス・モデルを使用して、RESTful なアプリケーションを簡単に構築できるようになっている Play では、私独自の永続モデル (MongoDB を使用する永続モデル) を簡単に組み込むことができます。

このサンプル・アプリケーションでは、同じく PaaS のプロバイダーである MongoHQ がホストする MongoDB インスタンスに位置座標を保管します。したがって私が行う作業は、データストアを作成して、そのデータストアに HTTP を介して文書を追加するまでのところです。後の作業は、MongoHQ がすべて引き受けてくれます。

アプリケーションを構築する

このサンプル・アプリケーションでは、アカウント管理用の Web インターフェースは省略します。実際のシナリオでは、エンド・ユーザーが Magnus サービスのアカウントを作成します。その場合、私はアカウントの位置情報を記述する JSON 文書に、追加のアカウント情報を組み込むことになると思います。しかし、サンプル・アプリケーションで位置情報をアカウントに関連付けるには、URL で十分です。

例えば、アカウント12345 に関連付けられた機器があり、現在その機器が、カナダのケベック州にあるとします。この場合、サンプル Web アプリケーションには、リスト 1 のような JSON 文書が送信されます。

リスト 1. 位置情報を記述する単純な JSON 文書
{
 "name":"location payload",
 "latitude":"46.49",
 "longitude":"71.11",
 "timestamp":"02-02-2011 14:43"
}

この文書は、HTTP PUT 呼び出しを使って以下の URL に送信されます。この URL は、アカウントの位置情報に対応します。

リスト 2. アカウントの位置情報に対応する RESTful な URI
http://some.web.address.com/location/12345

アカウントの位置情報は、リスト 2 に記載した URI にあるリソースです。つまり基本的には、HTTP PUT によってアカウント 12345 の位置情報をこのアドレスに更新していることになります。レスポンスは、リクエストを確認応答する JSON 文書です。

位置情報文書

位置情報文書を作成するには、Morphia を使用することにします。これは、POJO (Plain Old Java Object) を MongoDB にマッピングする ORM 風のライブラリーです。リスト 3 に、POJO で作成した位置情報文書を記載します。

リスト 3. 位置情報文書の作成
@Entity(value = "locations", noClassnameStored = true)
public class Location {
 @Id
 private ObjectId id;

 private String accountId;
 private double latitude;
 private double longitude;
 private Date timestamp;

 public Location(String accountId, Date timestamp, double lat, double lon) {
  this.accountId = accountId;
  this.timestamp = timestamp;
  this.latitude = lat;
  this.longitude = lon;
 }

 public void save() throws Exception {
  Mongo mongo = new Mongo("gnome.mongohq.com", 34256);
  Datastore datastore = new Morphia().createDatastore(mongo, "magnus", 
     "username", "password".toCharArray());
  datastore.save(this);
 }
}

MongoHQ への接続情報はハードコーディングしていることに注意してください。実際には接続情報をハードコーディングすることはしないはずですが、デモンストレーションをするのが目的であれば、これで問題ありません。

すべてを結び付けるのは、Play の単純なコントローラーおよびルート定義です。コントローラーは、JSON リクエストを受信するエンドポイントとして機能します。ルート定義は、リスト 4 に記載するとおりです。

リスト 4. Play のルート定義
PUT /location/{id}     Application.saveLocation

上記の定義では、/location/{some id} のパターンと一致する URI への HTTP PUT リクエストはすべて、Application クラスの saveLocation メソッドにルーティングするように規定しています。

saveLocation は、リスト 5 からわかるとおり、単純なメソッドです。

リスト 5. saveLocation メソッド
public static void saveLocation(String id, JsonObject body) throws Exception {
 double latitude = body.getAsJsonPrimitive("latitude").getAsDouble();
 double longitude = body.getAsJsonPrimitive("longitude").getAsDouble();
 String when = body.getAsJsonPrimitive("timestamp").getAsString();

 SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy HH:mm");
 Date dt = formatter.parse(when);

 new Location(id, dt, latitude, longitude).save();
 renderText("success");
}

Play は、リクエストされた URL の末尾の ID (つまり、12345) と JSON 本体を渡します (そのためには JSON バインディングを作成する必要がありました。これについては、Play Web サイトに説明が記載されています)。すると、このコードはすぐに、JSON 文書からデータ (つまり、緯度、経度、時刻) を取得し、Location インスタンスを作成して保存します。コードの最後で指定しているのは、レスポンスです。今のところ、これは単なるテキスト・ストリングのレスポンスですが、後で変更して、新しいバージョンをデプロイします。このコードには含まれていませんが、実際のアプリケーションではエラー処理も必要であることに注意してください。

簡単なヘルス・チェック

現時点で、サンプル・アプリケーションには 1 つの到達可能なエンドポイントがあります。このエンドポイントは、JSON リクエストしか受け入れません。これに対処するには、いくつかのツールが必要になってきます。それとは別に、アプリケーションをデプロイした後にすべてが機能することを確認できるように、ブラウザーでアクセスできる通常のエンドポイントも用意したいと思います。そこで、Play の Application クラスに index メソッドを実装して (このメソッドは、ルート・パスにアクセスするとデフォルトで呼び出されます)、何らかのテキストがすぐに返されるようにします。具体的には、renderText("Magnus Web is live");Application クラスの indexメソッドに追加します。

最後のステップとして、Beanstalk をデプロイするために WAR ファイルを作成します。このファイルは基本的には、見せ掛けの Tomcat コンテナーです。Play では、コマンド play war -o ../magnus --zip を実行するだけで、この Play のサンプル・アプリケーションが含まれる magnus.war というファイルが作成されます。

これによって、将来大きな成功を収めることになる、機密性を心配する必要のない私の位置情報収集アプリケーションがビルドされます。次のステップは、人々が自分の位置情報を継続的に提供することが賢明なことであると認識するようになった暁に必要となる、Beanstalk の大々的なスケーラビリティーがアプリケーションに備わっていることを確実にすることです。


Magnus と豆の木 (Beanstalk)

皆さんが Beanstalk にサインアップしていることを前提として、まずは AWS Management Console (AWS 管理コンソール) にログインしてください。管理コンソールから「Elastic Beanstalk」タブを選択し、「Upload your own application (独自のアプリケーションをアップロードする)」オプションをクリックした後、「Launch Application (アプリケーションの起動)」ボタンをクリックします。すると、いくつかの情報を求めるダイアログが表示されます (図 1 を参照)。

図 1. 新規 Beanstalk アプリケーションの作成
Beanstalk の新規アプリケーション作成画面のスクリーン・ショット

このダイアログに、アプリケーションの名前を入力してください。入力した名前は、アプリケーションの URL としても使用されます。また、WAR ファイルも指定する必要があります。「Continue (続行)」ボタンをクリックすると、アプリケーションが起動する間、AWS 管理コンソールが再び表示されます。アプリケーションが起動するまでには、時間がかかる場合があります。私の経験では、最大 10 分かかったこともあります。

アプリケーションが完全にデプロイされて、Amazon側での構成がすべて完了すると、アプリケーション名の隣に緑色のボックスが表示されます。緑色の表示は、アプリケーションを実行する準備ができていることを意味します (図 2 を参照)。

図 2. Magnus の準備完了!
アクセス可能な状態になっている新規 Beanstalk アプリケーションを示すスクリーン・ショット

Amazon によって提供された URL、magnus.elasticbeanstalk.com をクリックすると、アプリケーションが実行中であることがわかります。図 3 に示されている内容は、「簡単なヘルス・チェック」のセクションで追加したコードによる結果であることに注意してください。

図 3. Magnus 実行中!
実行中の新規 Beanstalk アプリケーションを示すスクリーン・ショット

Beanstalk の構成

Beanstalk Management Console (Beanstalk 管理コンソール) 右下の「Environmental Details (環境の詳細)」セクションに表示された「Edit Configuration (構成の編集)」リンクをクリックすると、Beanstalk の実力が見えてきます。このリンクをクリックすると表示されるダイアログには、実に賢明な選択肢を含んだ豊富なオプションが揃っています。

図 4. 環境の構成内容の編集
Beanstalk の構成を行うダイアログ・ボックスのスクリーン・ショット

Beanstalk は、アプリケーション・インスタンスのメモリーの量、I/O パフォーマンス、ローカル・ストレージなど、さまざまな上位レベルのデプロイメント・オプションを提供します。さらに、アプリケーションのロード・バランサーや自動スケーリングを構成することも可能です。後者は水平ノードを制御するオプションで、これを使って、実行させたいアプリケーションのインスタンス数、および各新規インスタンスのトリガー方法を決定します。

自動スケーリングは、アプリケーションのスケーラビリティーを開発者の手に直接委ねる、Beanstalk の並外れて強力な側面です。自動スケーリングに考えられる設定としては、例えば着信トラフィックなどの基準に応じて新規インスタンスを起動するように設定することができます。トラフィックが低下すれば、アプリケーションは元のスケールに戻ります。しかもこの過程はすべて、手動による介入なしで行われます。まさに、エラスティック・コンピューティングそのものです!


アプリケーションのテスト

Magnus が Web 上で有効になったところで、サンプル・アカウントに位置情報を追加してアプリケーションをテストしてみましょう。ここでは間に合わせとして、ツールを使用して JSON 文書をエンドポイントに送信します。RESTClient は HTTP PUT を使用して JSON 文書をサンプル・アプリケーションに送信します。ここまでのところ、図 5 に示されているように万事順調に運んでいます。

図 5. RESTClient がレポートする着信ペイロード
RESTClient レポートのスクリーン・ショット

最後のサニティー・チェックは、JSON 文書が MongoDB に永続化されているかどうかを調べることです。こう言うと、皆さんの記憶に蘇ってくると思いますが、MongoDB は MongoHQ で実行されています。

図 6. Magnus の位置情報文書を示す MongoHQ のインターフェース
Magnus の位置情報文書を示す MongoHQ のインターフェース

エンドポイントのレスポンスは、アプリケーション開発の初期フェーズでは単純なものにしておきましたが、これからアプリケーションに少し変更を加え、再デプロイします。


バージョン管理されたデプロイメント

Beanstalk は GAE と同じく、バージョン管理されたデプロイメントをサポートします。したがって、複数のバージョンをデプロイすることはできても、随時「有効」なのは 1 つのバージョンだけです。この機能により、例えばデプロイメントが失敗した場合にロールバックするなど、必要に応じて、あるバージョンから別のバージョンに容易に変更することができます。

Beanstalk コンソールの「Application Details (アプリケーションの詳細)」セクションの左上隅近くにある「Versions (バージョン)」タブをクリックしてください。この操作によって、サンプル・アプリケーションの最初のリリースが表示されるはずです。

図 7. Beanstalk によって表示されたアプリケーションのバージョン
Magnus v1 のアプリケーションの詳細を示す Beanstalk 管理コンソールのスクリーン・ショット

これから私のローカル・マシンで、Application クラスの saveLocation メソッドを変更します。具体的には、メソッドの最後の行が renderJSON("{success}"); となるようにします。これによって、レスポンスが単純なテキスト・ストリングの代わりに、単純な JSON 文書を返すことになります。

Upload New Version (新規バージョンのアップロード)」ボタンをクリックすると、お馴染みのダイアログが表示されます (図 8 を参照)。このダイアログで、WAR ファイルのバージョン・ラベルを入力します。

図 8. Magnus の再デプロイメント
再デプロイされるアプリケーションの詳細を示すスクリーン・ショット

図 8 に示されているように、私は WAR ファイルのアップロードだけを行い、デプロイメントはしないように指定しました。WAR ファイルがアップロードされていれば、後からいつでも「Versions (バージョン)」タブからファイルをデプロイできるからです。

図 9. Magnus の再デプロイメントと新規デフォルト・バージョンの作成
アプリケーションを再デプロイするための Beanstalk インターフェースのスクリーン・ショット

目的のバージョンの隣にあるチェック・ボックスをクリックすると、後は「Deploy Version (バージョンのデプロイ)」ボタンをクリックするだけで、そのバージョンを有効なバージョンにすることができます (図 9 を参照)。

Beanstalk を終了したいとしたら、もちろん、それも可能です。それには管理コンソールの右側にある「Actions (アクション)」ドロップダウン・ボックスから、「Terminate this Environment (環境の終了)」を選択します。この場合、バージョン管理された WAR ファイルを削除することも忘れないでください。これを忘れると、削除するまで S3 でのスペース使用料が請求されることになります。

図 10. Beanstalk の終了
Beanstalk を終了するための選択項目を示すスクリーン・ショット

豆の木を上ったり下りたりする (伸縮自在な Beanstalk)

Elastic Beanstalk は、開発者が Amazon の EC2 インフラストラクチャーに容易にアクセスする手段となります。しかも、私たちが GAE で受け入れるようになった制約を遥かに超えて、自由にインフラストラクチャーを構成できるようになっています。位置情報ベースのサンプル・モバイル・アプリケーションでデモンストレーションしたように、Play のような比較的新しい Java Web フレームワークでも問題なく使用できるだけでなく、MongoHQ.com で実行される MongoDB インスタンスを使って文書を永続化することもできます。

サンプル・アプリケーションでは、データベースや Tomcat のインスタンスを起動する必要も、さらにはポートが開いていることを確認する必要も一切ありませんでした。プロセスは単純で、時間もかかっていません。さらに嬉しいことに、このサンプル・アプリケーションはトラフィックが急増した場合、フロント・エンドのロード・バランサーによって 4 つのインスタンスにまで自動的にスケーリングします。しかも、このロード・バランサーを構成する必要はありませんでした。その一方、バージョン管理されたデプロイメントでの私の限られた経験によって明らかなように、なるべく自分で制御したいのであれば、そうすることもできます。使い始めにかかった合計コストは、これ以上抑えることは不可能な額でした。つまり、$0.00 です。

Amazon の Beanstalk は、新たに登場してきている PaaS の選択肢の 1 つに過ぎません。これらの選択肢によって、Java 2.0 の全体像はより豊かに、そしてより刺激的になっています。賢い革新的な企業がこの成長を続ける分野で新しいニッチ市場を開拓し始めているなか、急速な、しかも最小限のコストでのエンタープライズ環境への展開は、今後も続くはずです。

参考文献

学ぶために

製品や技術を入手するために

  • Amazon Elastic Beanstalk: リファレンス・マニュアルを読んで、GAE に代わる Amazon の PaaS、Elastic Beanstalk にサインアップして早速使い始めてください。
  • Play フレームワーク: Web 開発者によって構築された Java フレームワークを自称する Play は、開発者の生産性に重点を置き、RESTful なアーキテクチャーをターゲットとしています。
  • MongoDB: このとてつもなくスケーラブルなドキュメント指向のデータベースは、C++ で作成されていますが、JSON スタイルの文書を使用して保管することから Java に対応します。
  • MongoHQ: MongoDB がホストする、クラウド内でのデータベース・ストレージです。

議論するために

  • developerWorks コミュニティーに参加してください。ここでは他の developerWorks ユーザーとのつながりを持てる他、開発者が主導するブログ、フォーラム、グループ、ウィキを調べることができます。

コメント

developerWorks: サイン・イン

必須フィールドは(*)で示されます。


IBM ID が必要ですか?
IBM IDをお忘れですか?


パスワードをお忘れですか?
パスワードの変更

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


お客様が developerWorks に初めてサインインすると、お客様のプロフィールが作成されます。会社名を非表示とする選択を行わない限り、プロフィール内の情報(名前、国/地域や会社名)は公開され、投稿するコンテンツと一緒に表示されますが、いつでもこれらの情報を更新できます。

送信されたすべての情報は安全です。

ディスプレイ・ネームを選択してください



developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

必須フィールドは(*)で示されます。

3文字から31文字の範囲で指定し

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


送信されたすべての情報は安全です。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Java technology, Open source, Cloud computing
ArticleID=642245
ArticleTitle=Java 開発 2.0: Elastic Beanstalk という伸縮自在な豆の木に登る
publish-date=02222011