§Akka の統合
Akka は、アクター・モデルに基づいて、これまでより高い抽象度で、並列かつスケーラブルなアプリケーションを実装するためのプラットフォームです。Akka は耐障害性を実現するために ‘Let it crash’ モデルを採用しています。これは、自己修復するアプリケーション、言い換えれば落ちないシステムを必要としていた通信業界で大きな成功を収めているモデルです。アクターは分散処理を意識せずに実現できるような抽象化を提供する一方で、スケーラブルかつ耐障害性のアプリケーションを実装するベースにもなります。
§アプリケーションのアクターシステム
Akka 2.2.0 は アクターシステム
と呼ばれるいくつかのコンテナを持ちます。それぞれのアクターシステムは、それに含まれるアクターを動かすためのリソースを管理します。
Play 2.0 アプリケーションには、アプリケーション自身が使う特別なアクターシステムが用意されています。このアクターシステムはアプリケーションのライフサイクルに追従し、アプリケーションと共に自動的に再起動します。
ノート: 独自のアクターシステムを使っても何の問題もありません。最初から用意されているアクターシステムは、いちいちアクターシステムをセットアップしなくてすぐにアクターを利用できる、という利便性のためだけにあります。
アプリケーションのデフォルトのアクターシステムを利用するためには、play.libs.Akka
ヘルパーを利用します。
ActorRef myActor = Akka.system().actorOf(Props.create(MyActor.class));
§設定
デフォルトのアクターシステムの設定は、Play アプリケーションの設定ファイルから読み込まれます。例えば、アプリケーションのアクターシステムのデフォルトディスパッチャを変更したい場合は、 conf/application.conf
ファイルにその設定を数行追加します。
akka.default-dispatcher.fork-join-executor.pool-size-max = 64
akka.actor.debug.receive = on
ノート: Akka の規約に基づいて設定ファイルにトップの設定キーを記述することで、同じファイル内で全く別のアクターシステムを構成することもできます。
Akka のログ設定については ログの設定 を参照してください。
§Akka Future
から Play Promise
への変換
Akka アクターと非同期的にやり取りをすると、 Future
オブジェクトが返ってきます。play.libs.F.Promise.wrap()
メソッドを利用すると、この Future
を Play の Promise
オブジェクトに簡単に変換することができます。
- Java
-
import akka.actor.*; import play.mvc.*; import play.libs.Akka; import play.libs.F.Function; import play.libs.F.Promise; import static akka.pattern.Patterns.ask; public class Application extends Controller { public static Promise<Result> index() { ActorSelection myActor = Akka.system().actorSelection("user/my-actor"); return Promise.wrap(ask(myActor, "hello", 1000)).map( new Function<Object, Result>() { public Result apply(Object response) { return ok(response.toString()); } } ); } }
- Java 8
-
import akka.actor.*; import play.mvc.*; import play.libs.Akka; import play.libs.F.Promise; import static akka.pattern.Patterns.ask; public class Application extends Controller { public static Promise<Result> index() { ActorSelection actor = Akka.system().actorSelection("user/my-actor"); return Promise.wrap(ask(actor, "hello", 1000)) .map(response -> ok(response.toString())); } }
§コードブロックを非同期的に実行する
Akka の典型的なユースケースは、Actor を特別難しい使い方をせずに、計算を並列化することです。例えば、あなたが並列計算を行うためにアクターのプールを作成しているようなら、もっと簡単(かつ高速な)方法があります。
- Java
-
import play.libs.F.*; import play.mvc.*; import java.util.concurrent.Callable; import static play.libs.F.Promise.promise; public class Application extends Controller { public static Promise<Result> index() { return promise(new Function0<Integer>() { public Integer apply() { return longComputation(); } }).map(new Function<Integer,Result>() { public Result apply(Integer i) { return ok("Got " + i); } }); } }
- Java 8
-
import play.libs.F.Promise; import play.mvc.*; import static play.libs.F.Promise.promise; public class Application extends Controller { public static Promise<Result> index() { return promise(() -> longComputation()) .map((Integer i) -> ok("Got " + i)); } }
§非同期タスクのスケジューリング
Akka では、アクターへのメッセージ送信やタスク (関数または Runnable
インスタンス) の実行を予約することができます。予約を行うと、結果として Cancellable
のインスタンスが返ってきます。その cancel
メソッドを呼び出すことで、予約した操作の実行をキャンセルすることができます。
例えば、testActor
に 30 分おきにメッセージを送信する場合は次のように書きます。
Akka.system().scheduler().schedule(
Duration.create(0, TimeUnit.MILLISECONDS), //Initial delay 0 milliseconds
Duration.create(30, TimeUnit.MINUTES), //Frequency 30 minutes
testActor,
"tick",
Akka.system().dispatcher(),
null
);
さらに、今から 10 ミリ秒後にコードブロックを一度だけ実行したい場合は、次のようにします。
- Java
-
Akka.system().scheduler().scheduleOnce( Duration.create(10, TimeUnit.MILLISECONDS), new Runnable() { public void run() { file.delete(); } }, Akka.system().dispatcher() );
- Java 8
-
Akka.system().scheduler().scheduleOnce( Duration.create(10, TimeUnit.MILLISECONDS), () -> file.delete(), Akka.system().dispatcher() );
次ページ: 多言語対応
このドキュメントの翻訳は Play チームによってメンテナンスされているものではありません。 間違いを見つけた場合、このページのソースコードを ここ で確認することができます。 ドキュメントガイドライン を読んで、お気軽にプルリクエストを送ってください。