Java、Scala用マイクロサービスフレームワーク「Lagom」でシンプルなAPI実装:リアクティブプログラミング超入門(4)(2/2 ページ)
本連載では、リアクティブプログラミング(RP)の概要や、それに関連する技術、RPでアプリを作成するための手法について解説します。今回は、マイクロサービス向けフレームワーク「Lagom」について解説します。
Lagomとは
Lagomとは、リアクティブなマイクロサービス向けに設計されたサーバサイド用フレームワークです。リアクティブなアプリを構築するためのいろいろな機能を持っています。
非同期/ノンブロッキングAPI
Lagomでは基本的に全て非同期で通信を行います。これによって低レイテンシとなり、外部サービスの影響を受けづらくなります。
イベントソーシングとCQRS
イベントソーシングとは、「Akka Persistens」(Lagomが使用するPersistensモジュール)の基礎となる設計手法です。この仕組みはエンティティーに対する変化をCRUD(Create、Read、Update、Delete)で表現するのではなく、エンティティーに対するイベントを永続化し、そのイベントを再生することで最新の状態を復元するものです。
また、このイベントソーシングと相性の良い考え方が「CQRS(Command Query Responsibility Segregation:コマンドクエリ責務分離)」です。
CQRSでは、「データの読み込み」と「データの書き込み」は明確に違うものだという前提で、データストアへの処理をクエリ(データ読み込み)とコマンド(データ書き込み)に分けます。通常、コマンドは処理の成功/失敗のみの情報を返します。このコマンドがイベントソーシングにおける「イベント」に当たります。またクエリは、冪等性が保証されなければいけません。
この仕組みを使うと、データの読み込みと書き込みを明確に分離することが可能になります。Lagomは、これをフレームワーク側でサポートしています。
サーキットブレーカー(circuit breaker)
システムに障害は付きものです。重要なのは「いかに障害を小さくとどめて素早く復旧できるか」にあります。
サーキットブレーカーとは、障害が発生したサービスをシステムから分離させることでシステム全体を止めずに運用を続けることができる機能です。
Lagomでは、サーキットブレーカーで下記3つの状態を持ちます。
- close:サーキットブレーカーが閉じた状態。問題なく通信可能な状態
- open:サーキットブレーカーが開いた状態。サービスに問題があり、通信不可能。この状態から一定時間経過するとhalf-openに遷移する
- half-open:サービス復旧を行っている状態。成功すればcloseになり、失敗すればopenになる
このサーキットブレーカーの仕組みは簡単に使えます。タイムアウト時間やリトライ回数など、サービスごとに細かく設定することが可能です。
その他
これら以外に、Lagomでは簡単にサービスを実行できる開発環境と「ConductR」による管理機能を持っています。また、デフォルトのデータストアとして組み込みの「Apache Cassandra」がバンドルされています。
APIが提供されているプログラミング言語は「Java」と「Scala」です。
Lagomのインストールとサンプルの作成
次に、Lagomを実際にインストールしてアプリを作成してみましょう。
まずはここへアクセスし、プロジェクト名を指定して「Project作成」ボタンをクリックします。
プロジェクトをダウンロードしたらsbtコマンドで起動できます。
% cd path/your/project/lagom-scala-sbt % ./sbt runAll
アプリが起動したら、「http://localhost:9000/api/hello/World」にブラウザからアクセスしてみてください。「Hello, World!」と表示されるはずです。
curlコマンドでも試してみましょう。
% curl http://localhost:9000/api/hello/Taro Hello, Taro!
POSTメソッドで下記のようにすれば、データが登録されます。
% curl -X POST -d '{"message":"Hi"}' http://localhost:9000/api/hello/Hanako #GET % curl http://localhost:9000/api/hello/Hanako Hi, Hanako!
サンプルのソース説明
サンプルプロジェクトは、4つのサブプロジェクトで構成されます。
- hello-lagom-api
- hello-lagom-impl
- hello-lagom-stream-api
- hello-lagom-stream-impl
hello-lagom-apiとhello-lagom-implがサービスのセットになっており、hello-lagom-apiがサービス定義、hello-lagom-implがサービス実装です。hello-lagom-stream-apiとhello-lagom-stream-implはWebSocketを使用したサンプルです。
では、hello-lagom-apiの「HellolagomService」を見てみましょう。hello-lagom-apiプロジェクトの方では、サービスインタフェースの定義と、エンドポイントとのひも付けを行います。
例えばサンプルのHellolagomServiceでは、下記のようにpathCallでAPIのパスと関数を指定します。ここではGETで/api/hello/
//サンプルを少し編集 override final def descriptor = { import Service._ named("hello-lagom") .withCalls( pathCall("/api/hello/:id", hello _) ) .withAutoAcl(true) }
helloメソッドは、ここでは抽象メソッドとして記述されています。サービス用メソッドはServiceCall型を返すメソッドで、引数としてidを受け取り、型パラメーターはリクエスト型、レスポンス型を指定します。
/** * Example: curl http://localhost:9000/api/hello/Alice */ def hello(id: String): ServiceCall[NotUsed, String]
ここではリクエストパラメーターを受け取らないので「NotUsed」です。レスポンスは「String」となっています。
次に、hello-lagom-apiの実装であるhello-lagom-implを見てみましょう。hello-lagom-implの「HellolagomServiceImpl」では、hello-lagom-apiのHellolagomServiceトレイトを実装し、PersistentEntityRegistry(データ永続化用クラス)を持っています。
//サンプルを少し編集 class HellolagomServiceImpl(persistentEntityRegistry: PersistentEntityRegistry) extends HellolagomService { override def hello(id: String) = ServiceCall { _ => val ref = persistentEntityRegistry.refFor[HellolagomEntity](id) ref.ask(Hello(id)) } }
helloメソッドではストレージからidをキーにしてエンティティー(PersistentEntityRef)を探し、その結果を返します。
※デフォルトでは、組み込み用Cassandraを永続化に使用しています
APIを追加してみる
試しに、APIを追加してみましょう。最初に、hello-lagom-apiのHellolagomServiceに抽象メソッドを追加します。
def myApi(id: String): ServiceCall[NotUsed, String]
次に、descriptorで上記メソッドと追加するパスをひも付けましょう。
override final def descriptor = { import Service._ named("hello-lagom") .withCalls( pathCall("/api/hello/:id", hello _), pathCall("/api/myApi/:id", myApi _) ) .withAutoAcl(true) }
hello-lagom-implのHellolagomServiceImplでmyApiメソッドを実装します。
override def myApi(id: String) = ServiceCall { _ => Future{"myApi id = " + id} }
ソースの変更は自動でリロードされるので、そのまま下記コマンドを実行してみましょう。追加したAPIが動作しています。
% curl http://localhost:49848/api/myApi/Foo myApi id = Foo
以上がLagomにおけるシンプルなAPI実装の基本です。
次回はストリーミングデータ処理フレームワーク「Apache Spark」について
今回はマイクロサービス向けフレームワーク「Lagom」の基礎について解説しました。
このフレームワークはマイクロサービス開発を容易にするための機能を多く持っています。本稿では紹介しませんでしたが、サーキットブレーカーやクラスタリング設定も可能になっているので、興味のある方は公式ドキュメントをご確認ください。
次回は、Lightbend Platformの構成要素の1つ、ストリーミングデータ処理フレームワーク「Apache Spark」について解説する予定です。
Copyright © ITmedia, Inc. All Rights Reserved.
関連記事
- Java EE 8/9はマイクロサービス、リアクティブに向かう――MVCは生き残れるのか
デジタルトランスフォーメーション時代に生き残れるエンジニアに求められるものとは何か。長らく、日本のJavaコミュニティで存在感を示し続け、現在は日本マイクロソフトでJavaエバンジェリストとして活動する寺田佳央氏に聞いた。 - EJB、SOA、マイクロサービスへと至る大規模システム向けアーキテクチャの変遷
2000年前後からのアプリケーションアーキテクチャやEJB、SOAに触れながら、今後、大規模システム構築で主流になるであろう「マイクロサービス」アーキテクチャの意義と価値を考える。