grizzly フレームワーク non-blocking ソケットと非同期処理に対応した http...

25
© 2006 The Seasar Foundation and the Others, All rights reserved. Grizzly Grizzly フフフフフフフ フフフフフフフ Non-Blocking Non-Blocking フフフフフフフフフフフフフフフ フフフフフフフフフフフフフフフ HTTP HTTP フフフフフフフフフフフフフフフフフ フフフフフフフフフフフフフフフフフ Learning.sandbox.seasar.o rg 2006-12-27 フフ フフ

Upload: sheri

Post on 05-Jan-2016

56 views

Category:

Documents


0 download

DESCRIPTION

Grizzly フレームワーク Non-Blocking ソケットと非同期処理に対応した HTTP 等プロトコルハンドラフレームワーク. Learning.sandbox.seasar.org 2006-12-27 栗原 傑享. About Grizzly - とりまく環境 -. GlassFish の傘下コンポーネント 内包される Web コンテナの部品 プロトコルハンドラを作るための F/W NIO の Non-Blocking ソケットを活用する F/W 最近、 java.net のトッププロジェクトへ - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: Grizzly フレームワーク Non-Blocking ソケットと非同期処理に対応した HTTP 等プロトコルハンドラフレームワーク

© 2006 The Seasar Foundation and the Others, All rights reserved.

GrizzlyGrizzly フレームワークフレームワークNon-BlockingNon-Blocking ソケットと非同期処理に対応したソケットと非同期処理に対応した

HTTPHTTP 等プロトコルハンドラフレームワーク等プロトコルハンドラフレームワーク

Learning.sandbox.seasar.org

2006-12-27 栗原 傑享

Page 2: Grizzly フレームワーク Non-Blocking ソケットと非同期処理に対応した HTTP 等プロトコルハンドラフレームワーク

© 2006 The Seasar Foundation and the Others, All rights reserved.

About Grizzly - About Grizzly - とりまく環境 とりまく環境 --

• GlassFish の傘下コンポーネント– 内包される Web コンテナの部品

• プロトコルハンドラを作るための F/W

– NIO の Non-Blocking ソケットを活用する F/W

• 最近、 java.net のトッププロジェクトへ– https://grizzly.dev.java.net/

• Grizzly が採用されている OSS プロダクト– Jetty6.1

• http://www.mortbay.org/

– AsyncWeb• http://docs.safehaus.org/display/ASYNCWEB/Home

– JRuby on Rails• われらが、高井さんのプロジェクト。この先 Grizzly に同梱?

Page 3: Grizzly フレームワーク Non-Blocking ソケットと非同期処理に対応した HTTP 等プロトコルハンドラフレームワーク

© 2006 The Seasar Foundation and the Others, All rights reserved.

About Grizzly - About Grizzly - 守備範囲 守備範囲 --

• Non-Blocking ソケット通信– Java NIO にて提供される Non-Blocking ソケット(以

後、 NB ソケット)通信をフレームワーク化して容易に用いることができるようにしている。

• 非同期処理– Ajax や昨今の Web2.0 的アプリケーションで求めら

れる、超長期トランザクションに NB ソケット通信でも対応できる機能をフレームワーク上に応用実装した。

– さらに、 Ajax/Comet の機能をデフォルト提供• デフォルト HTTP 機能

– Grizzly は専ら HTTP のハンドラとして機能が設計、提供されている。

– 2.0 計画の中では、 ESB エンジンの実装基盤など、非 HTTP もしくは HTTP からさらに発展した今後、汎用のプロトコル通信フレームワークとして発展させていく野心があるように、説明されている。

Page 4: Grizzly フレームワーク Non-Blocking ソケットと非同期処理に対応した HTTP 等プロトコルハンドラフレームワーク

© 2006 The Seasar Foundation and the Others, All rights reserved.

BlockingBlocking ソケットソケット• NIO 以前

– Java.net パッケージの API を利用– Servlet コンテナの価値 = このコーディングを隠蔽

ServerSocket server = new ServerSocket(8080); Socket con = server.accept(); InputStream in = con.getInputStream();for(int b = in.read(); b != -1; b = in.read()) { // 読み込み}// ロジック実行( Servlet の実行など)OutputStream out = con.getOutputStream();for(int b = /* 書き出しバイトのバッファ */ ) { out.write(b);}

サーバソケット Open

接続 Accept

リクエスト Read

レスポンス Write

接続 Close

ロジック実行

Blocking

Blocking

Blocking

•例外処理、コネクション Close など省略

スレッド

Page 5: Grizzly フレームワーク Non-Blocking ソケットと非同期処理に対応した HTTP 等プロトコルハンドラフレームワーク

© 2006 The Seasar Foundation and the Others, All rights reserved.

Non-BlockingNon-Blocking ソケット ソケット - - ソーソース ス --

ServerSocketChannel channel = ServerSocketChannel.open();channel.socket().bind(new InetSocketAddress(8080));Selector selector = Selector.open(); channel.register(selector, SelectionKey.OP_ACCEPT);while(selector.select() > 0) { for(Iterator<SelectionKey> it = selector.selectedKeys().iterator; it.hasNext(); ) { SelectionKey key = it.next(); it.remove(); if(key.isAcceptable()) { SocketChannel socket = channel.accept(); socket.register(selector, SelectionKey.OP_READ); } else { if(key.isReadable()) { /* 読み込み */ } if(key.isWritable()) { /* ロジック実行、書き出し */ } } }}

•例外処理、コネクション Close など省略

コード例は不完全で、実際に動かすためにはほぼ倍以上の実装量が必要

Page 6: Grizzly フレームワーク Non-Blocking ソケットと非同期処理に対応した HTTP 等プロトコルハンドラフレームワーク

© 2006 The Seasar Foundation and the Others, All rights reserved.

アプリ

Non-BlockingNon-Blocking ソケットソケット

SelectorServerSocket

ChannelSocket

Channel

登録( ON_ACCEPT )SelectionKey に結びつく

ループselect を繰り返す

チャネル BINDクライアントから接続

Acceptable に設定

クライアントからリクエスト受信

SocketChannel 取得

初期化

isAcceptable ? Yes !

Accept 処理

登録( ON_READ )SelectionKey に結びつく

isReadable ? Yes !

Readable に設定

読み込み

isWriable ? Yes !書き込み

クライアントへ

省略のため UMLを故意に誤用

Writable に設定

スレッド

Page 7: Grizzly フレームワーク Non-Blocking ソケットと非同期処理に対応した HTTP 等プロトコルハンドラフレームワーク

© 2006 The Seasar Foundation and the Others, All rights reserved.

スレッドに優しい仕組みスレッドに優しい仕組み

• NB ソケット– スレッドの占有の問題を解決する

• ソケット接続を維持( OS 機能)、スレッドは適宜解放• OS 機能に「待ちうけ時間」は負担してもらう• 結果、接続数あたりのスレッドの消費が少ない

• リスク– 実装が複雑になること -> Grizzly で解決。– スケーラビリティをアプリケーション外部(クラ

スタリングなど)で確保するのであれば、 Blocking のほうが単純なので早いものが作れる

Page 8: Grizzly フレームワーク Non-Blocking ソケットと非同期処理に対応した HTTP 等プロトコルハンドラフレームワーク

© 2006 The Seasar Foundation and the Others, All rights reserved.

No ApacheNo Apache

• http://weblogs.java.net/blog/jfarcand/archive/2005/06/grizzly_an_http.html– But as other Java based HTTP Connector, scalability is always li

mited to the number of available threads, and when keep-alive is required, suffer the one thread per connection paradigm. Because of this, scalability is most of the time limited by the platform's maximum thread number. To solve this problem, people usually put Apache in front of Java, or use a cluster to distribute requests among multiple Java server.

• 前後の事情も込みで意訳 – ( Grizzly がベースとして採用している Tomcat Coyote も含め

た従来の) Java ベース HTTP コネクタは、スケーラビリティは常に利用可能スレッド数に制限されています。 keep-alive でリクエストされた時は長い接続単位あたりそれぞれにずーっと1 スレッドが費やされ続けます。そのため、スケーラビリティは多くの場合プラットフォームの最大スレッド数に制限されます。この問題を解決するために、普通みんなは Apache HTTPD を Java システムの前に置いたり、たくさんの Java アプリケーションサーバをクラスタしてますね。(これは大変な苦労です。)

• Grizzly により、 Apache 無しの Java システムで OK になる。

Page 9: Grizzly フレームワーク Non-Blocking ソケットと非同期処理に対応した HTTP 等プロトコルハンドラフレームワーク

© 2006 The Seasar Foundation and the Others, All rights reserved.

Simple GrizzlySimple Grizzly

package org.ashikunep.iyomante;import com.sun.enterprise.web.connector.grizzly.SelectorThread;import com.sun.enterprise.web.connector.grizzly. standalone.StaticResourcesAdapter;import org.apache.coyote.Adapter;

public class SimpleGrizzly {

public static void main(String[] args) throws Exception { SelectorThread selectorThread = new SelectorThread(); selectorThread.setPort(8080); Adapter adapter = new StaticResourcesAdapter(); selectorThread.setAdapter(adapter); selectorThread.initEndpoint(); selectorThread.startEndpoint(); }

}

Tomcat Coyote のクラス

この Adapter を作って設定するのが、想定されている Grizzlyアプリケーションの開発方法。ここで用いているものは、静的なファイルを読み出して返すもの。

これだけで、最低限の機能ながらちゃんと動く

Page 10: Grizzly フレームワーク Non-Blocking ソケットと非同期処理に対応した HTTP 等プロトコルハンドラフレームワーク

© 2006 The Seasar Foundation and the Others, All rights reserved.

参考: 参考: Adapter Adapter インターフェインターフェイスイス

package org.apache.coyote;public interface Adapter {

void service(Request req, Response res) throws Exception;

void afterService(Request req, Response res) throws Exception; void fireAdapterEvent(String type, Object data);

}

package org.apache.coyote;public final class Request { public Response getResponse () { return response; } …}

package org.apache.coyote;public final class Response { public void doWrite(ByteChunk c) { … } …}

Page 11: Grizzly フレームワーク Non-Blocking ソケットと非同期処理に対応した HTTP 等プロトコルハンドラフレームワーク

© 2006 The Seasar Foundation and the Others, All rights reserved.

SelectorThread

GrizzlyGrizzly の構造の構造

クライアントから接続

SocketChannel

Selector(ACCEPT 用 )

ON_ACCEPT

Pipeline(Read 用 )

Pipeline(Process 用 )

ReadTask

ProcessorTask

ON_READ

StreamAlgorism

Adapterユーザー

アダプターごめんなさい、書きかけです。登場人物が多すぎ

Page 12: Grizzly フレームワーク Non-Blocking ソケットと非同期処理に対応した HTTP 等プロトコルハンドラフレームワーク

© 2006 The Seasar Foundation and the Others, All rights reserved.

GrizzlyGrizzly のアーキテクチャ のアーキテクチャ - - 用用語 語 --

• SelectorThread– NB ソケット処理のメインスレッドを隠蔽– nio.Selector 、 Pipeline を複数もつ

• ( Pipeline )– Task を単位として管理するスレッドプール

• Task– ソケットに対する処理を分割した単位– ( ReadTask )

• ON_READ に対する処理、 SlectorThread より実行される– ProcessorTask

• ON_WRITE に対する処理、 ReadTask より実行される• Adapter ( Tomcat Coyote より)

– ProcessorTask より実行される• ( Handler )

– Grizzly への高度なカスタマイズを行うイベントハンドラ– 今のところ、 Coyote との接続や Async の実装に使われるのみ

で、拡張ポイントとしてはあまり活用されていない。

Page 13: Grizzly フレームワーク Non-Blocking ソケットと非同期処理に対応した HTTP 等プロトコルハンドラフレームワーク

© 2006 The Seasar Foundation and the Others, All rights reserved.

GrizzlyGrizzly のアーキテクチャ のアーキテクチャ - - 逆引き逆引き --

• 接続処理 – SelectorThread#startEndpoint() で開始– クライアントからの接続要求に応答

• 読み込み処理 – ReadTask インターフェイスを実装する – クライアントから到着するリクエスト電文を読む。

• ビジネスロジック&書き込み処理 – ProcessorTask インターフェイスを実装

• もしくは、 coyote.Adapter を実装。– リクエスト電文に応じて処理を行う。 DB アクセスしたり、画面遷移したり、応答書き出しをすいる。

Page 14: Grizzly フレームワーク Non-Blocking ソケットと非同期処理に対応した HTTP 等プロトコルハンドラフレームワーク

© 2006 The Seasar Foundation and the Others, All rights reserved.

SSLSSL 対応対応

• 使ってる例が見当たりません– Jetty も Grizzly の SSL 機能を使ってない?– AsyncWeb も Grizzly の SSL 機能を使ってな

い?• コードを読むと

– SelectorThread の代わりにSSLSelectorThread を利用するだけのハズ。。。しかし動かない。。。

– ということで、いつかどこかでの、宿題。• たぶん、 WEB コンテナを作るために必要なので

近日に解明するでしょう。

Page 15: Grizzly フレームワーク Non-Blocking ソケットと非同期処理に対応した HTTP 等プロトコルハンドラフレームワーク

© 2006 The Seasar Foundation and the Others, All rights reserved.

非同期処理非同期処理

• NB ソケットは単一もしくは少数スレッドで多数の接続を処理する。– 読み込み、書き込みともに(大抵は)同一スレッドで多

数の接続を処理– ロジック実行に長時間が経過するアプリケーションだと、

この超ロングトランザクションによってスレッドがいわば「 Blocking 」されてしまう

• Task 処理をマルチスレッドで実行する– 特に ProcessorTask の処理– このあたりの技術をひとまとめに、 Grizzly では

「 Asynchronous Request Processing ( ARP )」と呼ぶ。

• 基本的に、ここに踏み込むことはあまりない。– Comet の実装など、プロトコル処理の根底に関わる仕組

みで、かつ非同期実行がその解決策であるときに利用

Page 16: Grizzly フレームワーク Non-Blocking ソケットと非同期処理に対応した HTTP 等プロトコルハンドラフレームワーク

© 2006 The Seasar Foundation and the Others, All rights reserved.

ARPARP

• 新たに、登場人物– AsyncFilter, AsyncHandler, AsyncExecutor

SelectorThread st = new SelectorThread();st.setPort(8080);st.setAdaptor(new StaticResourcesAdapter());AsyncHandler handler = new DefaultAsyncHandler();handler.addAsyncFilter(new AsyncFilterImpl());st.setAsyncHandler(handler);st.setEnableAsyncExecution(true);st.initEndpoint();st.startEndpoint();

class AsyncFilterImpl implements AsyncFilter { public boolean doFilter(AsyncExecutor executor) { … return false; }}

ここで何をやるのかが、大抵ネタが無い。必要なモノは AsyncExecutor が実行時コンテキストとしていろんなものを提供してくれているので、それを使ってプログラミング

Page 17: Grizzly フレームワーク Non-Blocking ソケットと非同期処理に対応した HTTP 等プロトコルハンドラフレームワーク

© 2006 The Seasar Foundation and the Others, All rights reserved.

CometComet

• Comet とは– CNet の江島氏の BLOG に詳しい

• http://blog.japan.cnet.com/kenn/archives/003149.html– サーバからクライアントへの通信をリアルタイムに行って、情報を擬似的に

プッシュを実現する– KeepAllive=true でつなぎっぱなしの仕組み

• スレッドが爆裂する問題にどう取り組むか?その答えが NB ソケット• Grizzly では Comet 対応が標準組み込み

http://www.machu.jp/diary/20060411.html より図を引用

1)と 6) の間には長い時間経過を許す。2)による書き込みがなければ、ずっとつなぎっぱなしで待機。

Page 18: Grizzly フレームワーク Non-Blocking ソケットと非同期処理に対応した HTTP 等プロトコルハンドラフレームワーク

© 2006 The Seasar Foundation and the Others, All rights reserved.

まとめまとめ

• Grizzly はプロトコルハンドラをつくるためのフレームワークである

• 特別踏み込まなければ驚くほど簡単• NIO の NB ソケットをゼロから使って同様

なものを作ってもいい、しかしいろいろ嵌るので Grizzly を使うと吉

• 基本的な NB ソケットによる HTTP ハンドラに加え、 SSL 対応、非同期処理、 Comet エンジンがそれぞれ標準で組み込まれている

Page 19: Grizzly フレームワーク Non-Blocking ソケットと非同期処理に対応した HTTP 等プロトコルハンドラフレームワーク

© 2006 The Seasar Foundation and the Others, All rights reserved.

今回触れなかったもの その今回触れなかったもの その 11

• 今回触れなかった、 2 つのパッケージ– com.sun.enterprise.web.ara– com.sun.enterprise.web.portunif

• ARA– Grizzly’s Application Resources Allocation– RCM の実装、 JSR284 にて作業中のものを意識

• Resource Consumption Management • Google のリードで、 2006年 12月 18日にパブリッ

クレビュー終了したところ。これからファイナルドラフトへ

• あらゆる Java アプリケーションで扱う「リソース」を管理する仕組み。 Grizzly ではスレッドとメモリに注目。

– ルールベースによる Read タスクの分散技術?

Page 20: Grizzly フレームワーク Non-Blocking ソケットと非同期処理に対応した HTTP 等プロトコルハンドラフレームワーク

© 2006 The Seasar Foundation and the Others, All rights reserved.

今回触れなかったもの その今回触れなかったもの その 22

• 今回触れなかった、 2 つのパッケージ– com.sun.enterprise.web.ara– com.sun.enterprise.web.portunif

• PortUnif– TCP ソケットの送信バイトをちょっと見て、プロト

コルの種類を識別する仕組み?単一ポートで複数プロトコルを取り扱うことが狙いのようである。 HTTPと HTTPS を扱うものが同梱されている

SelectorThread st = new SelectorThread();st.setPipelineClassName(PortUnificationPipeline.class.getName());…st.initPipeline();PortUnificationPipeline pup = (PortUnificationPipeline)st.getReadPipeline();pup.addProtocolFinder(…);pup.addProtocolHandler(…);

Page 21: Grizzly フレームワーク Non-Blocking ソケットと非同期処理に対応した HTTP 等プロトコルハンドラフレームワーク

© 2006 The Seasar Foundation and the Others, All rights reserved.

今回説明できなかったこと今回説明できなかったこと

• SSL を利用した Grizzly アプリケーション– 時間作って、 GlassFish のコードを読んでみます

• ARP 、 Comet の具体的動き– これは理解&ちゃんと動作済み。しかし当面取り

組むネタが無い。可能性を考察していきましょう。–整理:

• ビジネスロジックを実行するのに、時間がかかるとき有効な仕組み

• NB ソケットは基本的にシングルスレッドの下で動くので、これをちゃんとやらないと全体速度に関わる

• Comet は今、ホットな話題だそうです。手軽にはCometd や Jetty6 で試すことができます。

Page 22: Grizzly フレームワーク Non-Blocking ソケットと非同期処理に対応した HTTP 等プロトコルハンドラフレームワーク

© 2006 The Seasar Foundation and the Others, All rights reserved.

GrizzlyGrizzly に無いものに無いもの

• WEB コンテナを作る上で Grizzly に無いもの– そもそも: WEB コンテナ仕様– ブートストラップ– アプリケーションコンテナ

• 仮想化されたファイルシステム– セッションマネジメント

• クラスタリング– 認証関連

• Grizzly にあるけど作りたくなるもの– リクエストパーサ、レスポンスアウトプッター– ログ出力– JMX 対応等、管理関連 ( JMX 、あるのです!)

Page 23: Grizzly フレームワーク Non-Blocking ソケットと非同期処理に対応した HTTP 等プロトコルハンドラフレームワーク

© 2006 The Seasar Foundation and the Others, All rights reserved.

参考資料参考資料• 開発者: Jean-Francois Arcand の Blog

– http://weblogs.java.net/blog/jfarcand/– Grizzlyおよび NIO の高度な話題、しかし更新頻度が

低い。• JavaOne2005/2006 プレゼンテーション

– http://72.5.124.65/learning/javaoneonline/2005/webtier/TS-3227.pdf

– http://weblogs.java.net/blog/jfarcand/archive/2006_BOF0520.pdf

• Grizzly ソース– ほか、 AsyncWeb や Jetty ソースのごく一部

• NIO による Non-Blocking ソケット通信– 「 ServerSocketChannel 」「 Selector 」

「 SelectionKey 」などで検索すると結構たくさん出てくる。しかし、ほぼ初級な話題。

Page 24: Grizzly フレームワーク Non-Blocking ソケットと非同期処理に対応した HTTP 等プロトコルハンドラフレームワーク

© 2006 The Seasar Foundation and the Others, All rights reserved.

おまけおまけ

Page 25: Grizzly フレームワーク Non-Blocking ソケットと非同期処理に対応した HTTP 等プロトコルハンドラフレームワーク

© 2006 The Seasar Foundation and the Others, All rights reserved.

フレームワークの限界フレームワークの限界

• 最近の私の主張– いろいろありますが、アプリケーションに近い F/W だけで

なんとかできることも減ってきてるでしょ?(以下略)– バカ対策 F/W を否定するのであれば、その解決策を模索し

ていかなければならない• 私の考える二つの方向性へのヒント

– WEB コンテナなど、アプリケーションのブートストラップからの見直し -> Grizzly の出番もあるか? Kvasir ?

– Eclipse プラグインなどの IDE だけに止まらない、開発環境アプリケーションの創造

• しばらく具体的な話は蒸発する状態でのみします– ほら、世間って怖いし w 。。。ということで今日、放談。– 具体的なアプリケーションを見せないと、机上の空論だし