Hatena::Groupdann

dann's blog このページをアンテナに追加 RSSフィード

Fork me on GitHub

2010-03-07

SEDA (Staged Event-Driven Architecture)

 SEDA (Staged Event-Driven Architecture) - dann's blog を含むブックマーク はてなブックマーク -  SEDA (Staged Event-Driven Architecture) - dann's blog  SEDA (Staged Event-Driven Architecture) - dann's blog のブックマークコメント

Casssandraの設計を理解する上で、SEDAのアーキテクチャを理解する必要があったので調べてみました。

http://www.eecs.harvard.edu/~mdw/papers/seda-sosp01.pdf

既存技術の問題

  • Thread modelは設計・管理しやすいがサーバのスケーラビリティという観点からは問題あり。負荷が増えると、スレッドコンテキストの切り替えでスループットも落ち、一定以上の負荷の下では性能が出ない。
  • Event model は負荷には強いがスケジューリングがアプリケーションに任されるため、設計・実装が難しい

SEDAで提案しているアーキテクチャ

ThreadモデルとEventモデルのいいとこ取りをするために、

  • アプリケーションを、複数の独立なStageに分離して管理する。
  • 各Stageをincoming event queue, thread pool, application-supplied event handlerで構成し、各ステージはイベントをpassingすることで繋ぐ
  • event handlerでは、Threadのallocationとschedulingを気にしないようにStageで隠蔽

する

という構成を取っている。

SEDAの構成の利点

  • 各ステージはスレッドにより実行される
  • スレッドとコネクション要求の処理とを分離するため、コネクション数が増えてもスレッド数が増加してスループットが落ちることはない
  • アプリケーション(event handler)はスレッドのスケジューリングなどを気にしなくて良い
  • ステージでは、ステージごとに様々なスケジューリング・スレッドモデルを採用可能
  • ステージ間のeventのやりとりが監視しやすい
Sedaの構成要素について

Stageとresource controllerが構成要素。

SEDA Stage
  • Stageは、incoming event queue, thread pool, application-supplied event handlerから構成される。
  • Stageの操作は(resource allocationとschedulingを行う)controllerによって管理される
  • 各ステージのロジックは、event handlerに実装される。event handlerで処理して、他のstageのincoming event queueにイベントをつっこむ
SEDA resource controllers
  • Thread pool controller
    • stage内で実行するスレッドの数を調整する。event queueのメッセージ数を観察して、thread poolのサイズを調整する。
  • batching controller
    • event handlerの各iterationで処理するイベントの数を調整する

See also

以下の二つの論文もざっと目を通しておこうかなと。

CassandraとSEDAのアーキテクチャの対応関係

 CassandraとSEDAのアーキテクチャの対応関係 - dann's blog を含むブックマーク はてなブックマーク -  CassandraとSEDAのアーキテクチャの対応関係 - dann's blog  CassandraとSEDAのアーキテクチャの対応関係 - dann's blog のブックマークコメント

Cassandraで、SEDAのアーキテクチャをどのように実装しているかを調べてみました。SEDA対応部分は、concurrent.utilのお陰でとてもシンプルな実装でわかりやすいですね。

https://svn.apache.org/repos/asf/incubator/cassandra/trunk/

以下、概要です。

SEDA Stageに対応するもの

以下の二つ

  • Event queue + Thread Pool
    • StageManagerで定義されているThread Pool Executor
  • application handler
    • MessagingServiceに登録されているVerbHandler

SEDA Resource controller

  • SEDA Thread pool controller
    • StageManagerにあたる。ただ、動的なリソース管理はしていない。
  • Cassandraで定義されているStage (StageManager)
   public final static String READ_STAGE = "ROW-READ-STAGE";
    public final static String MUTATION_STAGE = "ROW-MUTATION-STAGE";
    public final static String STREAM_STAGE = "STREAM-STAGE";
    public final static String GOSSIP_STAGE = "GS";
    public static final String RESPONSE_STAGE = "RESPONSE-STAGE";
    public final static String AE_SERVICE_STAGE = "AE-SERVICE-STAGE";
    private static final String LOADBALANCE_STAGE = "LOAD-BALANCER-STAGE";

メッセージ配送処理

メッセージ配送の主要ロジック

MessagingServiceのrecieveメソッドからがメッセージ配送処理の肝。以下が概要。

  • MessagingServiceは、Messageのタイプをみて、Stageを取得
  • StageをStageManagerから取得して、メッセージ配送タスクに処理を委譲
  • メッセージ配送タスクでは、メッセージのverbにしたがって、verbHandlerを取得して、VerbHandlerを実行
  • VerbHandler中で処理を実行(doVerb)して、MessagingServiceでメッセージ配送(sendOneWayで)
メッセージ送信部分

こちらもMessagingServiceで。

  • sendRRでmessage送信するときに、taskCompletion_に突っ込んでおいて、sendOnewayでメッセージを非同期送信。
  • Futureパターンで、getAsyncResultメソッドでメッセージ受け取り。TcpConnectionのpoolからTcpConnectionを取得して、データ送信。
メッセージの送信
  • データの送信はTCP
  • 制御は、UDP

所感

SEDA対応部分の実装は、java.util.concurrentのパワーのお陰でとてもシンプルな実装でわかりやすいなと。

他に思ったのは、APIサーバーは、SEDAモデルと相性がいいかもなぁと。Stageが1個だけでいいケースも割と多そうなので、ステージを分割する意味がでるケースがどれだけあるかは少し微妙かもしれないけど。ただ、SEDAのアーキテクチャ的には、1個のステージでもいいわけで、汎用のAPIサーバーを作りたければ、SEDAのアーキテクチャは面白いかもなぁと思いました。

cassandraの実装を見て、concurrent.utilとNIO系のフレームワークを組み合わせて、SEDAのアーキテクチャをベースにして、APIサーバーを作れば、割と現実的なものができそうだなぁと思ったのでした。コード的にはさほど量を書かなくても書けそうです。

# SEDA部分意外も実装として面白そうなので、読みすすめようかなと思ってます。