Play2
- BluemixにPlayframeworkアプリケーションをデプロイする (22 Jan 2017 | Tags:
BluemixにPlayframeworkアプリケーションをデプロイする BluemixにPlayframeworkアプリケーションをデプロイする
Bluemixを触りだしたので、HelloWorldとしてWebアプリケーションをデプロイしてみた。
準備
- Playframework 2.5.10
- Scala 2.11.7
- CloudFoundry CLI
上記に加え、Bluemixのアカウントの登録、適当なアプリケーションが実装済みの前提で進めます。
デプロイ対象を生成する
sbt dist
でzipファイルを生成する。 [APPLICATION_NAME] etc..はプロジェクト固有の値になっているので、適宜読み替え。> sbt dist ・・・ [info] Your package is ready in /~/[APPLICATION_NAME]/target/universal/[APPLICATION_NAME-VERSION-SNAPSHOT].zip
manifest.ymlファイルを作成する
プロジェクトルートにmanifest.ymlを作成。 [HOST_NAME]、 [NAME] は任意の値を設定。 path の設定は、↑のzipファイルのパスを指定。
applications: - host: [HOST_NAME] name: [NAME] buildpack: java_buildpack path: ./target/universal/[APPLICATION_NAME-VERSION-SNAPSHOT].zip instances: 1 memory: 512M
認証
Bluemix登録時のメールアドレスとパスワードを聞かれるので、入力する。
> cf login API エンドポイント: https://api.ng.bluemix.net > Email > Password
APIエンドポイントの設定
↑で認証したエンドポイント以外を使う場合、エンドポイントを指定しなおす必要がある。
今現在、使用できるエンドポイントは以下の3つ。
- 米国南部
- 英国
- シドニー
それぞれ設定が異なるので注意。
使用する組織、スペースが異なる場合も別途設定。
cf api https://api.[REGION].bluemix.net
エンドポイント REGION 米国南部 ng 英国 eu-gb シドニー au-syd
デプロイ
> cf push ・・・ 要求された状態: started インスタンス: 1/1 使用: 512M x 1 インスタンス URL: [HOST_NAME].au-syd.mybluemix.net 最終アップロード日時: Mon Jan 22 02:33:15 UTC 2017 スタック: cflinuxfs2 ビルドパック: java_buildpack 状態 開始日時 CPU メモリー ディスク 詳細 #0 実行 2017-01-22 11:34:21 AM 0.0% 512M の中の 964K 1G の中の 1.3M
こんなような出力がされて、完了。
URL を叩くと、アプリケーションの動作を確認できる。
LinkLatest post:
- OpenWhiskのScala sbtプロジェクトのgiter8テンプレートを作った
- OpenWhisk+Scalaで作るServerless Architectureとっかかり
- BluemixにPlayframeworkアプリケーションをデプロイする
- sbt、Giter8を統合するってよ
- Scala 2.12.0でSAM型
Recent Books:
- 【意訳】Scala on Play2 with Squerylではじめるデータベース駆動アプリ #scalajp #play_ja (31 Jul 2012 | Tags:
【意訳】Scala on Play2 with Squerylではじめるデータベース駆動アプリ #scalajp #play_ja 【意訳】Scala on Play2 with Squerylではじめるデータベース駆動アプリ #scalajp #play_ja
この記事は、HerokuのPrincipal Developer EvangelistのJames Ward氏とRyan Knight氏の記事Getting Started with Play 2, Scala, and Squerylの意訳です。参考程度にどうぞ。
誤訳・誤植等ありましたら、@modal_soulまでリプライいただけるとありがたいです。
サマリー
この記事では、Play2,Scala,Squeryl,JSON,CoffeScript,CoffeScript,jQueryとScalaTestを使ったWebアプリケーションの作り方を紹介します。また、同時にScalaTestを使ったテスト方法とHerokuを使ったクラウド環境へのアプリケーションデプロイについても学べます。 Play2,Scala,Squeryl,JSON,CoffeScript,jQueryとScalaTestの組み合わせによって、モダンなWebアプリケーションの構築とテストを効率的に行うことができ, シンプルなデータベース駆動Webアプリケーションの構築、テスト、クラウドへのデプロイを体験できます。
Play2の紹介
Play2は数あるWebフレームワークの中でも、ステートレスアーキテクチャで設計された、ユニークなWebフレームワークです。 Play2は、メモリやCPUなどのリソースの消費を抑えた、とても軽量なフレームワークです。 ステートレスであるため、昨今クラウドアーキテクチャにとって重要な、水平のスケーリングを容易に行うことができます。 他のアーキテクチャの特徴としては、完全に非同期なHTTPプログラミングモデルを使った、Websocketやcometのようなlong lived-connectionを利用するために設計されていることです。
また他の特徴としては、Herokuのようなクラウドアプリケーションプラットフォームへのデプロイに適するように、完璧に完結していることです。 Playアプリケーションのデプロイはシンプルで、コンテナベースのアプローチをしてきたJava開発者の多くが経験してきた環境齟齬を回避することができます。
Ruby on Rails, GrailsやDjangoなどの新しいWebフレームワークは、動的型付によってとても優れた生産性を発揮します。Playも動的言語フレームワークが持っているのと同じように、素早い繰り返しと高速な開発を行うことができ、しかしながらJavaやScalaのような静的型付言語による恩恵も留めています。これによりコンパイラは生産性を妨害することなく開発者を支援することができます。
Squerylの紹介
データベースとのインテグレーションに最適の技術は何か?これは今まで幾度と無く討論されてきました。幸いなことに、JavaやScalaのエコシステムでは、データの永続化の方法が複数用意され、選択することができます。 Play2のデフォルトのデータベースマッピングツールはAnormが使われています。(※AnormはORMではありません) 名前が指し示す通り、Anormはオブジェクトとリレーショナルモデルとの自動マッピングを行いません。 代わりに、開発者はネイティブなSQLを書き、手動でリレーショナルデータとオブジェクトのマッピングを行います。 この手法では、実行される生のクエリーをチューニングすることができるという利点があります。 Playの開発者は、SQLを使用することはリレーショナルデータベースとの対話とSQL層を抽象化することにおいての優れたDSLであり、パワフルで柔軟な方法だと主張してます。
Squerylは、Scalaにおけるデータ永続化のためのAnormの代替手段です。Anormと比較して、SquerylはHibernateに似ており、オブジェクトリレーショナルマッピングを提供します。Squerylはデータベースとの対話において、型安全なDSLを提供します。 またSquerylは、明示的に取得されるデータオブジェクトの粒度を制御することができます。 Hibernateのような従来のORMと共通のN+1問題に対するエレガントなソリューションを提供します。
SquerylはPlay2のデフォルトのデータ永続化ライブラリではありませんが、特別な追加設定やセットアップは必要としません。データベースエボリューションは手動で行う必要があり、データベース接続は初期起動時に生成する必要があります。トランザクションも同様に、コントローラーで呼ばれた際に、明示的に定義される必要があります。
Play2でのSquerylのセットアップ
Play2プロジェクトがまだない場合、Play2をインストール後、新規プロジェクトを作成しましょう。
プロジェクトの言語はScalaを選択しましょう。
SquerylライブラリをPlayプロジェクトに追加する必要があります。後ほどプロジェクトはHerokuにデプロイします。HerokuのデフォルトのデータベースはPostgreSQLで、PostgreJDBCドライバーも依存関係にあるためここで追加します。
project/Build.scalaファイルを編集し、依存関係を更新しましょう。
IDEにEclipseやIntellijを使っている場合、Playはプロジェクトを自動作成してくれます。
Intellijの場合
Eclipseの場合
ここでは注意ですが、プロジェクトファイルは依存関係を更新した後に作成しましょう。なぜならプロジェクトは必要なライブラリも含めて構成されるからです。もし後で依存関係を更新する場合は、プロジェクトを生成するコマンドを再度実行してください。
これでプロジェクトを実行することができます。プロジェクトルートに移動し、以下のコマンドを実行しましょう。
サーバは以下のURLで起動しています。確かめてみましょう。
ローカルでのテストではインメモリのh2データベースを使用します。Playでこのデータベースを使用するには、conf/application.confファイルを修正し、以下の行のコメントアウトの解除か、行の追加をします。
最後のセットアップ手順として、Squerylデータベースを接続します。データベースの接続情報を取得するために、Play標準の構成システムを使います。 Playアプリケーションのライフサイクルのスタートアップフェーズにフックするグローバルクラスを追加するだけで完了です。 app/Global.scalaファイルを新規に作成し、以下を記述します。
アプリケーションスタートアップのdb.default.driver設定パラメータは、データベース接続のセットアップのために使用するドライバを決定するために使われます。新しいコネクションが生成され、SquerylのSessionFactoryにストアされます。
ブラウザで、http://localhost:9000をリロードすると、アプリケーションが動作し、PlayのSTDOUTログで以下のメッセージが表示されるはずです。
Entityの作成
それでは、データベースでデータを保持するためのシンプルなEntityオブジェクトを作成しましょう。app/models/Bar.scalaファイルを新規に作成し、以下のを記述します。
これはBarオブジェクトのリストを保持するかなりシンプルなentityです。各々のBarはnameとプライマリキーとしてIDを持っています。Scalaのcase classは,不変で、基本的にクラスを文法上の便宜で満たすものです。また、クライアントから返却されたフォーム値のマッチングを行う際にとても便利なパターンマッチングとして使用することもできます。AppDBオブジェクトは、Squerylがデータベースへマッピングするスキーマのインスタンスです。今回の場合、データベースにbarというテーブルを1つ定義します。スキーマは単一のオブジェクトとして宣言されるため、シングルトンオブジェクトを生成します。
Squerylを使うと、AppDB.createメソッドを呼ぶだけでプラグラムチックにデータベーススキーマを生成することができます。ですが、手動でSQLスクリプトを作成する方法をお勧めします(PlayではこのSQLスクリプトをevolutions scriptと呼びます)。Playは、これらのSQLスクリプトに対応するデータベーススキーマをチェックして、データベーススキーマの変更を追跡します。Playは、スキーマが古くなっていることを検出すると、このSQLスクリプトの適用を提案してきます。これはDEVモードのときにのみ行われ、PRODモードでは、アプリケーションの起動前にスクリプトを適用されます。これにより、データベーススキーマの変更やバージョンのロールバックを行う必要がある場合に、スキーマの変更をコントロールすることができます。
conf/evolutions/default/1.sqlファイルを新規作成して、以下を記述します。
このSQLファイルは”Ups”と”Downs”の2つのセクションから成っています。”Ups”セクションは、データベーススキーマに変更を反映させ、”Downs”セクションは、データベースへの変更を取り消す際の記述です。Playは、データベーススキーマへの変更をこれらのファイルの名前順に適用します。もし、デプロイ後1.sqlの適用後にスキーマへ変更を行う必要がある場合は、2.sqlファイルに変更内容を記述します。 http://localhost:9000をリロードすると、Playがデータベースへの変更を適用するか尋ねてくるはずです。1.sqlの”Ups”セクションをローカルのインメモリデータベースに適用するために、Apply this script now!ボタンをクリックします。
モデルのテスト
Play2では、テスト駆動開発のスタイルに合った強力なテストサポートがなされています。ScalaでPlay2を使う場合、テストはデフォルトでspaes2が使われていますが、ScalaTestを使用します。Barモデルオブジェクトのシンプルなテストを作ります。プロジェクトにScalaTestの依存関係を追加し、testOptions設定を修正します。project/Build.scalaを以下を追記して更新します。
test/BarSpec.scalaを新規作成し以下を記述します。
このテストでは、実行するためにFakeApplicationとインメモリデータベースを使います。FakeApplicationを使用すると、Squerylデータベースコネクションは先に生成されたGlobalオブジェクトを使って構成されます。テスト本体は単純にBarのインスタンスを生成し、idが0ではないことをテストします。 これはSquerylトランザクションで行われます。 1系のPlayと異なり、テストはコマンドラインから実行されます。コマンドは以下
テストが終了したら、以下のメッセージがPlayのSTDOUTログに出力されていることを確認します。
ソースの変更の度にテストを実行するには、以下のコマンドで実行します
~runと~testコマンドはバックグラウンドで継続して実行することができます。これにより、ユニットテスト/機能テストやブラウザからの手動テストをすぐさま実行することができます。
WebフォームからBarを生成する
新しくBarオブジェクトを生成するための基本的なWeb UIを追加してみましょう。このセクションの手順を全て踏まないとコードのコンパイルができないので注意してください。
最初に、app/controllers/Application.scalaファイルを下記の記述を追加して更新します。
barFormは、リクエストパラメーターnameからcace class Barのプロパティnameへ(コンストラクタを通して)マッピングをします。indexメソッドは、index templateへbarFormのインスタンスを渡すように更新されました。次にtemplateを更新します。addBarメソッドは、リクエストパラメーターをオブジェクトbarにバインドし、トランザクション内でデータベースへインサートします。SquerylはPlay frameworkに統合されていないので、データベーストランザクションはSquerylのinTransactionを使って明示的に開始する必要があります。次にユーザはindexページにリダイレクトされます。リクエストパラメータがbarFormを使ってBarにマッピングされなかった場合、BadRequestエラーが返却されます。
次にapp/views/index.scala.htmlテンプレートに以下を追記して更新します。
この時点で、テンプレートはApplication Controllerのindexメソッドから渡されたForm[Bar]パラメータを取ります。テンプレート本体の新しいHTMLフォームはPlay2のform helperを使ってレンダリングされます。このフォームは、nameフィールドとsubmitボタンを持ちます。注意しなければいけないのは、フォームのアクションは、ルートからApplication controllerのaddBarメソッドへを指していることです。
この時点でコンソールウィンドウをみると”value addBar is not a member of controllers.ReverseApplication”エラーがみられると思います。 これは、routeファイルがコンパイルされ、routeがチェックされたからです。まだrouteが作られていないので、conf/routesファイルを編集し、以下の行を追加します。
これにより、/barsURLへのPOSTリクエストをaddBarメソッドへマッピングするHTTPルートを作成します。
ブラウザでhttp://localhost:9000 を更新すると、新しいBarオブジェクトを追加するための基本的なフォームが表示されているはずです。成功した場合、新しいBarを追加した後に、ブラウザはindexページにリダイレクトして戻ります。
これで一通りが動くようになったので、controllerのコードに戻り、これらの動作についてより理解しましょう。addBarメソッドについて理解することは、コンパイラが周囲のスコープから値を見つけるために、どのように暗黙的なキーワードを通知するかを理解するのに役立ちます。Scalaでは、implicitキーワードは、implicit関数のパラメータもしくは、inplicitオブジェクトへの変換としても使用することができます。二つは全く異なりますが、両方ともにScalaの定義を解決する方法に関連しています。この場合、implicitは一つもしくはそれ以上の関数を呼ぶ場合と全ての関数に同じあたいを渡す必要がある場合に使われます。この手順は、APIを構成する際に便利で、ユーザはいつも何のパラメータが使用されるかについて明示する必要がなくなりますが、変わりにデフォルト値に依存します。
addBarの場合、barForm.bindFromRequestメソッドがplay.api.mvc.Requestパラメータをとり、明示的に渡す必要がないため、リクエストをimplicitと明示します。
参考に、Form.bindToRequestメソッドのメソッド定義を記載します。
bindFromRequestはフォームオブジェクトを返します。addBarメソッドでは、この場合Option[Bar]を返却するFormインスタンスのvalueメソッドを呼び出します。そして、呼び出しもとのマップがBarを取得し、フォームマッピングから生成できれば生成し、そうでなければgetOrElseステートメントはBadRequestを返却します。Barオブジェクトが生成することができた場合、それはトランザクション内でデータベースに保存されます。
これで、Squerylでリクエストパラメータとオブジェクトをマップしオブジェクトを保存する方法について理解できたと思うので、新しいaddBar controllerメソッドのテストを書きましょう。
Barの追加のテスト
下記の記述を新規作成したtest/ApplicationSpec.scalaファイルを記述し、addBar controllerメソッドの新しいテストを作ります。
機能テストではインメモリーデータベースとFakeApplicationを使います。テストでは、Application controllerのaddBarメソッドへのリクエストとnameという名前でFooBarという値のフォームパラメータを生成します。このテストの成功は、シンプルにindexページへリダイレクトされることで、ステータスがSEE_OTHER(HTTP 303ステータスコード)であるかをチェックし、リダイレクトのロケーションはindexページのURLでチェックされます。play testでテストを実行するか、play ~testであればコードの変更のタイミングでテストが実行されています。
JSONとしてBarを取得する
JSONのシリアライズされたデータとして全てのBarオブジェクトをアプリケーションへ返却するRESTfulなサービスを追加しましょう。app/controllers/Application.scalaファイルに新しいメソッドを追加します。
getBarsメソッドは、Squerylを使用してデータベースからBarオブジェクトを取ってきて、BarオブジェクトのJSON形式のリストを生成し、JSONデータを返却します。
conf/routesファイルに新しいルートを追加します。
これにより、/barsへのGETリクエストがgetBarsメソッドへマッピングされます。
ブラウザでhttp://localhost:9000/barsを表示させ確認してみましょう。
JSONとしてシリアライズされたBarオブジェクトのリストが見られるはずです。
前述した通り、トランザクションはSquerylのinTransactionで明示的に開始される必要があり、データベースから値をselectする場合もです。そして、トランザクション内で、Barの全てののエンティティはデータベースから取得されます。
クエリーの構文は、Squerylのタイプ・セーフなクエリー言語の力とDSLを作るためのScalaの力を示しています。from関数は最初のパラメータとしてテーブルへのタイプ・セーフな参照を受け取ります。これはキーワードからのSQLに似ています。2番目のパラメータは、パラメータとしてクエリーにテーブルを取得し、そのテーブル上に何をするかを指定します。この場合はselectです。formは、barsを不変な定数にセットされている反復処理可能なオブジェクトを返却します。その後、Json.generateメソッドは、データベースから取得されたbarsを反復処理し、それらを返却します。jsonの定数は、application/json(JSONの値)にセットされたコンテントタイプと共に、OK(HTTP 200ステータスコードの応答)で返却されます。
JSONサービスをテストする
JSONサービスをテストする新しいテストのためにtest/ApplicationSpec.scalaを更新します。以下を追記します。
再びこの機能テストでは、FakeApplicationとインメモリデータベースを使用します。そしてデータベースに新しいBarを生成し、Application controllerのgetBarsメソッドへのリクエストを作ります。テストしたレスポンスはOK(HTTP 200)で、生成されたBarの名前を含んでいるはずです。前と同じように、play testでこのテストを実行するか、play ~testで実行します。これで3つのテストに通っているはずです。
CoffeScriptとjQueryでBarsを表示する
これで、Barオブジェクトのリストを取得するRESTfulなJSONサービスができたので、取得とindexページへの表示を行うようCoffeScriptとjQueryを使って書いてみましょう。Play2の新しい機能の一つに、CoffeeScriptからJavaScriptへコンパイルとJavaScriptの構文チェック、ミニファイ化、LESSのCSSへのコンパイルを行うassetコンパイラがあります。
app/assets/javascripts/index.coffeeファイルを新規作成し、下記を記述します。
このCoffeeScriptは、/barsへのgetリクエストを作るためにjQueryを使用し、各barに対して反復処理を行い、barsのidと共にbarをページのエレメントに追加します。では、このスクリプトをロードするためにapp/views/index.scala.htmlテンプレートを更新し、ページにbarsエレメントを入れてみましょう。以下の記述をテンプレートのmainセクションのトップに追加します。
スクリプトのsrcは、javascripts/index.min.jsファイルへのURLを取得するためにroutes.Assets.at関数を使うことに注意してください。まだこのファイルは存在していません。Playのassetコンパイラは、index.coffeeファイルをコンパイルしてミニファイ化されたこのファイルを生成する必要がることを検知します。再度http://localhost:9000 のWebページを読み込み、新しいBarを生成し、Webページに表示されることを確認しましょう。
Herokuへのデプロイ
Herokuはクラウド上でPlay2の実行環境を提供する複数言語対応したCloud Application Platformです。このアプリケーションをHerokuへデプロイするには以下の手順を実行します。
1. 下記の内容を記述したProcfileをルートディレクトリは以下に作成します。
これによりHerokuへPlayアプリケーションの実行方法を伝えます。
2. Herokuは、Heroku上へのファイル転送にGitを用います。まだGitがインストールされていないのであれば、Gitをインストールしましょう。プロジェクトのルートディレクトリから、このプロジェクト用のGitリポジトリを生成し、ファイルを追加し、コミットします。
3. HerokuのツールベルトはHerokuへのコマンドラインインターフェースです。Heroku ツールベルトをインストールしましょう。
4. Herokuアカウントへサインアップします。
5. コマンドラインからHerokuへログインします:
GitのSSHキーをセットアップし、それをHerokuアカウントへ紐付けます。
6. 新しいアプリケーションをHerokuにプロビジョニングします。
7. HerokuへアプリケーションをPushします。
Herokuが、SBTでアプリケーションをビルドし、dyno上で実行します。
8. ブラウザでクラウド上で実行されるアプリケーションを開きましょう。
おめでとうございます!これであなたのアプリケーションはクラウド上で実行されています。
Share Your Opinion
Play2について思うところはありませんか?Getting Started with Play2, Scala, and Squerylのフォーラムトピックで議論しましょう。
リソース
このプロジェクトの全てのソースコードは、Github上から入手することができます。
https://github.com/jamesward/play2bars/blob/scala-squeryl
ローカルでPlayが実行されている場合、Playのローカルドキュメントにアクセスできます。
http://localhost:9000/@documentation
下記のサイトでもPlayのドキュメントを閲覧できます。
http://www.playframework.org/documentation
Herokuについては、Heroku Dev Centerを見てください。
この記事が一助となればと思いますが、もし質問や問題があれば我々に知らせてください。
著者について
James Ward (www.jamesward.com) is a Principal Developer Evangelist at Heroku. Today he focuses on teaching developers how to deploy Java, Play! and Scala apps to the cloud. James frequently presents at conferences around the world such as JavaOne, Devoxx, and many other Java get-togethers. Along with Bruce Eckel, James co-authored First Steps in Flex. He has also published numerous screencasts, blogs, and technical articles. Starting with Pascal and Assembly in the 80’s, James found his passion for writing code. Beginning in the 90’s he began doing web development with HTML, Perl/CGI, then Java. After building a Flex and Java based customer service portal in 2004 for Pillar Data Systems he became a Technical Evangelist for Flex at Adobe. You can find him tweeting as @JamesWard, answering questions on StackOverflow.com, and posting code at github.com/jamesward.
Ryan Knight is a senior software architect and consultant with over fifteen years of experience in all aspects of cloud computing and software development. He first started Java Consulting for Sun Microsystems Java Center and now runs his own consulting company. Some of his recent projects include being a software Consultant for Deloitte at the State of Louisiana, expert services for Adobe at T-Mobile, creatng a web application at Team Marketing Report, development of a text and voice chat system for Sony Online Entertainment, contributing to the Development of a Gift Card Creation Tool, and being a software architect for Williams Pipeline.
Latest post:
- OpenWhiskのScala sbtプロジェクトのgiter8テンプレートを作った
- OpenWhisk+Scalaで作るServerless Architectureとっかかり
- BluemixにPlayframeworkアプリケーションをデプロイする
- sbt、Giter8を統合するってよ
- Scala 2.12.0でSAM型
Recent Books:
- 【意訳】データベース駆動アプリのための、Play2最適化について #play_ja (26 Jul 2012 | Tags:
【意訳】データベース駆動アプリのための、Play2最適化について #play_ja 【意訳】データベース駆動アプリのための、Play2最適化について #play_ja
この記事は、HerokuのPrincipal Developer EvangelistのJames Ward氏の記事の意訳です。参考程度にどうぞ。
誤訳・誤植等ありましたら、@modal_soulまでリプライいただけるとありがたいです。
先週Matt Raible氏と共に、UberConfで行われたPlay vs. Grailsスマックダウンでプレゼンテーションをしました。 このセッションの目標は、同じフレームワークを用いて同じアプリケーションを作り、Play2+JavaとGrailsを比較することです。 比較のために、いくつかのベンチマークを含む評価基準を使用しました。 結果については、こちら(Matt’s session recap blog)に詳しく掲載されています。 評価結果のプレゼンの後、これらのタイプのアプリケーションでPlay2のAkkaスレッドシステムを最適化するのに重要なことを発見しました。 Play2は、ブロッキングのコールを含まないHTTPリクエスト(i.e. 非同期)のためにout-of-the-boxに最適化されています。 Javaのほとんどのデータベース駆動アプリでは同期コールはJDBC経由で使用されるため、Play2ではこれらのリクエストタイプのためにAkkaを調整するちょっとした設定が必要です。
シンプルな例をあげてみます。時間的に現実的なデータベースブロックをシミュレートするために、このベンチマークをローカルではなくHeroku上で実行します。 “play2bars”example appから”java-ebean”ブランチとHerokuの共有のPostgreSQLデータベースを使います。
Apache Benchを実行して、同時100クライアント接続で10000リクエストをアプリのJSONサービスへ投げるために、同じAWSリージョンにあるEC2サーバーからHerokuのmy appとして、以下のコマンドを実行しました。
最初の最適化前の結果がこちらです
毎秒973リクエストは悪くはありませんが、下記のようなエラーが確認できました。
これは、Akkaが長時間ブロックされたことを意味しており、同期のコード実行を改善するようにPlay中のAkkaの設定を変え、評価を再実行しました。その結果は以下のようになりました。
今回は、毎秒1374リクエストになりました。シンプルな最適化の方法は、Akkaで処理を行うスレッドを増やすして、タイムアウト値を長く設定することです。それによりスレッドが同期DBによってブロックされた際、より多くのリクエストをハンドリングするためにさらにスレッドを呼び出します。実際に使ったPlayの設定は以下です。
Akkaで使用されるスレッドの数は、CPUと”parallelism-factor”の設定値を掛け合わせた値で、”parallelism-max”が上限値です。 デフォルトの”parallelism-factor”は”1”に設定されていて、この場合スレッド数はCPU数と同じで、”parallelism-max”のデフォルトは”24”です。これらの設定について詳しくは、Playのドキュメントで確認できます。
すべての設定ファイルはこちらのplay2barsプロジェクトから
このベンチマークはあくまで参考であって、それぞれの環境で異なってくると思います。それぞれの環境に合わせたチューニングをしてください。質問があれば是非。
Latest post:
- OpenWhiskのScala sbtプロジェクトのgiter8テンプレートを作った
- OpenWhisk+Scalaで作るServerless Architectureとっかかり
- BluemixにPlayframeworkアプリケーションをデプロイする
- sbt、Giter8を統合するってよ
- Scala 2.12.0でSAM型
Recent Books:
- 【意訳】Tutorial:Play Framework 2 with Scala, Anorm, JSON, CoffeeScript, jQuery&Heroku[Herokuデプロイ編] (04 Mar 2012 | Tags:
【意訳】Tutorial:Play Framework 2 with Scala, Anorm, JSON, CoffeeScript, jQuery&Heroku[Herokuデプロイ編] 【意訳】Tutorial:Play Framework 2 with Scala, Anorm, JSON, CoffeeScript, jQuery&Heroku[Herokuデプロイ編]
元記事はこちら
少々長い記事なので、Play2アプリのビルド編とHerokuへのデプロイ編に分けます。
今回は、Herokuへのデプロイ編です。
Play2アプリのビルド編は、こちら
Step 1) Herokuのアカウントを取得して、Heroku Toolbeltとgitをインストールして、コマンドラインからHerokuへログインします
もしこれがはじめてのHerokuへのログインだったら、git用のSSHキーの作成と、Herokuアカウントへの紐付けをする必要があります。
Step 2) Heroku上の各アプリケーションは、テスト用にPostgres DBを持っています。 Heroku上でアプリケーションを実行してこのDBを使うには、別途設定が必要です。 これにはいくつか方法がありますが、最も簡単な方法はスタートアップコマンドラインからDBの設定をオーバーライドする方法です。 これはStep3で紹介します。 その前に、Psotgres JDBCドライバーをプロジェクトの依存関係として指定する必要があります。 “project/Build.scala”ファイルに、以下のような”appDependencies”を設定します。
Step 3) Herokuにどのプロセスを実行するのかを教えるために、プロジェクトルートディレクトリ配下にファイル名”Procfile”を作成し(※大文字と小文字が区別されます)、以下のように記述します
Play2では、プロジェクトのビルドにScala Build Tool(SBT)を使います。プロジェクトがHerokuへデプロイされると、プロジェクトをコンパイルするため”sbt stage!コマンドが実行されます。 そして、プロセスがJavaのクラスパスの設定とPlayサーバーの起動をする”taget/start”スクリプトを生成します。 Herokuはアプリケーションに、Javaプロパティ”http.port”が適宜設定されるように、環境変数”PORT”を使用してリッスンすべきHTTPポートを通知します。 また、Heroku上のアプリケーションへDB(とその他のリソース)への接続文字列は、デフォルトでは環境変数介して渡されます。 環境変数のDATABASE_URLは、DBホスト、名前、ユーザ名、パスワードを含みます。 所謂”db.default.url”プロパティがその値で設定されます。 またドライバは、Postgres JDBCドライバクラスに設定されます。
Step 4) Herokuはアプリケーションのアップロード方法としてgitを使っています。 SCMツールにgitを使っていようと無かろうとHerokuへアプリケーションをアップロードするにはgitを使います。 プロジェクトのルートディレクトリでgit repoを作り、ファイルを追加してコミットします。
※ 選択しての”git add”の代わりに、”.gitignore”ファイルを更新することもできます。
Step 5) Heroku CLIを使用して、Heroku上に新しいアプリケーションをプロビジョニングします。 あなたが作った各アプリケーションは1月辺り、750“dyno”時間無料です。 開発者として無料でHerokuを使用でき、スケールした分だけ支払うことになります。 コマンドライン上で、”cedar”スタックを使って新しいアプリケーションを作ります。
これでアプリケーションのHTTPとgitのエンドポイントを作ります。 アプリケーションで変更した名前を使うことも、自身のドメイン名を使うことも可能です。
Step 6) アプリケーションはクラウドへデプロイする準備が整いました。コマンドラインからHerokuのマスターブランチへ”git push”します。
Herokuがファイル受け取ると、Play Frameworkのプレコンパイラが実行され、Herokuが”slug file”をアセンブルし、”slug”がdynoへデプロイされます。
Step 7) これで”heroku create”に続いて出力のドメインに移動する、もしくは単純に実行することで、ブラウザでアプリケーションを表示できます。
Scala, Anorm, JSON, CoffeeScript, jQueryを使ったPlay2アプリケーションをHeroku上にデプロイできたはずです。 これよりも詳細にHerokuの使い方を知りたいときは、Heroku Dev Centerを確認してください。 もし質問があったら、私に知らせてください。
このエントリーは、CoffeeScript, jQuery, Play Framework, Scalaを使ってポストされました。パーマリンクをブックマークしてください。コメントかトラックバックをよろしく。トラックバックURLは、こちら
Latest post:
- OpenWhiskのScala sbtプロジェクトのgiter8テンプレートを作った
- OpenWhisk+Scalaで作るServerless Architectureとっかかり
- BluemixにPlayframeworkアプリケーションをデプロイする
- sbt、Giter8を統合するってよ
- Scala 2.12.0でSAM型
Recent Books:
- 【意訳】Tutorial:Play Framework 2 with Scala, Anorm, JSON, CoffeeScript, jQuery&Heroku [Play2アプリのビルド編] (29 Feb 2012 | Tags:
【意訳】Tutorial:Play Framework 2 with Scala, Anorm, JSON, CoffeeScript, jQuery&Heroku [Play2アプリのビルド編] 【意訳】Tutorial:Play Framework 2 with Scala, Anorm, JSON, CoffeeScript, jQuery&Heroku [Play2アプリのビルド編]
元記事はこちら
少々長い記事なので、Play2アプリのビルド編とHerokuへのデプロイ編に分けます。
今回は、Play2アプリのビルド編です。
Herokuへのデプロイ編は、こちら
※ 2012/03/06:アドバイスいただいた箇所について修正しました。
Play Framework2 RC2がリリースされ、モダンなWebアプリケーションを構築する手法として成熟した生産的な方法になっています。
Play2とScala,Anorm,JSON,CoffeeScript,jQueryを使って迅速なアプリケーション構築を体験してみましょう。
一度ローカルでアプリケーションが動いてしまえば、あとはHerokuにデプロイするだけです。
(注意:これはmy Play1+Java turtorialの、Play2+Scala版です。)Githubからソースを入手してください。
Step 1) Play2 RC2版をダウンロード・インストールしてください。
Step 2) 新しいアプリケーションを作ります:
プロンプトの言語選択画面がでたら、Scalaを選択してください。
Step 3) 新しく作成した”foobar”ディレクトリ配下にIDEの設定ファイルを生成します。
IntelliJでは、このように実行します。
注意:ここで生成されたIMLファイルは、プロジェクトとして直接インポート可能ではありません。代わりに、モジュールなしでプロジェクトを新たに生成して、このステップで生成したIMLファイルからそのプロジェクトへモジュールをインポートする必要があります。もしわからなければ、Play1+Scala IntelliJ articleが参考になります。
Eclipseプロジェクト化するために、下記のコマンドを実行
Step 4) Playサーバの起動
正常に起動していることをテストするために、ここにアクセスhttp://localhost:9000
Step 5) Play2 with ScalaではデフォルトでORマッパーを提供していません。代わりにデフォルトのRDBMS永続性プロバイダとなっているのがAnormです(Anormは Object Relational Mapperではありません)。このシンプルなアプリケーションでは、1つの永続的オブジェクト:Bar(ひとつのプライマリキーと名前を持っている)を持っています。Anormは、自動でのスキーマ作成を行わないので、SQLスキーマの作成/廃棄のためのスクリプトが必要です。新しいファイル”conf/evolutions/default/1.sql”を作成し、以下の内容を記述します。
Anormでは、Scalaの”case class”を永続的/CRUDインターフェースとして、値オブジェクトとシングルトンオブジェクトとして扱うことができます。”app/models/Bar.scla”というファイルにBar case classとオブジェクトを作成して、以下の内容を記述します。
変数の”simple”は、データベースの行値をBar case classにマップする、基本的なパーサを提供します。
静的関数、”findAll”と”create”は、一般的なデータアクセスを行います。
注意点としては、”findAll”はBarへ各行を返すために、”simple” row parserを使っている点です。
Step 6) インメモリーのh2データベースを使うために、”conf/application.conf”ファイルに以下の値を設定する。
Step 7) “app/controllers/Application.scala”を下記のように更新し、BarをHTTP POSTへ変換してデータベースに反映するアプリケーションコントローラー関数を作成します。
“barForm”マップは、フォームオブジェクトへパラメータを要求し、入力データのバリデーションを行います。 静的関数の”addBar”は、リクエストと”barForm”へのリクエストパラメータのマッピングを行います。 失敗した場合は、コントローラはBadRequestを返します。 成功した場合は、Barの名前は新しい”Bar”を構築するために使われます。そしてその”Bar”はデータベースに保存され、indexページへのリダイレクトが送られます。 index関数は、Step 9で更新されるテンプレートへ”barForm”を渡すように変更されました。
Step 8) “conf/routes”ファイルに以下の行を追加して、”/addBar” URLへのPOSTリクエストを”Application.addBar”へマップする新しいルートを作成します。
Step 9) フォームパラメータを受け取るために、”main”テンプレートを拡張した”app/views/index.scala.html”テンプレートを更新し、Webページ上のフォームをレンダリングするためにPlay2 form helperを使います。
ブラウザでhttp://localhost:9000を開き、データベース変更の適用と、フォームのテストをします。うまくできていれば、フォームを送信するとindexページへリダイレクトされるはずです。
Step 10) JSONサービスを作成し、barの全てを取得するための関数を、”app/controllers/Application.scala”ファイルに追加します。
新しく作成した関数は、シリアル化されたJSONとして、”Bar.findAll()”から”Bar”オブジェクトのリストを返します。
“/listBars”へのリクエストのために、下記のように新しいGET request handlerを”conf/routes”に追加します。
ブラウザでhttp://localhost:9000/listBarsを開いてみてください。Step 9で作成したbarが表示されているはずです。
Step 11) jQueryを使いJSONシリアル化されたbarの取得と、それぞれのページ追加のために、新しいCoffeeScriptファイル”app/assets/javascripts/index.coffee”を作成します。内容は以下
CoffeScriptは、”/listBars”へのGETリクエストの作成と返却値の反復、ページ(Step 12で追加します)の”bars”エレメントへの各アイテムの追加のために、jQueryを使います。
Step 12) CoffeeScriptのソースから自動コンパイルされたindex.jsスクリプトを使うために、”app/views/index.scala.html”を以下の行を”main”ブロックへ追加し、更新します。
ブラウザで、http://localhost:9000/を表示し、barがページ上部に表示され、新しいbarが期待通りに追加されていることを確認してください。
これで、Scala, Anorm, JSON, CoffeeScript, jQueryを使ったPlay2アプリのビルド完了です。ここで紹介したすべてのソースコードはGitHub上にあります。あとはHerokuへデプロイするだけです。
Latest post:
- OpenWhiskのScala sbtプロジェクトのgiter8テンプレートを作った
- OpenWhisk+Scalaで作るServerless Architectureとっかかり
- BluemixにPlayframeworkアプリケーションをデプロイする
- sbt、Giter8を統合するってよ
- Scala 2.12.0でSAM型
Recent Books:
- 【意訳】Play Framework 2.0とJsTestDriverによるJavaScriptテスト。 (21 Feb 2012 | Tags:
【意訳】Play Framework 2.0とJsTestDriverによるJavaScriptテスト。 【意訳】Play Framework 2.0とJsTestDriverによるJavaScriptテスト。
Testing javascript with Play Framework 2.0 and JsTestDriverを適当翻訳でご紹介します。
元記事はこちら
qwallet.comでは、バックエンドにScala on Play2.0を使った広大なjavascriptアプリケーションを構築しています。
Scalaの開発にIntelliJ IDEAを使うようになってからは、JavaScriptでも同じように使っています。
これにより、IntelliJとJsTestDriverの統合による恩恵を受けています。
JavaScriptアプリでは、常に3つのブラウザを対象にテストをしています。
テストコンソールにはテスト結果と、ブラウザからフェッチされたコンソール出力を確認できます。
上の試験例では、FireFox, Chromeのテストは通っていますが、Safariでは失敗しています。 サンプルでは3つのテストケースがあり、拡張した1つは2つのテストメソッドを持っています。 もしエラーが発生した場合、スタックトレースがクリッカブルになり、IntelliJはエラーの行右側に飛びます。
テストはとても速いですが、この小さなサブセットのためにChromeでは6msかかっていますが、まだ改善の余地があります。
Play2.0の親切なところは、JavaScriptファイルの自動コンパイルです。 JsTestDriverのdevモードでは、ライブラリファイルとテストケースをブラウザに送り、アプリケーションファイルはPlay2.0アプリケーションによって送られます。 Playは、ファイルの変更を検知して自動でリコンパイルします。 テストを書くときに見逃しているかもしれないものをコンパイラがキャッチしてくれ、結果としてカバレッジが向上します。
CIモードでは、JavaScriptファイルは1度コンパイルされておりPlayを経由して送られる必要がない。 この方法はとても早く、Playがバックグラウンドで実行されている必要性を低減してくれます。
qwallet.comの継続的デプロイの運用では、アプリケーションの全ての部分をテストします。 JsTestDriverはクロージャーコンパイラーとバンドルされ、fast devモードユニットテストとテスティングストラテジーのコンポーネントとして提供されています。
ところで、もし興味があったら、jobs@qwalletにメールを送ってくれ。
Latest post:
- OpenWhiskのScala sbtプロジェクトのgiter8テンプレートを作った
- OpenWhisk+Scalaで作るServerless Architectureとっかかり
- BluemixにPlayframeworkアプリケーションをデプロイする
- sbt、Giter8を統合するってよ
- Scala 2.12.0でSAM型
Recent Books: