最近2.0がリリースされたVert.xについて、皆さんご存じでしょうか?
Vert.xは一言で表現すると、
Vert.x is a polyglot, non-blocking, event-driven application platform that runs on the JVM.
です(公式サイトより引用)。
JVM上でのnon-blockingでevent-drivenなプラットフォームな所が私のお気に入りポイントです!まぁ、Java屋さんですからね。うちは。
そんなお気に入りのVert.xについて、これから数回に分けて本ブログにて記事を書いて行こうと思います。
Vert.xを知る
Vert.xを知るには、ドキュメントが充実した公式サイトを読むのが一番です。ですが、ボリュームがかなりあるので、オススメのサイトを紹介します。
- vert.xのハイボリューム/スケーラブルなアーキテクチャ - Eberhard Wolff氏とのインタビュー
- 内部から見たVert.xとNode.jsとの比較 - uehaj's blog
- Vert.x 2.0.0-final is released! | The Vert.x Blog
- Open source Java projects: Vert.x | JavaWorld
- Tim Fox氏、Vert.x 2.0の変更点について語る
多すぎてボリュームあるじゃんという突っ込みはなしで(^^;
Vert.xの良いところ
まぁ、たくさんあるんですけど、個人的には次の5つです。
- asynchronous programming model for writing scalable non-blocking applications
- advantage of the JVM and scales seamlessly over available cores
- a distributed event bus
- a powerful module system
- polyglot
1. asynchronous programming model for writing scalable non-blocking applications
Node.jsが人気な理由も同じですが、ノンブロッキングな非同期APIにより、少ないリソースで多数のクライアントからの要求を処理できます。
参照: C10K問題
Vert.xによるアプリケーションはVerticleと呼ばれる実行可能なパッケージを作ってVert.x Instance(Vert.xのプロセス)上で動作させるのですが、このVerticleは必ず1つのEvent Loop(スレッド)が割り当てられます。そのため、Verticleのコードを書く上では、同期や排他などを考える必要がなく、ソースコードが簡単になります。
2. advantage of the JVM and scales seamlessly over available cores
Node.jsはシングルスレッドで処理するので、マルチスレッドに処理したい場合はclusterを使って別のプロセスを立てる必要があります。ですが、Vert.xではJVMによるマルチスレッドが利用できるので、1つのVert.x Instanceに対して、起動時にinstance数を指定することで、マルチスレッドで動作するようになり、マルチコアリソースを簡単に活用することができます。さらに、異なるサーバ上にVert.x Instanceを動作させて、clusterを組むことも簡単です。
3. a distributed event bus
Vert.xはアーキテクチャの土台としてdistributed event busを持っています。このevent busを使うことで、作成したVerticleや1つ以上のVerticleをまとめたモジュール(Module)間を疎結合につなぐことができます。event busはPoint to PointとPub/Subメッセージングが使えます。メッセージにはいろいろな型が使えますが、Vert.xでは多言語でコードを書くことができるので、JSONを使うのが一番良いようです。
複数のVert.x Instanceをクラスタ化するのにもこのevent busを使います。また、event bus bridgeを使うと、クライアント側のjsともevent busを共有できるようになります。
4. a powerful module system
Vert.xは強力なモジュールシステムを持っています。モジュールはmavenやBintrayに公開することができ、さらに、そこからインストールすることができます。Vert.x Module Registryには既に以下のようなモジュールが公開されています。
- io.vertx~mod-web-server
- io.vertx~mod-mongo-persistor
- io.vertx~mod-auth-mgr
- io.vertx~mod-work-queue
- com.jetdrone~mod-redis-io
- com.jetdrone~yoke(Node.jsのConnect相当)
5. polyglot
JVMを使って多言語対応をしているため、Vert.xのVerticleはJava、Groovy、JavaScript、Ruby、Pythonで開発することができます。さらに近々Scala、Clojureもサポートされるとアナウンスされています。Vert.x 2.0からは各言語用の機能も上述のモジュールとして開発されており、必要なものだけを使うことができます。
個人的にはJavaで書ければ良いのですが、例えば他の人がJavaScriptやScalaを使って開発した優れたモジュールがあれば、それをevent busを介して利用できるのは素晴らしいことです。
開発者とコミュニティ
開発をリードしているのは@timfoxさんで、この方はRabbitMQの開発者でもあります。@normanmaurerさんはNettyの開発者でもあり、Vert.xはNettyと密接に連携しながら開発されています。二人とも現在はRedHat所属のようです。
コミュニティはGoogle Groupsを中心に作られているのですが、このフォーラムの最初にある注意書きがステキです。
Please don't use StackOverflow to ask Vert.x questions - ask them here!
この注意書きのおかげで(?)、情報がバラバラにならずに、このフォーラムに集まっています。1日の投稿数も多くて活発であり、レスポンスも非常に早いです。私も少しお世話になりました。
また、つい最近Vert.xプロジェクトはEclipse Foundationの傘下になりました。
Vert.xでHello World
実際にVert.xによる開発ってどんな感じ?かは公式サイトをご覧下さい。Node.jsでも紹介されるようなweb-serverのコードを、Java、JavaScript、Groovy、Ruby、Pythonで書いた例が紹介されています。
まぁ、これだけだとこの記事的に寂しいので、JavaによるHello Worldのコードをのせておきます。
public class MainVerticle extends Verticle { public void start() { container.logger().info("MainVerticle start."); vertx.createHttpServer().requestHandler(new Handler<HttpServerRequest>() { public void handle(HttpServerRequest req) { req.response().headers().set("Content-Type", "text/plain"); req.response().end("Hello World!"); } }).listen(8080); } }
Vert.xを利用する場面
Vert.xがどのようなアプリケーションに向いているか?というと、WebSocket/SockJSを使ったリアルタイムWebアプリケーションのサーバ、RESTful APIによるサービスの実装とかでしょう。少ないリソース(サーバ)で多数のクライアントを処理することが可能であり、さらにスケールすることも容易という特長を活かしたい場面に使うと良いと思います。
後は、サーバ側でのクローラ−、Gatewayといったものを開発するのにも向いていると思います。
一般的なWebアプリケ-ションには向いていないとの声もあるようですが、Node.jsにExpressがあるように、Vert.xにはweb-serverやYokeといったモジュールもあるため、問題なく使えると思います。
Vert.xで注意すべきこと
良いことばかり書いてきたので、私の考える注意すべきこともあげておきましょう。でも、書いてみるとVert.x特有というよりは、non-blocking, event-driven application platformを使う場合に注意すべきことですね。
1. コードのネストが深くなる
非同期処理のコールバックを受けるハンドラを登録し、そのハンドラの中で、次の処理のコールバックのハンドラを登録して・・・となりがちです。これはコードの書き方で工夫すべき点ですが、何も考えないと見通しの悪いコードになってしまいます。
2. ブロックするコードを書いてはいけない
1つのEvent Loopを複数のVerticleが共有するため、ブロックするコードを書いてしまうと、他のVerticleの処理も影響を受けてしまいます。Thread.sleep()、Object.wait()やCPUヘビーな処理、ブロックするライブラリの呼び出し(例えばJDBC)はやめてね、とドキュメントにも書かれています。
じゃあ、実際に必要になったらどうすれば良いの?というと、Vert.xではWorker VerticleというEvent Loopとは別のスレッドプール(Worker Pool)上で動作するVerticleが用意されているので、これを使うことでEvent Loopからブロック処理を切り離すことができます。橋渡しはもちろんevent busで。
3. ステートフルな処理は状態遷移に注意すること
モジュール内部に状態を持つような機能を開発する場合には、状態遷移表/状態遷移図などを使った十分な設計と、ステートマシン的な実装上の仕組みを用意して開発しないと、後で大変なことになります。
See also
- Vert.x がいいね!(第2回:開発環境を構築する) - Taste of Tech Topics
- Vert.x がいいね!(第3回:Event LoopsとVerticle Instances) - Taste of Tech Topics
- Vert.x がいいね!(第4回:テストする) - Taste of Tech Topics
- RxJavaを使ってCallback Hellから脱出する( Vert.x がいいね!第5回 ) - Taste of Tech Topics
- RxJavaを使ってCallback Hellから脱出する( Java8 ラムダ編 ) - Taste of Tech Topics