まだプログラマーですが何か?

プログラマーネタとアスリートネタ中心。たまに作成したウェブサービス関連の話も http://twitter.com/dotnsf

「IBM 版の Cloud Foundry」(という表現でいいのでしょうか?)である BlueMix のレポート第二弾です。
前回のはこちら: 「BlueMix を使う」

前回は BlueMix のアカウントを取って、Java アプリケーションサーバーを1つ作って、war ファイルをデプロイする、という手順を紹介しました。IaaS 環境用の war ファイルがそのまま動く、というのは PaaS であることを考えるとなかなか凄いな・・ という印象でした。

今回は前回使わなかったデータベースサーバーを作ってつなげてみる、という所を紹介します。
が、そこでの手順に関係していることもあって、その前にもう少しダッシュボードの説明をさせてください。

前回紹介した作業までを行った状態で、再度 BlueMix にログインした時の様子がこんな感じになると思います。作成した Java アプリケーションサーバーが APPS というところに1つ追加されているのがわかります。この APPS をクリックします:
2014032601


APPS が展開されて、現在この環境で動かしているアプリケーションサーバーの一覧(といっても今は1つだけですけど)が表示されます。前回作成したアプリケーションサーバーの名前は "kkimura1" にしたので、そのサーバーが表示されています。ここでも再度アプリケーションサーバー名(この例だと "kkimura1")をクリックします:
2014032602


"kkimura1" アプリケーションサーバーの現在の状態が表示されました。App Runtime 欄でランタイムは "Liberty for Java" という Java アプリケーションサーバーが使われています。また Services 欄にはまだ何のサービスも紐づいていないことがわかります。ここでアプリケーションサーバーの状態を更に細かく見るため、左ペインの "LIBERTY FOR JAVA" と書かれた箇所をクリックします:
2014032603


現在のアプリケーションサーバーの状態が表示されました。Resources 欄を見ると、現在のインスタンス数は1、メモリ上限は 512MB で稼働していることがわかります。また Instance Details 欄では現在の CPU 稼働率が 0.3%、メモリ利用量は 90.8MB であることもわかります:
2014032604


実はインスタンス数とメモリ上限はこの画面からダイナミックに変更することができます。メモリが足りなくなってきたら Memory Quota を変更して増やしたり(或いは減らしたり)、CPU が厳しくなってきたら Instances を増やして負荷分散したり、ということがここから簡単にできてしまうのでした。これは超便利!

また更に画面下部を見ると、Environment Variables と書かれた欄があります。ここでアプリケーションサーバーの各種環境変数を見ることができます:
2014032605


この状態では VCAP_SERVICES という環境変数の中身が empty と報告されています。実はこの環境変数はアプリケーションサーバーがデータベースなどのサービスと紐付けられた時に、その接続情報が格納される変数なのでした。この段階では(まだ何のサービスとも繋がっていないため)中身が空のままになっている、ということです。


ではこのアプリケーションサーバー用にデータベースサーバーを1つ起動させてみましょう。BlueMix ではデータベースは「サービス」の1つとして提供されています。そこでダッシュボード画面に戻り、左ペインの SERVICES と書かれた箇所をクリックします:
2014032606


すると選択できる各種サービスの一覧が表示されます。"BLUAcceleration" ってのが DB2 だよな。後は・・・なんとなくわかるようなわからないような IBM 製サービス("IBM Created")が並んでいます:
2014032608


少し下の方をみると IBM 製ではないサービス("IBM Certified" や "Community")も並んでいます。データベースだけでなく、メッセージキューやジオコーディング、そして電話/SMS連携の Twilio なんかも選ぶことができるようです。 色々試してみたいところですが、とりあえずは1つデータベースを選びます。得意なのを選びましょうか、自分の場合は "MySQL" を選んでみました:
2014032609


確認画面が表示されるので "ADD TO APPLICATION" をクリックします:
2014032610


そして、この MySQL サービスをどのアプリケーションサーバーと紐づけるか聞かれます。この段階ではどことも紐づけなくても構いません(その場合は単独で稼働する MySQL サーバーになります)が、上述の環境変数の確認をしたいので最初に作ったアプリケーションサーバーを選ぶことにします。これでこの MySQL サーバーが Java アプリケーションサーバーと紐づけられたことになります。最後に "CREATE" をクリックして起動します:
2014032611


ダッシュボード画面に戻ると、SERVICES 欄に (1) という数字が表示されているはずです。また MySQL サーバーが SERVICES から確認できるはずです:
2014032612


ダッシュボードの ALL を見ると、Java アプリケーションサーバーと MySQL サーバーの2つが確認できます。また Java アプリケーションサーバーに紐づけられたサービスとして MySQL のアイコンが表示されているはずです:
2014032613


さて、この状態で改めて上述の Java アプリケーションサーバーの Environment Variables 欄にあるVCAP_SERVICES の値を確認してみましょう。JSON フォーマットでこんな感じの値が表示されるはずです:
2014032614

 
これが Java アプリケーションサーバーからみた MySQL サーバーの接続情報になっています。MySQL サーバーのホスト名(IP アドレス)が hostname 値、ポート番号が port 値、データベース名が name 値、 ユーザーIDが username 値、そしてパスワードが password 値にそれぞれ格納され、1つの JSON にまとまっています。

アプリケーションサーバーからは、これらの情報をあらかじめ確認した上で(ソースコード内に)接続のための情報を記述すればデータベース接続ができます。ただよりスマートに以下のような方法も考えられます:
(1) アプリケーション側でまず VCAP_SERVICE を確認し、 
(2) 中身(JSON)が入っていた場合は、JSON をデコードして接続のための情報を動的に取り出してデータベースに接続する
(3) VCAP_SERVICE に値が設定されていなかった場合は(それは BlueMix 環境ではないことを意味するので)通常の IaaS やオンプレ環境として接続先のデータベース情報を取得する 

このようにすると BlueMix 環境用と、BlueMix でない環境用それぞれで接続先データベースを都合いい方法で取得/設定することができるようになると思われます。war/ear ファイルがそのまま動くような環境だからこそ、こういう方法で接続先データベースも分けられるのは(その情報をハードコーディングする必要もなくなるので)便利ですね。

・・・ところで、Java で JSON 使う時の便利なライブラリをどなたかご存知ないでしょうか? いくつか知ってるんですが、どれも「帯に短し・・・」的な感じで、「これっ!」ってのがないんですよね。。



 

IBM 版の CloudFoundry である BlueMix を使ってみました。ペースとしては CloudFoundry の PaaS ですが、標準で用意されたアプリケーションサーバーや各種サービスに IBM ベースのものも使える、というもの。なので例えば Java アプリケーションサーバーとしての WebSphere Application Server Liberty Core (と思われるモノ)が選択するだけで使えるようになっています。DB サーバーには IBM DB2 も用意されていますが、MySQLmongoDBRedis といったオープンソース/コミュニティ系DBサーバーを選択することもできます。これら以外にも電話/SMS連携サービスである Twilio も連携サービスとして利用できるようになっているなど、無料で使えるサービスという意味でもアプリケーション開発者としてなかなか興味を惹かれるものがあります。なお "BlueMix" は現在ベータバージョンとしての公開であり、名称もコードネームのようです(今後変更の可能性もあります)。
 

BlueMix を使うには IBM ID および BlueMix のユーザー登録が必要です。IBM ID の新規取得方法についてはこちら(PDF)を参照ください。既に IBM ID を持っている場合、BlueMix のトップページより、"Join us in beta" と書かれたボタンをクリックします:
2014032501

取得済みの IBM ID とパスワードでログインします:
2014032502


IBM ID のメールアドレスにアクセスコードの書かれたメールが届きます。その内容を 300 秒以内にこの画面に入力して Submit します:
2014032503


BlueMix に興味を持った理由を簡潔に記述し、また利用条件に対して "I Accept" を選択して Submit します:
2014032504


この画面が出れば申し込みは完了です。BlueMix が利用可能になるまでしばらく待ちます:
2014032505


審査が滞りなく進んで、BlueMix の利用が可能になると IBM ID のメールアドレスにその旨の通知が届きます。これで BlueMix にログインできるようになりました:
2014032500



ログインができるようになった段階で改めて BlueMix のホームページにアクセスし、右上の "LOGIN" をクリックし、IBM ID とパスワードでログインします:
2014032506


今度はこのような画面になりました。これが BlueMix のダッシュボードページです。この画面から現在の利用アプリケーションサーバーやサービスの状態を確認したり、アプリケーションサーバーやサービスの追加、その紐付け等を行うことができます:
2014032507


今はまだアプリケーションサーバーもサービスも何も動いていません。とりあえずアプリケーションサーバーを1つ追加してみましょう※。

※実は後述のコマンドラインツールを使ってデプロイと同時に直接アプリケーションサーバーを作ってしまうことも可能ですが、このダッシュボードの使い方にも慣れておく必要があるのでここで作成します。

"Add an application" をクリックします: 
2014032508


アプリケーションサーバー(やサービス)として選択可能な一覧が表示されます。現時点では Liberty for Java や Node.js、 Ruby on Rails、Ruby Sinatora が選択できるようになっています。好きなものを選んでいいのですが、ここでは個人的に得意な Java アプリケーションサーバーを使いたいので "Liberty for Java" を選択してみます:
2014032509


選択したアプリケーションサーバーの説明と確認が表示されます。ここで "CREATE APP" をクリックしてアプリケーションサーバーを作成します:
2014032510


作成する Java アプリケーションサーバーの情報を入力します。といってもここで必要な情報はアプリケーションの名前とそのホスト名(***.ng.bluemix.net の *** 部分を指定)だけです。試しにこんな感じで入力してみましたがおそらくどちらも一意の名称である必要があると思います(なので早い者勝ち)。アプリケーション名をベースにホスト名が作られるようですが、後からホスト名だけを編集することも可能です。最後に "CREATE" をクリックします:
2014032511


2014/03/26 訂正
ホスト名は全ユーザー内で一意の必要があるが、アプリケーション名はユーザーごとに一意であればよい、とのことでした。



ダッシュボード画面に戻ります。これだけで Java アプリケーションサーバーが出来て、ダッシュボード画面に追加されています。作成直後はまだ稼働状態にはなっていませんが、しばらく待つとこの Java アプリケーションサーバーが起動し、有効な状態になります:
2014032512


有効な状態になるとこんな画面になります。この段階で(ホスト名である) kkimura1.ng.bluemix.net が公開され、アクセス可能な状態になっています:
2014032513


試しにこの段階でウェブブラウザを使ってアプリケーションサーバーにアクセスするとこんな感じの画面が表示されます。デフォルトでは環境変数の一覧が表示されるようになっている模様です:
2014032514


ではこの Java アプリケーションサーバーに自分で作った Java アプリケーション(warファイル)をデプロイしてみましょう。

現状、BlueMix サーバーとの対話はすべて専用の(というか CloudFoundry 用の)コマンドラインツール("cf")を使って行います。ということでまずは "cf" を入手する必要があります。cf のダウンロードページへ行き、少し下へスクロールすると各種プラットフォーム向けのインストーラバイナリがそろっているので、ここから自分の環境に合った cf インストーラをダウンロード&インストールします。
2014032515


cf コマンドを実行して、コマンドラインヘルプが表示されればインストールは成功です:
2014032516


最初に cf の環境設定を行う必要があります。アクセス先を BlueMix API に設定し、かつログイン情報(IBM ID とパスワード)を設定します。ちなみに入力しているのはピンクの文字部分で、(IBM ID) には IBM ID を、(パスワード)にはパスワードを指定しています:
# cf login -a https://api.ng.bluemix.net -u (IBM ID) -p (パスワード)
API endpoint: https://api.ng.bluemix.net
Authenticating...
OK

API endpoint: https://api.ng.bluemix.net (API version: 2.0.0)
User:         (IBM ID)
Org:          (IBM ID)
Space:        dev

#

これでデプロイ前の準備は完了しました。では実際にサンプルの Java アプリケーションを先ほど作成した kkimura1 アプリケーションサーバーにデプロイしてみます。今回はテスト用に(DBサーバーなどを使わずに)単独で動作する helloworld.war ファイルを使って試してみます。ご自身でデプロイしてみたい WAR ファイルがあればそれを使っていただいても構いません。もし手元にいいのがなくて、紹介するのと同じサンプルでよければこちらからダウンロード可能です: helloworld.war

↑名前から想像できると思いますが、ただの "HelloWorld" 表示アプリです。ブラウザが日本語仕様だと「こんにちは」になる程度の制御はしてますが・・・ BlueMix 用に作ったものではなく、普通のオンプレミス環境や EC2 などクラウド上に Tomcat などが導入されていれば使える、標準的な WAR ファイルです。

カレントディレクトリに helloworld.war が存在している状態で以下のコマンドを実行します。push コマンドに続いてアプリケーション名(kkimura1)、そして -p オプションで war ファイルを指定します:
# cf push kkimura1 -p helloworld.war
Creating app kkimura1 in org (IBM ID) / space dev as (IBM ID)...
OK

Creating route kkimura1.ng.bluemix.net...
OK

Binding kkimura1.ng.bluemix.net to kimura1...
OK

Uploading kkimura1...
Uploading from: /tmp/helloworld.war
2.4K, 6 files
OK

Starting app kkimura1 in org (IBM ID) / space dev as (IBM ID)...
-----> Downloaded app package (4.0K)
OK
-----> Downloading IBM 1.7.0 JRE from http://file.w3.bluemix.net/buildpack/jre/ibm-java-jre-7.0-6.0-linux-x86_64-small-footprint-uncompressed-jar-20140116.tar.gz (0.0s)
       Expanding JRE to .java (2.0s)
Downloading from /icap/jazz_build/build/Core_Managed/build.image/output/wlp/com.ibm.ws.liberty-8.5.5.1-201402080619.tar.gz ... (0.0s).
Installing archive ... (1.3s).
-----> Uploading droplet (92M)

0 of 1 instances running, 1 starting
0 of 1 instances running, 1 starting
0 of 1 instances running, 1 starting
0 of 1 instances running, 1 starting
1 of 1 instances running

App started

Showing health and status for app kkimura1 in org (IBM ID) / space dev as (IBM ID)...
OK

requested state: started
instances: 1/1
usage: 1G x 1 instances
urls: kkimura1.ng.bluemix.net

     state     since                    cpu    memory        disk
#0   running   2014-03-25 01:43:51 PM   0.0%   74.3M of 1G   182.5M of 1G


余談ですが、この出力結果の中に Uploading droplet (92M) とありますね。helloworld.war 自体は数キロバイトなので、共通環境というか、Java アプリ用の前提環境がほとんどだと思います。一回のデプロイで 100Mbyte 近いアップロードがされるのだとしたら容量制限のあるモバイルテザリング環境で何度も試すには厳しいかも。。


さてデプロイできました。この状態で再度 http://kkimura1.ng.bluemix.net にアクセスすると、先ほどまでの環境変数一覧とは変わって、helloworld.war のアプリケーションが稼働している状態になっているのが確認できます:
2014032517


今回用意した helloworld.war は DB も使わないごくごくシンプルな Java アプリケーションではありますが、普通のオンプレミス環境や Amazon EC2 などの一般的な IaaS 環境で動作する WAR ファイルです。それを1バイトも変更することなく、WAR ファイルのまま PaaS 環境にデプロイできる、というのはなかなかよくできているなあ、と感じました。
 
とはいえ、現実には DB を使った場合はどうやって接続するのか? どこを変えないといけないのか? IaaS 用の WAR ファイルパッケージとどこまで互換性を持たせたまま利用できるのか? 何ができて何ができないのか? といった疑問/問題もあります。その辺りをこのブログで引き続きレビューしていければ、と思っています。
 

まずはこの2つのスクリーンショットを見比べてください:

(スクリーンショット1)
2014031401

(スクリーンショット2)
2014031402


どちらもアマゾンのウェブページを同じ Chrome ブラウザで見ている時に取得したものです。全般的に似たような内容ですが、パッと見で「同じではない」ことはわかりますよね。

でもどちらも全く同じページ(同じURL)を指しています。どちらのページもアマゾンのトップページから "ThinkPad" を検索した時の結果ページです。PC 用とモバイル用、というわけでもなさそうですよね。 ではこの違いはなんでしょう?



・・・答は User-Agent の違いでした。(1)は普通の Windows 向け Chrome 標準の User-Agent でアマゾン内を検索したものですが、(2)は Google のクローリングボットの User-Agent(Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)) に偽装してから検索したものです。
2014031403

ここからわかることはおそらくアマゾンはGoogle のクローリングボットが来た時用の、なんらかの手を加えて結果を返すようにしている、ということです。そしてそれはおそらく SEO 対策であろう、と推測されます。

普通に人間がウェブページを見る時に見やすい〈求める)情報と、SEO 対策を重視した画面が同じとは限りません。SEO 的に有利なページを作りたい一方で、ユーザーにはパーソナライズやレコメンドを表示するなど使い勝手を損ないたくもない。そのためにはこのような表示出し分けの対策をしている、ということだと思います。

ちなみに (1) の HTML は約80Kバイト、(2) は約110Kバイトでした。SEO 対策済み(?)のサイトの方が3割程度情報量が多いと考えるべきなのか、人間向けのサイトの方が情報をまとめていると考えるべきなのか。


詳しい内容を調べたわけではないのですが、とりあえずこの2つのページの大きな違いとして、(1) は Shift_JIS 、(2) は UTF-8 で記述されていました。まあ根本的に違うエンジンが使われていると考えるべきでしょうね・・・



このページのトップヘ