2011年7月26日 (火)

BIGLOBEクラウドホスティングを少し触ってみた感想

すごくひさしぶりの更新です。プロジェクトに忙殺されていました。
よくないですね。これからまた更新頻度をあげていきたいと思います。

さて、今日はBIGLOBEクラウドホスティングを使ってみたのでそのことを書いてみようと思います。サービスのサイトは以下です。

http://business.biglobe.ne.jp/hosting/cloud/

使い方は以下のページに載っていて、イメージしやすいです。

http://www.atmarkit.co.jp/ad/nec_biglobe/biglobe_cloud.html

私自身はAWSを使ったサイト構築や受託での提案などの経験があり、
普段AWSを愛用しているものですが、そういった立場で試用して
みた感想(なるべくよいところ)を書いてみようと思います。

■ サービス概要と最初の印象

クラウドサービスの分類としてはIaaSに入ります。Amazon EC2と同じく、コントロールパネルからサーバの起動や停止ができます。鍵ペアを発行してログインに至るまでのプロセスなどはEC2を使っている人はなじみがあるプロセスかと思います。

サービスはEC2と同じくサーバリソースの提供がメインです。CentOS、RHEL、Windows系が
サポートされており、EC2を激しく意識しているらしいので、価格帯はEC2と勝負できる範囲です。Reserved Instanceに相当するものが今のところ用意されていなさそうなのは、価格面では
ちょっと残念なことろでしょうか。(もちろん、今後に期待!)

DB等のミドルウェア系のサービスは今のところあまりありませんが、きっとこれから提供されていくのだと思います。あ、DBサーバにMySQLを初期インストールするといったショートカットするオプションはあります。

サーバイメージの保存、ロードバランサ、監視サービスなどは提供されています。

ただ、AWSと比較するとS3、SimpleDB、SNS、SQS、SES・・・といったAWSを彩る魅力的なサービス群に該当するものはなさそうです。(一部は連携メニューにあるかもです)

■ セキュリティサービスがあるのが一番の特徴(だと思う)

ここまでは始ったばかりのサービスでもあるからか、あまり大きな特徴がないようにも見えますが、一点、目を見張るサービスがありました。セキュリティオプションのWAF(Web Application Firewall)です。(あ、サーバ稼働率99.99%のサービスレベルの保証は「おっ」とは思いました)

最近は個人情報漏洩などの問題もあり、セキュリティ系だけはきっちり、という要望が私の知る範囲では多く見られます。セキュリティをがっちり、というのはたしかに大事なのですが、WAFやIDSなどはそれを主業務としない立場としては、構築、運用にけっこう手間がかかってしまうというジレンマがあります。
構築するのもアプリ開発とは違う知識が必要ですし、構築後も「検知ルールの運用どうするんだぁ?」とかとか、いろいろ大変です。

AWSで自分がログ等を監査できるWAFやIDSをきっちりやろうとすると、今のところは自前で構築が必要になります。(IDSは程度にもよりますが、ネットワーク型のものは自前では構築は明らかに困難・・・、)
実際の私の経験でもWAFやIDSの設置(設置した場合の運用コスト)がネックのひとつと
なりAWSを提案したけど、見送られたというケースがありました。

そういったことを踏まえたとき、WAFが最初から選択可能なサービスとして提供されているのはすごくうれしい限りです。さっとサービスを立ち上げたいけど、WAFを設置したい、ってのを両立できそうです。

IDSに関してはコントロールパネルから利用可能な形ではなく、連携メニューとしてホームページに掲載がある程度ですが、そういうものをちゃんと用意してきてくれているのがすごく個人的にはよいなと思いました。

こういったセキュリティ系のサービスをなるべく拡充して、使い勝手よくローコストで提供していってほしいな、と思いました。

■ あと、細かいかもしれませんが、用語が馴染みやすい

今のところシンプルなコントロールパネルですが、AWSとの比較で考えると、対エンジニアはともかくとしてそうではない人にたいして、言葉が簡単でよいな、と思いました。

AWSについて打ち合わせなどをするとS3、ELB、RDS、EC2・・・、という短縮語が飛び交い、慣れている人はよいですが、そうではない人に対して「S3ってのはね・・・」「EC2ってのはね・・・」と説明しなくてはいけないケースがときどきありました。
(これは、職場環境やどういったお客様と接しているか、という環境にもよるのであくまでも私のケースですが)

BIGLOBEのはサーバ作成、サーバ一覧、ディスク追加、といった用語がコントロールパネル上を埋めており、「あー、まあ、たしかに分かりやすいよね」と思いました。
AWSのS3とか使わない人にはとっつきやすいかもしれません。

■ 当社にとってSIerとしての使いどころ

当社は自社サービスでAWSを使っており、S3など気に入って使っているので個人的には自社開発のものはやはり引き続きAWSを使おうかなぁ、と思っています。
また、当社はSalesforceとのインテグレーション事業を一所懸命やっていますが、Salesforceとの連携においてEC2というよりはS3などのAWSのコンポーネント群とのインテグレーションはノウハウを引き続き活用していきたいと思っています。

ただ、WEBサイト開発などの受託開発という面においては必ずしもS3とかAWSのコンポーネント群を必要としないお客様も多く、またセキュリティ要件が一層厳しくなりつつある状況なので、
そういったお客様に対してはWAFやIDS連携ができるといったメリットが大きく効いてくる可能性が高いと考えています。そういったお客様は少なくないので、ひとつの有力な選択肢として準備しておきたいな、と思いました。

■ 今後について

現在、BIGLOBEクラウドホスティングをひとつの選択肢にしようと、一部の自社内システムリソースの移行を検証しており、おそらく夏中には実運用することになると思います。AWSの知見を引き続き自社サービスで蓄えつつ、セキュリティに強い方の選択肢としてBIGLOBEクラウドホスティングの知見をこれから社内でためていこうと思います。

その上で、ニーズに応じて必要なプラットフォームを選択できる体制を社内に築いていくつもりです。

また、新しいサービス等、追加されたら試してブログ書いてみます。

2011年1月27日 (木)

セールスフォース、Google、AmazonのPaaSの比較とSIer視点からの印象

最近、Amazon Beanstalkが発表されて、PaaS領域が一段と盛り上がってきました。

業務系に強いForce.com、ソーシャルアプリなどコンシューマ系サービスに強いGoogle App Engineあたりが有名でしたが、最近は選択肢がかなり増えました。
この記事を書いている最中にもちょうど以下のような記事がでていて、PaaSに対する注目度が高いことがうかがえます。

http://www.publickey1.jp/blog/11/google_app_engine_paas.html

http://www.publickey1.jp/blog/11/_java_paas.html

上記の記事でだいたいよいところ、難しいところがまとまっているのですが、今日はGoogle App Engine、Force.com、AWSのサービス、それぞれ実サービスの運用や受託開発で使った経験や、SIerでマネージャをする立場から、自分なりの比較と印象を書いてみようと思います。まず、セールスフォース、Google、Amazonが提供、あるいは関連が強いPaaSについて言語、利用するDB、インフラ運営元、そしてサービス提供会社を一覧にしてみました。

◆ 各プラットフォームと言語、DBなどの比較

名前言語DBインフラ環境サービス提供会社
Google App Engine(GAE) Python, Java BigTable Google Google
Force.com Apex, VisualForce Force.comのDB(Database.com) Force.com(セールスフォース) セールスフォース
VMForce Java(Spring Framework) Force.comのDB(Database.com) Force.com(セールスフォース) セールスフォース
Heroku Ruby(Ruby on Railsなど) PostgreSQL(標準)など Amazon セールスフォース
Amazon Beanstalk Java Amazon RDS(MySQL), Amazon SimpleDBなど Amazon Amazon
Engine Yard Ruby(Ruby on Railsなど) MySQL(標準)など Amazon Engine Yard(いずれAmazon?)

注目すべきはGAEはDBが独自であること、Force.comはApex、VisualForceという独自の言語でアプリケーション構築をする必要があることでしょう。(Force.comのDBは独自といえば独自ですが、RDBの考え方でだいたい操作できます)

それに対して、Amazon上で動くPaaSは言語、DBともに、オンプレミス環境からの差分はかなり少ないと思ってよさそうです。こういった特徴を踏まえたうえで、「よいところ」と「気をつけるべきところ、気になるところ」を私の所感でまとめてみました。

◆ 特徴まとめ

PaaS分類よいところ気になるところ
Google App Engine(GAE) ・アプリケーションサーバだけでなく、データベースまで自動スケールするところ。

・Java/Pythonといった汎用性の高い言語で開発できること

・非常に安い。1日あたりのQuota制限があるが、ある程度のボリュームまでは無料と考えてもよい。範囲を超えても安い。

・個人で勉強しやすい。情報も多いし、安い。
・物理的にどこにデータが置かれているかなどブラックボックス(悪いこととは限らない)で、どう動いているか見通しがきかないことがあること

・BigTableという、RDBとは違う考え方が求められるデータベースを使うため、使いこなすにはかなりの学習コストが発生すること。開発者の確保もやや難しいこと
Amazon系(Heroku、Engine Yard、Beanstalk) ・Java(Tomcat)やRuby on Railsなど、オンプレミスの環境で培われた技術を用いてアプリケーションが構築できること。

・開発者が確保しやすい。

・Amazon EC2、RDS、S3、CloudFrontなどPaaSの構成要素となるコンポーネントが独立したサービスとなっており、自由自在に組み合わせられる。
・GAE、Force.comと比べるとRDBやストレージなどのバックアップ等、ミドル、インフラの運用面的なことを多少意識しないといけないこと

・アプリケーション部分についてはForce.comのように何かベースとなる強力な機能があるわけではないので、その開発コストはオンプレミスに近い感じになること
Force.com系 ・GUI操作(Point&Click)だけで、かなりのカスタム機能が作成でき、型にはまると生産性がかなり高いこと。

・認証系の機能、ユーザの権限制御、ワークフローなどスクラッチ実装をするとけっこう面倒な機能が既に存在すること。

・国内、海外問わずたくさんの大手企業が業務システムに使っており、セキュリティ含め、実績面では信頼しやすい
・Apexなど独自技術の学習コストがかかる

・ストレージ容量やレコード件数、外部からのAPI呼び出しの最大数の制限など、「容量の大きいデータ」、「件数の多いデータ」への制限は強いこと

・ライセンス費用がユーザ単位であり、GAEやAmazon系の課金と違うのは注意が必要なこと

上の色をつけているところが、もっともメリットとして特色があるところです。

◆ 用途に合うと高い効果を出すGAEとForce.com

GAEとForce.comは「制約は強いが、型にはまると高い効果を出す」と考えるとよいと思います。

GAEはデータベースが独自なので「Joinをさける」「集合関数は使わないで、レコードに持つ」などRDBとは違う考え方で開発が必要です。しかし、アプリケーションサーバだけでなく、データベースまでもが自動スケールするので、アクセス量が読めないアプリケーション(ソーシャルアプリなど) では、独自技術を習得するコストを払ってもメリットを得られる可能性があります。

Force.comについては、GAEに比べると書籍等少なく、個人で勉強する人も少なそうなので、知らない人も多そうですが、GAEと同じく型にはまると強いPaaSと考えています。
GAEやAmazon系のPaaSが提供している機能はデータストアやストレージのAPIなど、どんなアプリケーションでも共通で使いそうなものが中心です。それに対して、Force.comは会社などの組織で使うアプリケーション構築に必要な機能が最初から揃っています。たとえば、ユーザの発行、権限管理、ワークフローなど。認証処理とか権限制御など、受託案件では「毎度おなじみ」の機能ですが、けっこう作るのは毎度面倒、な機能です。そういったものが最初からそろっていて、しかも簡単にカスタマイズできるというのは、はまるとすごい生産性です。

実際、フレクトでも案件管理や勤怠管理、経費申請などいくつかの業務アプリをバンバン作っていった実績があります。セールスフォースが得意とするCRMだけでなく、多くの業務系アプリの開発が高い生産性でできる実感を持っています。

一方でForce.comはユーザごとにライセンス費用がかかったり、CPUやストレージをちょっと使うと意外と早く制限がくるなど、特有の制約事項があり、注意しながらの開発が必要です。

両方とも制約が強く、はまると効果テキメンっといった感じですが、学習コストがかかるので開発者のアサインが意外と難しい、といったデメリットがあります。

◆ 既存のオープンな技術をベースにスピーディに作れるAmazon系

HerokuやBeanstalkなどのPaaSはRuby on Rails、Java(Tomcat)、PostgreSQL、MySQLなどのオンプレミス環境でも存在しているオープンな技術をベースとしていて、それらを使ったシステムをすばやく作れるというメリットがあります。アプリケーションサーバ、RDB、ストレージなどはAWSや各PaaSが提供してくれているサービスをそのまま使えばいいので、インフラ、ミドルの心配をせずに、Web開発のスタンダードな技術であるJava、Ruby、MySQLなどを使って開発できるというのがGoodです。オンプレミス環境と同じで、なおかつオープンな技術をベースにしているものが多いので学習コストも低く、開発者のアサインも容易です。

コンシューマが使うWeb系のシステム構築で、とにかく早くリリースしたい、早く作りたい、という場合には、Amazon系のPaaSが有力な選択肢になります。

実際、フレクトでもPaaSではありませんが、Amazon EC2、S3などを使ってモバイルサイト(http://bhmb.jp/)を開発、運用しており、開発時のプラットフォーム選択の決め手はクラウドの恩恵をうけつつ、既存技術をベースにすばやく開発したい、というものでした。

◆ SIer視点からの認知度、信頼度の印象

SIerである私たちにとって、多く接するお客様はユーザ企業の情報システム部門の方々です。そういった企業の方々からも選択肢として認知されているのはセールスフォースがやはり一番という印象です。多くの企業で導入されたということはコンプライアンス観点などからもクリアした案件が多いということで、この辺はお客様に提案するプラットフォームとしてはSIer的にはGoodです。

Amazon系のサービスやGoogle App Engineもまったく認知されていないというわけではないのですが、積極的に選択肢にあがってくるケースが多いかというと必ずしもそうではなさそうな気もします。Amazon系やGAEの事例もサービス企業が内製でそのメリットを活かして作っているケースが多く見受けられます。企業の情報システム部門からの認知度、信頼度という点は、今後の向上に期待というところです。

もちろん、私が知る範囲でもお客様によってはAmazon系やGAEなどの技術に長けていて、すごく活用されているというケースもあります。ただ、全体で見るとまだ低い割合なのかな、と思います。

◆ 今後の気になるところはPHPのPaaS

SI案件というとJava系が多いと思いますが、Web絡みになるとPHPの比重が高くなります。そういう点ではPHP系のPaaSは有名なものは見当たらないですね。注目としてはPHP Fog(http://www.phpfog.com/)が、Heroku的立ち位置を目指しているようなので今後どうなるか気になるところです。

※ 【追記】 AzureでPHPできるとご指摘いただきました。ちょっと調べてみます。

◆ まとめと中途採用募集のお知らせ

VMForceなどリストアップしていながら、あまり言及していないものがあり、すみません。また今度調査してみます。

最後に、フレクトはセールスフォースのプラットフォームやAWSを使ったインテグレーション事業を拡大中です。最新のPaaSを使った開発に興味のある人はぜひご連絡いただければと思います。採用エントリーは以下からです。お待ちしております。

http://www.flect.co.jp/recruit/

2011年1月10日 (月)

Herokuについて調べたことのまとめ

遅くなりましたが、あけましておめでとうございます。
フレクトの大橋です。

フレクトはセールスフォースを使ったシステムインテグレーション事業が
中心事業の1つだったりします。なので、年末年始はセールスフォースが買収した
Heroku(ヘロク)やRubyについて急に勉強を始めました。

忘れないように、年末に年始に勉強したことを備忘録的にまとめておきます。

<1. どんなものか>

乱暴な言い方をすれば、Google App EngineのRuby版です。(乱暴すぎる?)

もっとも違うのは、Ruby, Rails, PostgreSQL、memcachedなどオープンな技術の上に作られており、自分たちのLinuxサーバで動かしたアプリケーションをそのまま動かしやすい環境であることです。

Dynoと呼ばれるWebサーバプロセス数や、データベースの使用する容量などにより課金され、無料の範囲もありますが、Goolge App Engineよりは無料範囲が小さいと思っておいてよいと思います。

<2. Hello, World的なものを動かすには>

とりあえず、Hello, World的なものを動かしたくなります。動かすだけならば以下のすばらしい記事を見ればOKでした。

http://kuranuki.sonicgarden.jp/2009/05/rubypaasherokurails.html

デプロイなどはgitに連動していて、コマンドラインから簡単にできることが体感できると思います。

<3. 構成コンポーネントとリクエストの流れ>

以下の図にあるようなコンポーネントが基本コンポーネントで、
リクエストを順次処理していきます。

Herokuarch

(※ http://heroku.com/how/architecture から図は引用しています)

まず、リクエストはnginxでできているリバースプロキシ(HTTP Reverse Proxy)に到達します。そこから、varnishでできているHTTP Cache層に来ます。

HTTP Cache層ではCache-Controlヘッダなどの内容によりコンテンツキャッシュを
返す機能があり、キャッシュヒットするコンテンツはここでレスポンスとしてユーザに戻します。

HTTP Cache層の次は、Routing Meshです。ここでリクエストを各Dynoにバランシングします。ここはHerokuがErlangで独自実装したミドルウェアのようです。

次にDyno Grid上での各Dynoで動くアプリケーションにリクエストが来ます。マルチテナントなので、Dyno Grid上にはいろいろな人、組織のアプリケーションが動いていますが、適切なDynoにリクエストが送られるよう、Routing Meshでルーティングされています。

なお、Dynoはアプリケーションサーバの1プロセスで、アプリケーションサーバThin(http://code.macournoyer.com/thin/)をベースにしているもののようです。Dynoは追加購入すれば、ユーザは柔軟に増やすことができ、2秒で起動するとのことです。

Dyno上のアプリケーションがリクエストを処理し、必要に応じてDatabaseやMemory Cacheにアクセスします。

Databaseは標準はPostgreSQLで、Memory Cacheはmemcachedが動いています。それぞれ、Dyno上で動くアプリケーションからアクセスできます。

<4. 動かせるアプリケーション>

Rackに対応したアプリケーションであれば動かせます。
RackというのはRubyにおけるWebサーバとフレームワーク(RailsやSinatraなど)との
インタフェースの役割を果たすライブラリです。詳しくは以下で。

http://gihyo.jp/dev/serial/01/ruby/0023

Rackに対応したフレームワークであれば、Heroku上で動くことになります。なので、Railsだけでなく、Sinatraなど他のフレームワークでも動くそうです。

<5. 無料で使える範囲>

1つのアプリケーション、1つのDyno、5MBのデータベース領域であれば無料で使うことができます。個人で勉強する分には十分かと思いますので、いろいろ試してみたいところです。

<6. 魅力的なアドオンがたくさん>

標準では、Dyno(アプリケーションサーバ)、Databaes(PostgreSQL)、Memory Cache(memcached)を使うくらいかもしれませんが、よく見てみるアドオンがたくさんあり、使いたくなるものもいろいろありました。個人的に使いたいと思ったものをいくつか列挙しておきます。

◆ Amazon RDS連携

  EC2上で動いているので当たり前っぽいサービスですが、これは必要ですね。

    http://addons.heroku.com/amazon_rds

 

 

◆ Exceptionトラッキング(通知)

  エラー発生時にメールやTwitterで通知してくれるサービス。運用上こういう
  仕組みを作るのは以外と面倒なので助かります。

    http://addons.heroku.com/exceptional

 

 

◆ Solr

  フレクトでは全文検索などやるときSolrを使っていたりするので、これは
  魅力的です。外部のSolrサービスをWeb経由で提供している会社に
  つながるみたいですが。
  日本語辞書で形態素解析できるのか、など追加の調査は必要ですね。

    http://addons.heroku.com/websolr

 


<まとめと今後>

Rails(Rack)アプリのためのPaaS、"Heroku"について勉強したことを備忘録的にメモにしました。

US-EAST以外にいつ展開されるのか、といったことや、セールスフォースが買収したことにより、どんなサービスが追加されるのか、など今後の動きが気になります。

一部、実験的にnode.jsに対応など始まっており、多言語展開するのかも気になるところです。

実戦投入まではもう少し勉強、検証が必要ですが、海外を中心に実戦投入された事例も多いので、フレクトでも経験積んで実戦で活かす機会が作っていきたいと思います。

しばらく研究してみて、今後、Herokuの記事もたくさん書けるようにしていきたいです。

では、本年もよろしくお願いします。

2010年12月14日 (火)

AWS SDK for JavaでAmazon SimpleDBを使う


前回、Amazon SimpleDBの記事で、コマンドラインから操作する方法を紹介しましたが、
今日はJavaから使う方法を紹介したいと思います。

■ AWS SDK for Java

JavaからAmazon Web Servicesを操作するには、Amazon純正のSDKである
「AWS SDK for Java」を使います。以下からダウンロードできます。

http://aws.amazon.com/sdkforjava/


■ 使うための準備

AWS SDK for Javaの現在のバージョンは1.0.14なので、aws-java-sdk-1.0.14.jarというファイルがダウンロードできると思います。これをクラスパスに通しましょう。
また、CommonsのHTTPクライアントライブラリやCODECライブラリが必要になるので
それぞれ以下からダウンロードしてクラスパスに通しましょう。

http://hc.apache.org/httpclient-3.x/
http://commons.apache.org/codec/


■ 最初にアクセスキー、秘密キーのセットアップ

最初にアクセスキーと秘密キーを指定して、AWSCredentialという認証情報を持つインタフェースを実装しているBasicAWSCredentialsクラスのインスタンスを作成します。
そして、認証情報を引数にしてAmazonSimpleDBClientというのクライアントクラスの
インスタンスを作成します。AmazonSimpleDBClientは同期アクセス版のクライアントです。
非同期版は別にあるのですが、今回は同期版で進めます。

// アクセスキーと秘密キーは任意のものを指定してください。
String accessKey = "xxxxxxxxxxxxxxx";
String secretKey = "xxxxxxxxxxxxxxx";

AmazonSimpleDB sdb = new AmazonSimpleDBClient(new BasicAWSCredentials(accessKey, secretKey));


■ エンドポイントURLでRegionの指定

アメリカ東海岸、西海岸、シンガポールなど、どこのSimpleDBサーバを使うか指定します。

sdb.setEndpoint("sdb.us-west-1.amazonaws.com");

今回はアメリカ西海岸を使うことにします。各Regionのエンドポイントは以下にあります。

http://docs.amazonwebservices.com/AmazonSimpleDB/latest/DeveloperGuide/index.html?Endpoints.html


■ ドメインを作成(CreateDomain)

ここまでで準備ができたのでドメイン作成から始めてみます。
"book"というドメインを作ってみます。以下の通りです。簡単ですね。

sdb.createDomain(new CreateDomainRequest("book"));


■ アイテムを作ってみます(PutAttributes)

"book"というドメインに、キーをISBN(4873110963)として、属性には"name"と"author"を入れて
アイテムを作ってみます。

sdb.putAttributes(new PutAttributesRequest()
.withDomainName("book")
.withItemName("4873110963")
.withAttributes(
new ReplaceableAttribute("name","Programming Perl", true),
new ReplaceableAttribute("author","Larry Wall", true)
)
);

けっこう簡単ですね。


■ アイテムを1件取得します(GetAttributes)

先ほど作成したアイテムを取得します。GetAttributesというAPIを使います。
ドメインとアイテムのキー(ItemName)を指定して取得します。取得できた値は
GetAttributesResultというクラスのインスタンスに格納されるので、以下のように
ループをまわすと属性情報が取得できます。

GetAttributesResult getAttrResult = 
sdb.getAttributes(
new GetAttributesRequest()
.withDomainName("book")
.withItemName("4873110963")
);

// 属性情報を表示します
for (Attribute attr : getAttrResult.getAttributes()) {
System.out.println("name = " + attr.getName() + ", value =  " + attr.getValue());
}


■ Select文でアイテムを取得します。

以下のようにSelect文を指定して、値を取得することができます。
取得できる値はItemクラスのインスタンスに格納されて返って来ます。
これも簡単にいきますね。

String query = "select name, author from book where author like \"Larry%\" ";
for (Item item : sdb.select(new SelectRequest(query)).getItems()) {
    System.out.println("------------");
    System.out.println("Item Name = " + item.getName());
    for (Attribute attribute : item.getAttributes()) {
        System.out.println("\tAttribute");
        System.out.println("\t\tName = " + attribute.getName());
        System.out.println("\t\tValue = " + attribute.getValue());
    }
}


■ アイテムの削除(DeleteAttributes)

あるアイテムの、ある属性でけ削除したい場合はDeleteAttributesというAPIを使います。
bookドメインのあるアイテムの"author"という属性を削除したい場合、以下のように
書きます。

sdb.deleteAttributes(new DeleteAttributesRequest("book", "4873110963")
.withAttributes(new Attribute().withName("author")));

また、あるアイテムをひとつまるごと消したい場合は、以下のように
属性を指定しないで、DeleteAttributesを呼び出します。

sdb.deleteAttributes(new DeleteAttributesRequest("book", "4873110963"));


■ Consistent Readの指定

Amazon SimpleDBでは一貫性読み込みのオプションをつけて、アイテムを読み込むことが
できます。これも非常に簡単でGetAttributesのAPIでwithConsistentReadをtrueに設定するだけです。

sdb.getAttributes(new GetAttributesRequest().withDomainName("book").withItemName("4873110963").withConsistentRead(true));


■ ドメイン削除

最後にドメイン削除です。以下のような感じであっさりです。

sdb.deleteDomain(new DeleteDomainRequest("book"));


■ まとめ

今回はAWS SDK for Javaを使ってAmazon SimpleDBを操作する方法の主要な箇所をだいたい書きました。この記事自体は技術的には内容は薄いですが、簡単なお勉強には役に立つかもしれません。

次回からはAmazon Web Servicesからはちょっと離れたクラウドネタを書いてみようかと
思います。

2010年11月18日 (木)

Amazon SimpleDBをコマンドラインから使う方法

こんにちは、大橋です。

前回、Amazon SimpleDBに関して記事を書きましたが、
今回は実際にSimpleDBに触ってみる方法を書きます。

■ まずはツールの選択

GUIベースのツールでは以下のようなツールがあります。

・AWS Toolkit for Eclipse
     http://aws.amazon.com/eclipse/
・SDB Explorer(有料、試用期間あり)
     http://www.sdbexplorer.com/

最初のものはAmazon純製ですね。
また、CUIでは以下のようなものがあります。

・Amazon SimpleDB command line interface(amazon-simpledb-cli)
 http://code.google.com/p/amazon-simpledb-cli/

他にもツールはいろいろあると思いますが、サーバ管理者としては
CUIベースでできるものがほしいので、まずはamazon-simpledb-cli
を使ってAmazon SimpleDBを操作できるようになりたいと思います。

■ amazon-simpledb-cliのインストール

【モジュールのインストール】

amazon-simpledb-cliはPerlでできています。
最初に必要な以下のモジュールをインストールします。

  • Getopt::Long
  • Pod::Usage
  • Digest::SHA1
  • Digest::HMAC
  • XML::Simple

cpanmでインストールすると簡単です。以下のようにcpanmコマンドを実行すると
インストールできます。簡単ですね。

 > cpanm XML::Simple

cpanmの使い方インストール方法は以下が分かりやすいので参考にしてみてください。
http://www.omakase.org/perl/cpanm.html

 【Amazon SimpleDB用のPerlモジュールのインストール】

次にAmazon SimpleDB用のモジュールのインストールをします。
モジュールをダウンロードして、以下のようにコマンドを打ってインストールします。

> curl -Lo amazon-simpledb-perl-library.zip http://amazon-simpledb-perl-library.notlong.com
> unzip amazon-simpledb-perl-library.zip
> sitelib=$(perl -MConfig -le 'print $Config{sitelib}')
> sudo cp -r AmazonSimpleDB-*-perl-library/src/Amazon $sitelib/

これでモジュールセットアップは完了です。

 【simpledbコマンドのインストール】

> sudo curl -Lo /usr/local/bin/simpledb http://simpledb-cli.notlong.com
> sudo chmod +x /usr/local/bin/simpledb

なお、simpledbコマンドの1行目は 「#!/usr/bin/perl」 となっています。
必要に応じて「#!/usr/bin/env perl」などと書き換えてください。

【環境変数のセットアップ】

コマンドとして実行したり、.bashrcに記載するなどして以下のようにAmazon SimpleDBのアクセスキーと秘密キーをセットアップしておいてください。

export AWS_ACCESS_KEY_ID='xxxxxxxxxxxxxxxxx'
export AWS_SECRET_ACCESS_KEY='xxxxxxxxxxxxxxxxxxxx'

【インストールできているか確認する】

PATHが/usr/local/binに通っている場合は以下のようにコマンドを打つと
ちゃんと実行され、ヘルプがでます。/usr/local/bin/simpledb とコマンドを
打ってもOKです。

> simpledb
Usage:
     simpledb [opts] create-domain DOMAIN
     simpledb [opts] delete-domain DOMAIN
     simpledb [opts] list-domains

     simpledb [opts] put         DOMAIN ITEM [NAME=VALUE]...
     simpledb [opts] put-replace DOMAIN ITEM [NAME=VALUE]...
     simpledb [opts] get         DOMAIN ITEM [NAME]...
     simpledb [opts] delete      DOMAIN ITEM [NAME[=VALUE]]...

     simpledb [opts] select SELECTEXPRESSION

Options:
     --help         Print help and exit.

     --aws-access-key-id KEY
                    AWS access key id
                    [Defaults to $AWS_ACCESS_KEY_ID environment variable]

     --aws-secret-access-key SECRETKEY
                    AWS secret access key
                    [Defaults to $AWS_SECRET_ACCESS_KEY environment variable]

     --max COUNT
                    Maximum number of domains/items to retrieve and list.
                    [Defaults to all]

     --separator STRING
                    Separator between attribute name and value.
                    [Defaults to equals (=)]

Arguments:
     DOMAIN            Domain name
     ITEM              Item name
     NAME              Attribute name
     VALUE             Attribute value
     SELECTEXPRESSION  SimpleDB select expression

■ amazon-simpledb-cliを使ってみる】

【コマンド書式】

基本的な書式は以下です。

> simpledb コマンド名 ドメイン名 値

【ドメイン作成】

書籍(book)ドメインを作ってみましょう。以下のようにすればドメインが作成できます。

> simpledb create-domain book

【値を何かputしてみる】

putコマンドで書籍(book)ドメインに書籍アイテムを一つ入れてみましょう。Itemの主キーとなる部分にはITEM名には
ISBN(4873110963の部分)を登録します。その他は書籍名(name)、値段(price)、著者名(author)をいれます。

> simpledb put book 4873110963 name='Programming Perl' price=5565 author='Larry Wall'

【アイテムの属性(Attribute)に2個目の値を入れてみる】

SimpleDBで1つの属性に複数の値を入れることができます。以下のようにすれば、2つ目の値が入ります。
主キーとなる部分にはISBNを指定し、追加する属性のところだけ値をいれます。

> simpledb put book 4873110963 author='Tom Christiansen'

【アイテムを更新する】

アイテムの属性に値を追加するのではなくて、アイテムそのものを入れ替える場合は以下のようにput-replacekコマンドを使います。

> simpledb put-replace book 4873110963 name='Programming Perl' price=5565 author='Larry Wall'

【Select文でアイテムを取得する】

以下のようにSelect文でアイテムの情報が取得でき、出力が得られます。
アイテムごとの最初の行がITEMのキー(この場合はISBN)です。

> simpledb select 'select name, price, author from book'
4873110963   # ISBN(主キーの部分)
author=Larry Wall
author=Tom Christiansen
price=5565
name=Programming Perl

以下のようにLike文などSQLっぽいクエリを投げることができます。

> simpledb select 'select name, price, author from book where author like "Larry%" '

likeや=, >, <, OR, ANDなどいろいろな演算子が使えます。詳しくは以下あたりから
情報をたどるといろいろなクエリが分かります。

http://docs.amazonwebservices.com/AmazonSimpleDB/latest/DeveloperGuide/index.html?UsingSelect.html

機会があれば、もう少し丁寧にクエリを解説したいですが、今回はスキップします。

【アイテムをgetする】

以下のようにITEMのキーを指定して、アイテムを1つ取得することができます。

> simpledb get book 4873110963 
author=Larry Wall
author=Tom Christiansen
price=5565
name=Programming Perl

【アイテムを削除する】

以下のようにITEMのキーを指定して、アイテムを1つ削除できます。

> simpledb delete book 4873110963

【ドメインを削除する】

最後にドメインの削除です。以下のようにdelete-domainコマンドで削除できます。

> simpledb delete-domain book

【まとめ】
以上がAmazon SimpleDBをコマンドラインから使う方法の紹介です。

一通りこれだけのコマンドが分かっていれば、デバッグするなど簡単な
オペレーションはだいぶ便利になると思います。

次回はJavaでAmazon SimpleDBを操作してみたいと思います。また、Consistent ReadやConditional Put/Deleteについても近いうちに書いてみるつもりです。

2010年11月16日 (火)

Amazon SimpleDBについて調べたことをまとめました

こんにちは。大橋です。

最近、セールスフォース関連の仕事でAmazon SimpleDBの話題がでることがあったのですが、
EC2やS3に比べると情報が少ないなぁ、というのを実感しました。

そこで、SimpleDBについていろいろ勉強してみました。ただ、量が多いので分割して
記事にしたいと思います。今回の記事ではSimpleDBとは何かということ、RDBと比較しながら
データモデルの説明、そしてどのような操作(API)があるのか、制約、メリットなど、
調べたことをまとめたいと思います。

【SimpleDBとは?】

SimpleDBはHTTPベースのAPI(REST/SOAP)で操作できる構造化されたデータストアです。
Amazonのページによると以下のように説明があります。

Amazon SimpleDB は可用性、拡張性、柔軟性の高い、非リレーショナル型データストアで、
データベース管理の負荷を軽減します。開発者は簡単なwebインターフェイスを使ってデータの保存や参照を行うだけで、
後はAmazon SimpleDB が残りの部分を担当します。

RDBではないのですが、ある程度構造化されたデータをHTTPベースのAPIで
簡単に扱うことができるデータベースというところです。

では、中身を追っていきます。

【データモデル】

Amazon SimpleDBのデータモデルをRDBと比較しながら説明します。

例として以下のような書籍データベースを考えてみます。
RDB的には以下の表そのものがテーブルに該当します。フィールドは書籍名(Name)、価格(Price)、商品のURL(URL)、著者名(Author)で、主キーにあたるところがISBN(Item Name)にあたると考えてください。

Simpledb_2


SimpleDBでは、上記の表のようなデータについて以下のように考えます。

(やや乱暴な言い方ですが、)RDBのテーブルに該当するのが「ドメイン」です。上記の表の1レコード1レコードは1つのアイテムです。
アイテムにはアイテムを一意に決めるユニークなキーがあります。それがItemのNameです。
ここはユニークでないといけません。この書籍のデータではISBNを入れています。

アイテムは複数の属性(Attribute)を持ちます。これが書籍名(Name)、価格(Price)、商品のURL(URL)などのフィールド(カラム)に該当します。各属性には名前と値があり、Price(名前)=3780(値)というように指定します。また、値はすべて文字列で、インデクシングされます。RDBならば各属性には1つの値しか入れることはできませんが、SimpleDBでは1つの属性に複数の値を入れることができます。上記の表では著者名(Author)が該当します。

なんとなく分かりましたでしょうか。乱暴な言い方をすれば、以下のように考えればよいかと。

  • テーブルがドメイン
  • RDBのレコードにあたるものがアイテム(Item)
  • 主キーにあたるところがItem Nameでドメイン内ではユニークでないといけない
  • 各フィールド(カラム)のことは属性(Attribute)という。
  • 1つのアイテムのある属性の値は複数持つことができる
  • 属性の値は文字列だけ。すべての値はインデクシングされる。


【SimpleDBの機能】

次に、SimpleDBがアプリ開発者に提供している機能を紹介します。ドメイン操作に関することと、アイテムなどデータを操作に関することの大きく2つの機能群があるのでそれぞれ説明します。

ドメイン操作

ドメイン操作には以下の4種類の機能がAPIとして提供されています。

  • CreateDomain

        ドメインを作成します

  • DeleteDomain

        ドメインを削除します

  • ListDomains

        アクセスキー、秘密キーでアクセスできるドメインのリストをできます。

  • DomainMetaData

        ドメイン名、ドメイン内のアイテム数や属性値の数など、ドメインに関するメタ情報を取得できます。

データ(Item)操作

データ操作には以下の操作がAPIとして提供されています。

  • PutAttributes

        アイテムと属性を登録するか、アイテム名を指定して属性を登録/更新します。

  • GetAttributes

        アイテムのNameを指定して、アイテム情報を1件取得できます。

  • BatchPutAttributes

        複数のアイテムをまとめて登録/更新できます。(1回の操作で25件)

  • Select

        SimpleDB用のselect文でアイテムを取得できます。

  • DeleteAttributes

        アイテムから属性を削除します。また、アイテムそのものを削除します。

  • BatchDeleteAttributes

        複数のアイテムについて属性削除からアイテムそのものを削除します。

【ドメイン/アイテムに関する制約事項、気をつけるポイント】

ここまで、「どんなことができるか」を簡単に説明してきましたが、それなりに制約もあります。

以下に気をつけたほうがいい制約事項を列挙します。

  • APIのリクエストサイズは1MBを超えることはできません。(BatchPutAttributesあたりで関係します)
  • 1つのアイテムにつき、属性は最大256個までです。
  • 1つのドメインに10億アイテムまで格納できます。つまり、それを超えた場合はドメイン名を変更するなど対処が必要です。
  • ドメインごとに最大10GBのユーザデータを持つことができます。
  • 1つのアカウントにつき100件のドメインを作成できます。ただし、AWSのサポートに連絡すれば追加ドメイン作成もお願いできるようです。※ http://aws.amazon.com/contact-us/simpledb-limit-request/ でお願いできるみたいです。
  • 1つのクエリ(select)で取得できるアイテム数は最大2500です。
  • RDBではないので、joinはできません。工夫してデータモデルの設計を行いましょう。
  • RDBのようにスキーマを事前に定義するわけではありません。いわゆるスキーマレスなデータベースになります。

それと、Wikipediaに以下のように記載がある通り、CAP定理に置ける一貫性は成立していないです。この辺がクラウド的(?)です。

CAP定理において、一貫性が成立していなく、それゆえ、書き込みをしても、一貫性読み込みを指定しない限り、読めるようになるまで1秒程度以下の時間がかかる。


【うれしいポイント】

制約も説明したので、個人的にうれしいと思っているポイントも列挙しておきます。

  • 管理が簡単

        インストールとかセットアップとかほとんど不要です。

        バッファとか一所懸命調整しなくても十分なパフォーマンスが出ます(出るらしいです)。

  • 高い可用性

        Amazon S3やSQSと同じように高い可用性があります。

        データは地理的に分散された環境の保存されるのでMySQLで

        一所懸命レプリケーション設定する、みたいなことはしなくてよいです。

  • EC2と使うのであれば高速

        同一リージョンであればLAN内アクセスと同程度の遅延でアクセスできます。

  • HTTPベースなのでEC2以外からも容易にアクセスできる

        オンプレミスの環境やセールスフォースなど他のクラウド環境からも

        REST/SOAPのAPIを通じて簡単にアクセスできます。

        SimpleDBを介したデータ連携なども容易にできます。
        (注意しないとセキュリティ上危険なことにもなりそうですが)

  • すごく安い

        あとで説明しますが、すごく安いです。

        Amazonのデータベースサービスでは他にAmazon RDSが
        ありますが、それと比べてもずっとずっと安いです。

【課金体系】

詳細は以下を見てください。安いです。

http://aws.amazon.com/jp/simpledb/#pricing

US価格だとデータ転送は送信に限り、0.15ドル/GB(US価格)、データ保存は1ヶ月に0.25ドル/GBです。それぞれ最初の1GBは無料です。それと、PUT/GET/Selectなどのクエリを実行するのに使ったSimpleDBのマシン稼働時間も課金対象です。毎月、最初の25時間は無料で、そのあとは1時間あたり0.140ドルです。

【まとめ】

今回はSimpleDBについてその概要的なことを説明しました。
joinができない、スキーマレス、一貫性、あたりにとまどいが出てしまう面はありますが、
簡単に使えて、Amazonクォリティの可用性があるデータベースということで、けっこう魅力があると思っています。特に、EC2だけでなく多様な環境が入り交じったときなどにHTTPベースのAPIで操作できることは大きなメリットがあるのではないかと考えています。

次回からはコマンドラインでの使い方やプログラムからの使い方など
より実戦で使いそうな内容を書いていきたいと思います。

2010年10月28日 (木)

AWS SDK for JavaでAmazon SQSを使う

前回、Amazon SQSの記事で、Perlから使う方法を紹介しましたが、今日はJavaから
使う方法を紹介したいと思います。

というのはフレクトでは、Web系のアプリケーション構築はJavaで作ることが多いからです。
Perlはサーバの運用・管理のツールとして使うケースが多いです。

なお、Amazon SQSの本ブログでの紹介は以下のページを参照してください。

http://blog.flect.co.jp/cto/2010/09/amazon-sqs-4938.html

■ AWS SDK for Java

JavaからAmazon Web Servicesを操作するには、Amazon純正のSDKである
「AWS SDK for Java」を使います。以下からダウンロードできます。

http://aws.amazon.com/sdkforjava/

他にもPHP、Ruby、.NETなどの純正SDKがあります。

■ 使うための準備

AWS SDK for Javaの現在のバージョンは1.0.14です。aws-java-sdk-1.0.14.jarというファイルが
ダウンロードできると思います。これをクラスパスに通しましょう。

また、CommonsのHTTPクライアントライブラリやCODECライブラリが必要になるので
それぞれ以下からダウンロードしてクラスパスに通しましょう。

http://hc.apache.org/httpclient-3.x/
http://commons.apache.org/codec/

これで、コードを書き始められます。

■ 最初にアクセスキー、秘密キーのセットアップ

最初にアクセスキーと秘密キーを指定して、AWSCredentialという認証情報を持つインタフェースを実装しているBasicAWSCredentialsクラスのインスタンスを作成します。
そして、認証情報を引数にしてAmazonSQSClientというSQSのクライアントクラスの
インスタンスを作成します。

ちなみに、この手順はAmazonS3Clientなどでも同じような手順になります。
AWSCredentialを実装しているクラスにはPropertiesCredentialというプロパティファイルに
キー情報を保持して、それを読み取る実装クラスもあります。

String accessKey = "xxxxx"; // アクセスキーの設定
String secretKey = "xxxxx"; // 秘密キーの設定
// SQSのクライアントを作成。
AmazonSQS sqs = new AmazonSQSClient(new BasicAWSCredentials(accessKey,secretKey));

■ エンドポイントURLでRegionの指定

アメリカ東海岸、西海岸、シンガポールなど、どこのSQSサーバを使うか指定します。

// アメリカ西海岸を指定する。
sqs.setEndpoint("sqs.us-west-1.amazonaws.com");

ちなみに各Regionの指定は以下のURLです。

・アメリカ東海岸(US-East):sqs.us-east-1.amazonaws.com
・アメリカ西海岸(US-West):sqs.us-west-1.amazonaws.com
・シンガポール(Asia Pacific):sqs.ap-southeast-1.amazonaws.com
・ヨーロッパ(EU):sqs.eu-west-1.amazonaws.com

■ キューを作成する

エンドポイントを作成したら、いよいよキューを作成しましょう。以下のようにさくせいする。
視認性の秒数は、あるクライアントがキューのメッセージをReceiveしたときに、ここで指定した
秒数分は他のクライアントからReceiveできない(見えなくなる)、というものです。デフォルトは
30秒です。キューのURLはこのあと、メッセージの受け渡しをするときに使います。

// キュー作成のリクエスト作成。第2引数は視認性の秒数。
CreateQueueRequest createQueueRequest = new CreateQueueRequest("FlectQueue", 30); // キューを作成する。 CreateQueueResult createQueueResult = sqs.createQueue(createQueueRequest); // キューのURLを取得。この後のリクエストで使います。 String queueUrl = createQueueResult.getQueueUrl();

■ メッセージをキューに送信する

以下のように、SendMessageRequestクラスでリクエスト用のインスタンスを設定し、先ほど作成したキューのURLを指定します。そして、メッセージ内容を setMessageBody で指定して、最初に作成した
AmazonSQSClientのインスタンス(sqs)からメッセージをキューに送信します。

SendMessageRequest sendMessageRequest = new SendMessageRequest();
// 作成したキューURLを指定する。
sendMessageRequest.setQueueUrl(queueUrl);
// メッセージ内容をリクエストにセットする。
sendMessageRequest.setMessageBody("Hello, World");
// キューにメッセージを入れる。メッセージ結果を取得するとメッセージIDを取得できます。

SendMessageResult sendMessageResult = sqs.sendMessage(sendMessageRequest);

System.out.println(sendMessageResult.getMessageId());

■ キューからメッセージを受信し、処理が終わったら削除する

キューに入っているメッセージは他のワーカープロセス等で処理するのが一般的だと思います。
メッセージを取得する側を書いてみます。途中まではメッセージ送信と同じですね。
受信側特有なのは receiveMessageRequest.setMaxNumberOfMessages の部分で、メッセージ取得数をセットできる部分です。リクエスト送信後はforループにあるように、最大で指定した数分のメッセージを取得し、その結果をハンドリングできます。

取得したメッセージからは MessageクラスのgetReceiptHandle()メソッドを使うことで
メッセージのReceiptHandleを取得できます。メッセージに対応する処理が終わったら、
このReceiptHandleを指定して、キューからメッセージを削除します。
メッセージを削除しないと、キュー作成時に指定した視認性の秒数を経過したら、他のクライアントから同じメッセージを取得できてしまうので、きちんと削除したほうがよいです。
(ただ、同じメッセージを取得してもシステムとして挙動がおかしくならないようにはしないといけません)

// リクエストクラスのインスタンスを作成。
ReceiveMessageRequest receiveMessageRequest = new ReceiveMessageRequest();
// キューのURLをセット。
receiveMessageRequest.setQueueUrl(queueUrl);
// 1回のリクエストで取得できるメッセージの最大数を指定。
receiveMessageRequest.setMaxNumberOfMessages(10);
// メッセージ取得。
ReceiveMessageResult receiveMessageResult = sqs.receiveMessage(receiveMessageRequest);

// getMessagesで複数のメッセージのリストが返ってきます。
for (Message message : receiveMessageResult.getMessages()) {
    // ReceiptHandleはメッセージの削除を行うために必要になるハンドルです。 
    System.out.println("ReceiptHandle : " + message.getReceiptHandle()); 
    System.out.println("MessageId : " + message.getMessageId());
    System.out.println("MessageBody : " + message.getBody());

    // ここで何かしらのメッセージに対する(重めの)処理をします。
    doSomething();

    // 処理が終わったらキューからメッセージを消します。
    DeleteMessageRequest deleteMessageRequest = new DeleteMessageRequest();
    // QueueのURLを設定します。
    deleteMessageRequest.setQueueUrl(queueUrl);
    // ReceiptHandleを設定します。
    deleteMessageRequest.setReceiptHandle(message.getReceiptHandle());
    // そして、メッセージの削除をします。
    sqs.deleteMessage(deleteMessageRequest);
}

■ with***メソッドを使ってコンパクトにキュー操作処理を呼び出す

ここまでの例はキュー作成、メッセージ送信、メッセージ受信、いずれもだいたい以下の流れで処理をしてました。

 (1) リクエストクラスのインスタンス作成(****Requestクラスをnewする)
 (2)  リクエストインスタンスにキューURLなどパラメータをセット(set***メソッド)
 (3) AmazonSQSClientインスタンスのcreateQueue, sendMessageなどのメソッドでリクエストインスタンスを指定し、実行

この流れを、リクエストクラスのwith****メソッドを使うことでコンパクトにできます。
以下にメッセージ送信を例に紹介します。

SendMessageResult sendMessageResult = sqs.sendMessage(
    new SendMessageRequest()
    .withQueueUrl(queueUrl)
    .withMessageBody("Hello World")
    );

少しコンパクトになった感じがしますね。

■ まとめ

AWS for Javaを使ってAmazon SQSを操作する方法を書きました。Amazon純正のSDKだけあってS3など他のサービスについても使い方に統一感があり、何かと使いやすいです。

このブログでPerl関連でサンプルを書いていたのですが、社員がJava好きが多いので、
S3、EBS、IAMなど他のサービスについても調査をしてなるべくJavaで使い方など
ブログに書いていきたいと思います。

■ 参考リンク

http://aws.amazon.com/articles/3586
http://docs.amazonwebservices.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/

2010年9月30日 (木)

Amazon SQSに入門してみました

こんにちは。大橋です。

今日はAmazon SQSについてです。

サイトを運営していると、ときどきメッセージキューで非同期に
処理をしたいなという箇所がよくあります。

また、最近、当社ではセールスフォースとAmazon EC2の併用など、異なる
クラウド環境を使ったシステムをを扱っており、その連携方法を日々調査しています。

1箇所のサーバ環境だけならば、GearmanやQ4Mなど自前インストール型のキュー
使えばよいかと思うのですが、クラウド環境間の連携などを考えると、
グローバルに利用できるメッセージ伝達方式の方が望ましいケースもあります。

そこで、今回Amazon SQSに触手を伸ばし、入門してみました。
今日は、その記録を残します。

【Amazon SQSを利用開始する】

Amazon Web サービスのアカウントにサインアップし、
Amazon SQS
のページで「Amazon SQSの利用を申し込む」
をすればOKです。

【料金はすごく安い】

課金はリクエスト数によるものととデータ転送量によるものの2系統です。

リクエスト課金は 10,000回のAmazon SQSリクエストに付き0.01ドル。
ほとんどお金かかりません。

データ転送量は米国&欧州とアジア(シンガポール)で異なりますが、
たとえば、米国&欧州では10TB(テラバイト!!)までのデータ受信で
0.15ドル。同一RegionでEC2と送受信するものは課金されません。

すごくすごく気軽に使える値段です。(個人で利用しても気にならない価格です)

【少ないAPIで使えるシンプルな設計】

機能が少ないともいえますが、シンプルに使えます。

だいたいのことはには、以下の4つを使ってできます。

(1) CreateQueue    :  メッセージキューを作成する
(2) SendMessage   : メッセージキューにメッセージを送信
(3) ReceiveMessage  : メッセージキューからメッセージを受信
(4) DeleteMessage  : メッセージキューからメッセージを削除

もちろん、他にもAPIはいろいろありますが、ちょっと試すだけならば
これでOKです。

キューを作成したあと、以下の絵のような流れで処理をすることになります。
Amazon SQSではメッセージは8192バイトが最大なので、もし大きなデータを
渡したい場合はAmazon S3やAmazon SimpleDBなど外部のデータストアに置いて
おき、そのポインタをメッセージに入れるのがよいです。

Sqs

【メッセージ保存期間と視認性について】

メッセージは4日間、キューに保存されます。

また、あるクライアントがReceiveMessageしたあとは、他のクライアントは一定期間、
同一のメッセージが見えなくなります。

見えなくなる時間(視認できなくなる時間)はAPI経由で設定でき、30秒から12時間まで
設定できます。

もしAというクライアントがメッセージαを取得したあと、なにかしらの処理に
失敗した場合、メッセージαは、一定期間(30秒~12時間)のあとに、他のクライアントから
見えるようになります。

もちろん、そのAというクライアントが処理に成功し、メッセージ削除APIを
キューに対して呼び出した場合は、その後、他のクライアントから見えなくなります。

【使い方 ~Perlで実際に使ってみる~】

PHP編やJava編はいずれ機会があったら書きます。
とりあえず、Perlから使ってみます。

先ほどの絵でいうところのSendMessageする側(Process1)が「メッセージ送信側」、ReceiveMessageする側が「メッセージ受信側」(Process2)とします。

やりとりするメッセージはサンプルなので「Hello, World」とします。
メッセージ送信側がキューに対して'Hello, World'とメッセージをいれ、
メッセージ受信側はそのメッセージをキューから取得、画面に表示して
キューからメッセージを削除しています。

実運用ではメッセージは処理を依頼する内容やデータのポインタになります。
また、メッセージ受信側では、時間がかかる処理をするなど、なにかしらの
処理をします。

なお、Perlから使うにはモジュールのインストールが必要です。Amazon::SQS::SimpleというモジュールがCPANにありますので、サンプルプログラムを使うには以下のモジュールをインストールしてから実行する必要があります。

Amazon::SQS::Simpleモジュール

以下、サンプルプログラムです。

・メッセージ送信側

#!/usr/bin/env perl                                                                                                                       
# sqs_msg_sender.pl                                                                                                                       

use strict;
use warnings;

use Amazon::SQS::Simple;

my $access_key = $ENV{AWS_ACCESS_KEY};
my $secret_key = $ENV{AWS_SECRET_KEY};

# SQSオブジェクトを作成します。                                                                                                           
my $sqs = new Amazon::SQS::Simple( $access_key, $secret_key );

# キューを作成します。作成済みの場合に実行してもそのままキューがある状態になります。                                                      
my $q = $sqs->CreateQueue('sample_flect_queue');

# キューにメッセージを送付します。                                                                                                        
$q->SendMessage('Hello World');

exit 0;

・メッセージ受信側

#!/usr/bin/env perl                                                                                                                       
# sqs_msg_receiver.pl                                                                                                                     

use strict;
use warnings;

use Amazon::SQS::Simple;

my $access_key = $ENV{AWS_ACCESS_KEY};
my $secret_key = $ENV{AWS_SECRET_KEY};

# SQSオブジェクトを作成します。                                                                                                           
my $sqs = new Amazon::SQS::Simple( $access_key, $secret_key );

# キューオブジェクトを取得します。                                                                                                        
my $q = $sqs->CreateQueue('sample_flect_queue');

# キューからメッセージを取得します。                                                                                                      
my $msg = $q->ReceiveMessage();

# メッセージの内容を出力してみます。                                                                                                      
print $msg->MessageId() . "\n";
print $msg->MessageBody() . "\n";

# キューからメッセージを削除します。ReceiptHandleというのを使います。                                                                     
$q->DeleteMessage( $msg->ReceiptHandle() );

exit 0;


【すぐに使えて高い信頼性があることについて】

メッセージキューは機能は非常にシンプルですが、同じようなキューを
自前で構築して、Amazon SQS並みの信頼性を保とうと思うとけっこう大変です。

たとえば、Q4MのようにMySQLを使うタイプのメッセージキューを自前で
構築した場合、1台くらいサーバが落ちてもメッセージをロストすることなく、
なおかつ、クライアントからのメッセージ送受信のリクエストをさばきつづける、
となると、必要な構築コストはかなり大きいです。

複数台のサーバが必要で、MySQLのレプリケーションをしたり、あるいは
DRBDで複数台のデータを同期させたり・・・、とかとか。ちょっと手間がかかりますね。

その点、Amazon SQSはAmazonが複数のサーバやデータセンターで冗長化していて大量のリクエストが来ても、ちゃんと止まらずにさばいてくれます。

そういったメッセージキューシステムを自前で作らなくても
すぐに本番システムレベルの信頼性で使える、というのは場合によっては
大幅なコスト削減になるんではないかと思います。

もちろん、パフォーマンス面など適合しないケースもあるかと思いますが、
クラウドな環境ではひとつの選択肢になるのではないかと考えています。

【制限や注意事項もあります】

基本的な注意事項は「メッセージ保存期間と視認性について」のところで
書いたとおりのこと、それと、メッセージが8192バイトが最大なので、
大きいデータの受け渡しが必要なときはS3などにデータをおき、その
ポインタ情報(URL)をやりとりするように、ということがあります。

その他に重要なポイントとしては

 (1) 同一のメッセージが複数回受信できてしまうことがある。
 (2) メッセージはキューに入れた順番どおりには受信できない。

ということです。

これはAmazon SQSが複数のサーバや複数のデータセンターを使って
運営されているためのようですが、注意が必要です。

(1)については場合によっては、Amazon SQS以外のデータストア
(Amazon SimpleDBなど)にどこまでのメッセージ処理ができたか、
などの情報を持っておく必要があります。
その辺はシステムの要求などによりケースバイケースだと思いますが、注意が必要です。

【まとめ&今後取り組むこと】

初期調査、入門だけなのに、記事が少しながくなってしまったので、今日は
これくらいにしておきます。

現在、私が行っているAmazon SQSの調査の最終ゴールは当社が現在力を入れている
Saleforceのシステムと連携させてみることです。

ちゃんと連携できたらまた記事にしますので、待っていてください。

なお、当社はAmazon Web Servicesに力を入れると同時に、Salesforce事業も
展開中です。現在、こういったいろいろなクラウドプラットフォームを使って
お客様によいソリューションを提供したい、というエンジニアの方を
大募集中です。もし、興味のある方は以下からご連絡いただけると幸いです。

http://www.flect.co.jp/recruit/index.html

2010年9月24日 (金)

Net::Amazon::EC2でEC2 API Toolsより高速にEBSのスナップショットを取得

こんにちは。フレクト 大橋です。

前回、EBS上に置いたMySQLのバックアップを取得する方法を紹介しましたが、
EC2 API Toolsを使ったEBSのスナップショット取得に5秒くらいかかってしまう
欠点がありました。
(※ 5秒かかるのは私たちが使っているベターホームレシピ(http:bhmb.jp)でのことで
 他の環境ではどうかは分かりませんが、それなりにかかると思います)
前回紹介した方法ではスナップショット取得中はファイルシステムへの書き込みを
ブロックしているので、運用中のサービスによっては5秒程度ブロックされるが嫌だったり
することもあると思います。
 
ところが以下を見てみると、スナップショット取得にEC2 API Toolsの
「ec2-create-snapshot」コマンドを使うより、PerlでNet::Amazon::EC2モジュールを
使った方が高速にスナップショット取得ができそうとのことなので
やってみました。
 
 
■ Net::Amazon::EC2を使ったEBSスナップショットの取得
 
cpanからNet::Amazon::EC2モジュールをインストールしてください。
cpanコマンドを使えば簡単にできると思います。Mooseが入っていないと
Mooseのインストールも必要になるため、若干時間がかかるかもしれません。
 
インストールしたあと、以下のようなスクリプトでEBSのスナップショット取得ができます。
Volume IDは各自の環境のものをご利用ください。またAmazon Web Serviceのアクセスキー、秘密鍵なども各自の環境のものをご利用ください。
 
#!/usr/bin/env perl
# ebs_snapshot.pl

use strict;
use warnings;

use Net::Amazon::EC2;

my $aws_access_key = $ENV{EC2_ACCESS_KEY};
my $aws_secret_key = $ENV{EC2_SECRET_KEY};
my $volume_id      = 'vol-xxxxxxx';

my $ec2 = Net::Amazon::EC2->new(
    AWSAccessKeyId  => $aws_access_key,
    SecretAccessKey => $aws_secret_key,
    region          => 'us-west-1',
);

my $snapshot = $ec2->create_snapshot(
    VolumeId    => $volume_id,
    Description => 'snapshot by Net::Amazon::EC2',
);

exit 0;
 
■ EC2 API Toolsとの比較
 
EC2 API Toolsを使うと以下のようなコマンドでスナップショットが取れます。
Volume IDに各自の環境のものをいれます。
 
> ec2-create-snapshot -d 'スナップショットの説明'  Volume-ID
 
EC2 API Toolsで私ども環境でEBSのスナップショット(40GB)を取得してみると、
timeコマンドでの計測ではだいたい4秒から5秒くらいかかっています。
環境はus-west-1のEC2上のインスタンスを使いました。(一部出力を省略しています)
 
【1回目】
# time ec2-create-snapshot -d command-line-test-01 vol-xxxxx
real     0m5.020s
user     0m4.408s
sys     0m0.205s
 
【2回目】
# time ec2-create-snapshot -d command-line-test-02 vol-xxxx
real     0m4.696s
user     0m4.603s
sys     0m0.151s
 
【3回目】
# time ec2-create-snapshot -d command-line-test-03 vol-xxxx
real     0m4.479s
user     0m4.590s
sys     0m0.165s
 
次にNet::Amazon::EC2を使ったスクリプトで計測してみました。
スクリプトは先ほど説明したPerlのスクリプトで、ebs_snapshot.plとしています。
EC2 API Toolsで計測した環境と同じ環境で試してみました。
 
【1回目】
# time perl ebs_snapshot.pl
real     0m1.256s
user     0m0.747s
sys     0m0.050s
 
【2回目】
# time perl ebs_snapshot.pl
real     0m1.468s
user     0m0.848s
sys     0m0.041s
 
【3回目】
# time perl ebs_snapshot.pl
real     0m1.331s
user     0m0.792s
sys     0m0.021s
 
だいたいこっちは1.2秒〜1.4秒くらいのスピードでできました。
EC2 API Toolsより3倍〜4倍くらいのスピード。計測方法が若干いい加減ですが、
速くなるのは間違いなさそうです。
こっちを使えば、バックアップ時に書き込みロックの時間を少し軽減できそうです。
また、コマンドライン操作でもストレスが減りますね。
 
■ なぜ速いのか&まとめ
 
詳細を調査したわけではないですが、単純にEC2 API ToolsはJavaでできていて
コマンドラインで実行すると起動すると実処理に入るまでが時間がかかることが
大きいです。あとはNet::Amazon::EC2はQuery APIを使っていて、EC2 API Toolsが
SOAPを使っているのも遅くなる要因にはあると思いますが、実時間がどれくらい
差があるのかは分かりません。
 
Amazon Web Servicesを操作するコマンドで、よく使うものは
Perl, Rubyなど起動の軽いスクリプトでQuery APIを使って運用ツールを作った方
が長期的には何かとストレスが小さいかな、と思います。
 
フレクトではAmazon Web Servicesを使ったプロダクトやソリューション事業を積極的に
実施しています。興味のある方はいつでも以下からご連絡ください。
 

2010年9月22日 (水)

EC2でEBS上のMySQLのデータをバックアップ

こんにちは。フレクトの大橋です。

ベターホームレシピ(http://bhmb.jp)では、MySQLを会員やレシピデータ用の
インスタンスと、Cicindela用のインスタンスを同一のサーバにそれぞれ
データをEBSに置いて運用しています。

レプリケーションなど信頼性向上のための施策をしているのですが、
運用上大事なのはバックアップです。

そこで、今日はEBS上のMySQLのデータのスナップショットを
整合性を失わずにバックアップする方法についてベターホームレシピでの
実運用の事例をもとに紹介します。

■ 本題の前に・・・、Amazon RDSについて

そもそも直接MySQLをEC2上にインストールしなくても、日々機能が強化されている
Amazon RDSを使えばよいのではないか、という考えもあります。はい、その通りです。
特に最近はMulti-AZ機能なども提供され、安心感があります。

ただ、ベターホームレシピを検討していたときには、RDSは冗長化機能が弱い、
バックアップでIOフリーズがあったりする、など現在より課題も多かったので
EC2上で自前運用としました。

また、運用にかけられる予算が少なかったので、EC2とは別に複数のインスタンスでの
RDSの費用が発生するのが嫌だったというのもあります。

RDSを選ぶかは、みなさまの環境によると思います。

■ EBS上にMySQLデータを置いて動かす

では、EC2上で自前でMySQLを運用する場合について進めます。
普通にインストールすると、EC2のローカルストレージにデータを置くことになりますが、
EC2のインスタンスが落ちた場合、データ消えてしまうので怖いです。

したがって、MySQLのプログラム自体はEC2のローカルストレージでも
いいのですが、データディレクトリはEBS上に置くことにします。

肝心の方法ですが、以下に書いてある通りですんなりできます。   

http://d.hatena.ne.jp/shibataism/20080822/1219422913
http://developer.amazonwebservices.com/connect/entry.jspa?externalID=1663&categoryID=100

■ ファイルシステムは xfs

ポイントはファイルシステムをxfsで作ることできます。

xfsはファイルシステムのフリーズフリーズ解除(freeze/thaw)機能があり、
EBSスナップショット取得中に書き込みをロックすることができ、
一貫性を持ったファイルシステムのスナップショット取得ができます。

freezeのコマンドはシェルからできるので、運用上、自動化することもでき、
今回の用途にはよいです。なので、以下に続く例もxfsにします。

■ 手動でフリーズ、スナップショット取得を実行してみる

前提としてmysqlのデータファイルは
  /vol/****/mysql/data
にあるものとします。(****は当社の場合はプロジェクト名です)

手順は以下の順番です。

 (1) MySQLのデータをFLUSHし、READロックをかけます。つまり、書き込みできないようにします。これでDBへの書き込みはできなくなります。
 (2) xfs_freezeコマンドでファイルシステムを凍結。ファイルシステムに書き込みをできなくすると同時に、ファイルシステム上のキャッシュやメタデータなどをディスクに書き込んでしまいます。
  (3) EBSのスナップショットを取得する。
 (4) xfsの凍結を解除します。ec2-create-snapshotでできます。
 (5) MySQLのロックを解除します。

DBやファイルシステムの状態が不整合を起こさないようにする工夫は(1)、(2)です。
(1)でMySQLのキャッシュのデータをFLUSHし、全部ディスクに退避させ、その上でREADロックです。
これでMySQLに追加書き込みはできません。その上で(2)を実施して、ファイルシステムに書き込みできなくします。
ディスクに追加書き込みできなくしてからEBSのスナップショット取得、そしてロックを順次解除していきます。具体的には以下のようにmysqlのコンソールに入ってコマンドを実行していくとできます。

----------------------------

 # mysql -u root --password=xxxx --port=xxxx --host=xxx.xxx.xxx.xxx     # mysqlのコンソールへ。

mysql >FLUSH TABLES WITH READ LOCK;                  # (1)MySQLをロック
mysql >SYSTEM xfs_freeze -f /vol                    # (2)ファイルシステムをロック
mysql >SYSTEM ec2-create-snapshot -d xxxxx vol-xxxxxx                  # (3)EBSのスナップショット
mysql >SYSTEM xfs_freeze -u /vol                    # (4)ファイルシステムのロック解除
mysql >UNLOCK TABLES;                      # (5)MySQLのアンロック

----------------------------
 

■ バックアップのプロセスを自動化する

上記のプロセスをスクリプトで自動化しておくと、定期的なスナップショット
取得ができて便利です。以下に簡単なPerlでのスクリプト例も書いておきます。
なお、xfsを使わない場合も想定して、xfs_freezeの前にsyncを入れていますが、
それ以外は上記のプロセスの自動化となっています。

#!/usr/bin/env perl

use strict;
use warnings;

use DBI;

my $use_xfs         = 1;
my $xfs_mount_point = '/vol';

my $use_mysql      = 1;
my $mysql_username = 'xxxx';
my $mysql_password = 'xxxx';
my $mysql_host     = 'xxx.xxx.xxx.xxx';
my $mysql_port     = 3306;
my $mysql_dsn      = [
    "DBI:mysql:;host=$mysql_host;$mysql_port", $mysql_username,
    $mysql_password
];

my $dbh = undef;

# connect and lock mysql
if ($use_mysql) {
    $dbh = connect_db($mysql_dsn);
    flush_tables_with_read_lock($dbh);
}

# commit buffer to disk
run_command( ['sync'] );

# freeze file system
if ($use_xfs) {
    run_command( [ 'xfs_freeze', '-f', $xfs_mount_point ] );
}

# snapshot ebs
run_command( [ 'ec2-create-snapshot', '-d', 'xxxxxx', 'vol-xxxxx' ] );


# thaw file system
if ($use_xfs) {
    run_command( [ 'xfs_freeze', '-u', $xfs_mount_point ] );
}

# unlock and disconnect
if ($use_mysql) {
    unlock_tables($dbh);
    disconnect_db($dbh);
}

exit 0;

sub run_command {
    my ($command) = @_;
    eval { system(@$command) and die "failed($?)\n"; };
    warn "ERROR: @$command: $@" if $@;
}

sub connect_db {
    my $dsn = shift;
    my $dbh = DBI->connect(@$dsn)
      or die "cannot connect database " . $!;
    return $dbh;
}

sub disconnect_db {
    my $dbh = shift;
    $dbh->disconnect();
}

sub flush_tables_with_read_lock {
    my $dbh = shift;
    $dbh->do('FLUSH TABLES WITH READ LOCK;') or die $dbh->errstr;
}

sub unlock_tables {
    my $dbh = shift;
    $dbh->do('UNLOCK TABLES; ') or die $dbh->errstr;
}

■ 注意点、制限事項など

ベターホームレシピで運用しているときはだいたい1回5秒くらいかかります。
特にEBSスナップショットに時間がかかります。その間、書き込みがブロックされるので
注意が必要です。書き込みに待ちが発生してもよい環境(スレーブ環境)などで取得するか、
マスタ環境で取得する場合は、書き込みブロックが許容できる環境で実施するのが
よいと思います。

なお、EBSスナップショットの取得はec2-create-snapshotコマンドではなく、APIを直接
たたけばもう少し高速になるはずです。それはまた今度実施してみます。

あと今回はxfsにしましたが、ext3,ext4など他のファイルシステムでもxfs_freeze的なことが
できるのかは、ちょっと調べましたが、見当たりませんでした。できるのかもしれませんが、
他のファイルシステムでもこういったバックアップ運用ができるのか、今後調べてみたいです。

■ 参考資料

今回の記事は以下の記事をもとに作りました。

・EBSでMySQLのスナップショットを取るための手順等の資料等
http://developer.amazonwebservices.com/connect/entry.jspa?externalID=1663&categoryID=100
http://alestic.com/2009/09/ec2-consistent-snapshot

■ まとめ

このような手順を踏めば、定期的に整合性の取れた状態でスナップショットを
作っておけて便利です。今度はリストアの方法なども記載したいです。

フレクトではEC2を使ったインフラ運用に興味のあるエンジニアを
募集しています。興味のある方は以下からご連絡ください。

 

http://www.flect.co.jp/recruit/index.html

 

採用情報

株式会社フレクトでは、事業拡大のため、
・Salesforce/Force.comのアプリケーション開発
・HerokuやAWSなどのクラウドプラットフォーム上での
Webアプリケーション開発
エンジニア、マネージャーを募集中です。

未経験でも、これからクラウドをやってみたい方、
是非ご応募下さい。

フレクト採用ページへ

会社紹介

株式会社フレクトは、
認定コンサルタント
認定上級デベロッパー
認定デベロッパー
が在籍している、セールスフォースパートナーです。
また、heroku partnersにも登録されています。
herokuパートナー
株式会社フレクトのSalesforce/Force.com
導入支援サービス
弊社の認定プロフェッショナルが支援致します。
・Visualforce/Apexによるアプリ開発
・Salesforceと連携するWebアプリ開発
も承っております。
セールスフォースご検討の際は、
お気軽にお問合せください。

2024年4月

  1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30        
ブログ powered by TypePad