連載
» 2013年12月18日 18時00分 UPDATE

Scala+Play 2.0でWebアプリ開発入門(11):Play2+nginx/Akka/WebSocketで高速双方向通信 (1/2)

Play framework 2.xを既存のWebサーバーと連携させる方法、並列処理や双方向通信を行う方法を紹介します。

[中村修太,クラスメソッド株式会社]

 前回の記事「Play2(+JavaScript)アプリを高速化、最適化する4つのテクニック」では、キャッシュの利用方法や非同期通信を行う手法、クライアントサイドでJavaScriptをうまく扱うテクニックについて紹介しました。

 今回はPlay framework 2.x(以下、Play2)を既存のWebサーバーと連携させる方法、並列処理や双方向通信を行う方法を紹介します。

WebサーバーとPlay2の連携

Webサーバーと連携する必要性

 連載第2回記事「Play 2.0のアーキテクチャとディレクトリ構成の基礎知識」で解説をしましたが、Play2では「Netty」というHTTPサーバーを内包しており、それを使用してリクエストを処理します。そのため、Play2の起動ポートを80番に設定すれば通常のWebサーバーと同じようにアクセス可能です。

 単純なWebアプリケーションの場合はこれで問題はないのですが、単一サーバーで複数アプリを使用したり、サーバーをクラスタリングしてスケーラブルにしたい場合には、フロントにApacheやnginxなどのHTTPサーバーを使用して、Play2アプリ(Netty)と連携させることもできます。

補足:いまさら聞けない、nginxとは

nginx(エンジンエックス)は、オープンソースのWebサーバーで、2013年時点ではApache、IISに次ぐ使用率を持っています。

HTTP以外にもリバースプロキシの機能を持っており、Proxyサーバーとして他のアプリケーションサーバーと同時に使用されることも多いようです。既存のWebサーバーよりリソースを抑えつつ、高い処理性能を実現できます。


 では、nginxをインストールしてPlay2アプリと連携して動かしてみましょう。

nginxのインストール

 まずはnginxをインストールしましょう。ここでは、OS X/Mac OS XでHomebrewを使用している場合を説明します。下記コマンドでnginxをインストールできます。

% brew install nginx

 それ以外の環境でnginxをインストールする場合、nginxのコミュニティサイト「InstallJa」のページを参照してインストール方法を確認してみてください。

 インストールが完了したら起動してみましょう。

% nginx

 上記コマンドを実行し、「http://localhost:8080」にアクセスして、次のような画面が表示されればインストールは完了です。

scalaplay11_1.jpg

Play2と連携させてみよう

 では、nginxのリバースプロキシ機能を使用してPlayアプリと連携させてみましょう。Homebrewでインストールした場合「/usr/local/etc/nginx」に「nginx.conf」があります。

※設定ファイルの場所が分からない場合、「nginx -t」コマンドを実行すれば、どこにある設定ファイルを使用しているかが分かります

 nginx(80番ポートで起動)にアクセスがきたら、Playアプリへフォワードするように指定します。

http {
・
・
・
    upstream my-backend {
        server 127.0.0.1:9000;
    }
 
    server {
        listen       80;
        server_name  localhost;
 
        location / {
            proxy_pass  http://my-backend;
        }
・
・
・
}

 nginx.confを編集したらnginxを再起動し、Playアプリを起動しましょう。

% nginx -s reload(sudoが必要な場合もあります)
% cd /path/rour/gyro
% play run

 アプリが起動したら、「http://localhost」にアクセスしてみてください。今までと同じく、Playアプリが実行されています。このように、簡単にnginxとPlayアプリが連携できていることが分かります。

Akkaを使用したスケジューリング処理

Akkaとは

 Akkaとは、Scala/Javaで非同期処理を実現するためのライブラリで、Scalaの開発元であるTypesafe社が中心となって開発しています。Akkaは軽量な並列処理のためのActorモデルをベースとしており、分散/並列/耐障害性を持ったイベント駆動型アプリケーションを構築できます。

scalaplay11_2.jpg Akka

 Akkaは「アクターシステム」と呼ばれるコンテナーを持っており、Play2アプリでは、アプリケーション自身が使う特別なアクターシステムが定義されています(※独自のアクターシステムを使用しても問題ありません)。

 そして、Play2アプリのアクターシステムを利用するためには、play.api.libs.concurrent.Akkaオブジェクトを利用します。

import akka.actor._
val act = Akka.system.actorOf(Props[MyAct],name="myAct")

 なお公式ドキュメントでは、「デフォルトのアクターシステムは、実行するアクターの数が少なく、別のアクターシステムを自分で用意するまでもないような場合に利用するとよい」とあります。こちらも併せてご確認ください。

 この章ではPlay2アプリ上でAkkaを使用し、スケジューリング処理を行ってみましょう。

タスクのスケジューリング

 Akkaを利用することで、任意の処理を一定時間ごとに実行したり、指定時間後に1回だけ実行したりすることができます。

 以前、アプリ起動時に処理を行うため、いつも使用しているgyroプロジェクトに、GlobalSettingsを継承したGlobalオブジェクトを作成しました。このオブジェクトでAkkaを使用してタスクのスケジューリングを行ってみましょう。

 Globalを作成していない場合、appディレクトリ下に「common.scala」という名前のファイルを作成してください。common.scalaでは下記のように記述しましょう。

import play.api._
import play.api.Play.current
import scala.concurrent.duration.DurationInt
import play.api.libs.concurrent.Akka
import play.api.libs.concurrent.Execution.Implicits._
object Global extends GlobalSettings {
  override def onStart(app: Application) {
    //↓以前作成したコード
    Logger.info("Application has started for " + app.mode + " mode.")
    app.mode.toString match {
      case "Prod" => Logger.info("Prod mode.")
      case "Dev" => Logger.info("Dev mode.")
      case "Test" => Logger.info("test mode.")
      case _ => Logger.info("unknown mode.")
    }
 
	//5秒後に1回だけ実行
    Akka.system.scheduler.scheduleOnce(5 seconds) {
    	println("execute Once")
    }
	//10秒ごとに実行
    Akka.system.scheduler.schedule(0 seconds, 10 seconds) {
    	println("execute Every 10 seconds")
    }
  }
  override def onStop(app: Application) {
    Logger.info("Application shutdown...")
  }
}

 アプリ起動時(devモードでは初回アクセス時)に実行されるonStart関数では、Akka.system.schedulerを使用して、スケジューリング処理を実行しています。scheduleOnce関数では第1引数の指定時間後に{}内の処理が1回だけ実行され、schedule関数では第1引数時間後に第2引数時間ごとに{}内の処理が実行されます。

 上記記述をしたら、アプリを起動してアクセスしてみてください。コンソールにメッセージが表示されます。

 なお、「5 seconds」といった特殊な記述は、importしている「scala.concurrent.duration.DurationInt」で暗黙的型変換が行われることによって可能になっています。

 次ページでは、AkkaとWebSocketを使ったサンプルを試してみましょう。

       1|2 次のページへ

Copyright© 2017 ITmedia, Inc. All Rights Reserved.

@IT Special

- PR -

TechTargetジャパン

この記事に関連するホワイトペーパー

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。