データフローDSLという観点で、今までScalaで2つの内部DSLをつくってきました。一つはモデル記述の私家版Asakusa DSL、もう一つはg3向けのフレームワークAPIです。
今回はg3向けのフレームワークAPIについて考えます。
g3については、このブログでも色々書いてきました。詳細は以下のリンクを参照してください。
g3
g3はクラウドアプリケーションのサーバーサイドで動作するサービス部向けのアプリケーションフレームワークです。
元々は、SimpleModelerでクラウドアプリケーションの生成を行う際に、現状では適切なフレームワークが見つからなかったので、「威力偵察」的な意味もあって自分で作ってみることにしたものです。
以下の特徴を備えています。
- REST指向
- イベント駆動
- サービス・バス
- Atom Publishing指向
- マルチ・プラットフォーム
- 運用のスケーラビリティ
- パイプライン・プログラミング
- 並行処理
- HTML生成やRDBMSアクセスをドライバモジュールでモジュール化
- WebSocket
REST指向、イベント駆動、サービス・バス
クラウドアプリケーション・フレームワークとして、まず欲しかったのはREST指向のイベント駆動&サービス・バスです。
RESTイベントをハンドリングするというより、すべてのイベントをRESTイベントとして抽象化して、この抽象RESTイベントでサービスを駆動します。サービスはサービス・バス上で動作し、チャネルを介して疎結合&非同期に連携します。
エンタープライズの世界ではESB(Enterprise Service Bus)が広く用いられています。ESBはアプリケーションレベルの少し粒度の大きいモジュールをターゲットにしたもので、現状ではXMLを用いて組立て情報を記述するのが一般的です。また、モジュールの連携にはMQを想定しています。EIP(Enterprise Integration Patterns)もこのESB上での構築を想定したものです。
g3の提供するサービス・バスは、ESB的なものをよりシンプルにインメモリ指向で使うことを指向しています。ただし、PaaSと連携することで、クラウドスケールのESBとして使用することもできるようなアーキテクチャにしています。
たとえば、Google AppEngineとの連携は現状でも可能です。Google AppEngineはPaaSの先行事例なので、アーキテクチャの確認の意味もあり、g3では当初から対応しています。
まだ未実装ですが、技術的にはJMS経由でMQを介して他のESBとの連携も可能なはずです。
Atom Publishing指向
抽象REST指向をさらに進めて、抽象Atom Publishing指向の要素を加えています。通常は抽象Atomとしてデータ操作して、必要に応じて抽象度の低い抽象RESTデータを操作することを指向しています。
マルチプラットフォーム&運用のスケーラビリティ
g3はマルチプラットフォームと運用のスケーラビリティも念頭において設計しています。抽象RESTイベントという切り口で、外部イベントと内部処理を疎結合にしているのがポイントです。
- スタンドアロンコマンドとしても動作
- Servlet
- Google AppEngine
g3は、CLIのインタフェースを抽象RESTイベントに変換するフロントエンドを持っているので、スタンドアロンのコマンドでも動作できるようになっています。
g3は、普通のServletとして動作させることができます。このため、TomcatやJava EE環境でそのまま利用できます。
g3は、Google AppEngine上で動作させることもできます。g3は、AppEngineのスケーラビリティを活かすようなアーキテクチャになっています。AppEngineのPaaS機能によって、クラウドスケールでのスケーラビリティを得ることができるようになるはずです。
パイプライン・プログラミング&並行処理
チャネルで抽象RESTイベントが発生しますが、この抽象RESTイベントをパイプライン上上で処理するのがg3の眼目の一つです。狭義では、一連のエントリ「データフローDSL考」で話題にしている項目です。
私家版Asakusa DSLは、モデル記述用とということもあって静的型付けにしていますが、g3はイベント駆動のアプリケーションAPIということもあるので動的型付けにして、パイプラインを上を流れるデータをPartialFunctionでマッチしたもののみ処理を行うプログラミング・モデルにしてみました。このプログラミング・モデルでは、複数種類のイベント(正常系イベントと異常系イベントなど)を同じパイプライン上に流すことが可能になります。
「データフローDSL考」シリーズで説明してきたとおり、単純なパイプラインでは、複雑なデータフロー・モデルを記述することはできません。
g3では、この問題を解決するために、サービス・バスを用います。チャネルから抽象RESTイベントで駆動されたパイプラインは、パイプライン上で加工処理を行いながら、他のチャネルに対して新たな抽象RESTイベントを同期発行または非同期発行していきます。パイプライン上での加工処理が完了後、RESTイベントを同期発行した主体に処理結果を返します。
このように、サービス・バスを経由して他のパイプラインと連携するメカニズムを導入することによってパイプライン・モデルの欠点を克服しています。
サービス・バスによってパイプライン・プログラミング・モデルの問題を解決することを含めて、広義のデータフローDSLと考えることができます。g3では、この広義のデータフローDSLという観点でも、パイプライン・プログラミング・モデルがうまく機能することを確認できました。
問題は、非同期発行した処理を回収するための同期機構です。この同期機構を実現するために、g3の内部で重たい処理をしているのですが、g3のユースケースを勘案した上での全体のバランスからするとちょっと重たすぎた感じがあり、改良ポイントと考えています。
HTML生成やRDBMSアクセスをドライバモジュールでモジュール化&WebSocket
抽象RESTイベント、サービス・バス、パイプライン・プログラミングのメカニズムの上でモジュールによる機能拡張のメカニズムを構築しました。色々な機能をこのセマンティクス&DSL的にうまく埋め込めることが確認できました。
評価
g3は、アプリケーションAPIとしてのデータフローDSLとしては色々チャレンジしてみた項目も含めて、概ねうまくいっているかなというのが自己評価です。ポイントは、パイプライン・プログラミング・モデルとサービス・バスをScala DSLでうまく結び付けることができた点です。
ただ、色々と使ってみて以下の点が問題を認識しています。
- 非同期同期機構が重たすぎる(前述)
- 可能であれば静的型付け化したい
- モデル記述DSL(SimpleModeler)との統合がしたい
新技術
g3を作りはじめた2010年初頭からは、Scalaでも色々な技術革新がありました。g3もこれらの技術を取り込んで、DSLをさらに最適化していく必要があります。
- 型クラス
- Monadicプログラミングの進化(Scalaz)
- Scala DSL技術の進化(Unfiltered など)
- 並行プログラミングの進化(Akka、Scalaz Promiseなど)
- マクロ(Scala 2.10予定)
- Play 2.0
型クラスを用いると、静的型付けのセマンティクスでパイプラインを駆動できるのではないかという期待があります。また、モデル記述DSLとの統合も可能かもしれません。型クラスの登場によって、いろいろな可能性が広がってきました。
Monadicプログラミング、Scala DSL技術、並行プログラミングは地道に進化してきており、2010年年初段階とは別世界の感があります。これらの進化を取り込んで、より強力なプログラミング・モデルを構築する必要があります。
さらに、Scala 2.10ではマクロ機能の導入が予定されています。このマクロはC的なテキスト置換のマクロではなく、ASTレベルでモデル操作ができるものです。これはかなり強力で、DSL技術に大きく寄与することになるでしょう。
プラットフォームとしては、Play 2.0が非常に強力なので、これもターゲットに加えて行きたいところです。
今後の展開
g3も2010年年初段階の技術ベースとしては、いい感じになっていると思いますが、最新技術の視座からみると少し古びてきているようです。
特に、型クラスやMonadicプログラミングの技術を使うことで、より簡潔で強力なプログラミング・モデルを構築できる可能性が高く、この進化を取り込んでいくことが急務です。
並行プログラミングも、フレームワーク内で独自に行うよりもAkkaなどの機構をうまくプログラマが活用できる形に持って行く方が適切です。
また、可能であれば静的型付けやモデルDSLとの統合なども行っていきたいところです。
以上の点から、g3をオーバーホールして、次世代向けのアプリケーション・フレームワークを作ることを考えています。技術的にはScala 2.10のマクロ機構のインパクトが極めて大きそうなので、この技術の評価ができた後に取り組むことになりそうです。
0 件のコメント:
コメントを投稿