アジェンダ
- Jettyとは何か
- SPDY
- 主要なコンポーネントの概要説明
- GroovyでSPDYサーバを実行する
- WebSocket
- 主要なコンポーネントの概要説明
- GroovyでWebSocketサーバを実行する
- WebSocketサーバをSPDY上で実行する
- まとめ
- Javaで実装されたHTTPサーバ。
- デフォルト非同期I/O。
- JEE6 WebProfile実装なのでServletをデプロイ出来る。
- ニッチで先進的な機能が満載。
- 比較的コードがクリーンでライセンスが緩いのでハックし易い。
- Stableリリースは7系と8系だが今回は開発版の9系ベースで話をする。
- Eclipse Public License - Version 1.0 / Apache License - Version 2.0
- 主にintalioの人がメンテナンスしている。
SPDY
- npn-boot
- npn-api
- spdy-core
- spdy-client
- spdy-server
- spdy-http-server
- Java用のNext Protocol Negotiation Extension実装。
- OpenJDKの名前空間である sun.security.ssl をダーティハックしている為、GPL。
- eclipse foundationでは無く、mortbay.org名義でリリースしているが、作業している人は同じなので単に政治的なアレだと思う。
- Javaがセキュリティアップデートする度に修正が入ったものがリリースされる。
_人人 人人人_
> 突然のGPL <
 ̄Y^Y^Y^Y^Y ̄
npn-api
- NPNをJettyから使う為のラッパーレイヤー
- クラスは1つしかないので特に見るべきものは無い
spdy-core
- SPDYプロトコルを実装しているモジュール
- 対応しているバージョンはV2とV3
spdy-core package構成
- org.eclipse.jetty.spdy
- org.eclipse.jetty.spdy.api
- org.eclipse.jetty.spdy.frames
- org.eclipse.jetty.spdy.generator
- org.eclipse.jetty.spdy.parser
- 入力仕様に対する実装
- 酷いコードの様に見えるかもしれないけど、Javaでプロトコルパーザを普通に書いたらこんなもん。
spdy-client
- 非同期I/OベースのSPDYクライアントライブラリ
- SPDYに対応しているサーバをクローリングするなら速いかも
- 自前SPDYサーバを自動テストするのに使うと良いかも?
spdy-server
- Jettyのサーバフレームワーク上に実装されているSPDYのサーバ実装
- 主にSPDY用TCPコネクションの管理コード
spdy-http-server
- HTTP上で動作する為のサーバ処理
- 文字列に関する処理は全部ここ
- SPDY-http-proxyの実装
- JettyをSPDYサーバとして使う場合このモジュールを使う
SPDYサーバを実行する
new org.eclipse.jetty.server.Server().with {
def connector = new org.eclipse.jetty.spdy.server.http.HTTPSPDYServerConnector(it,
new org.eclipse.jetty.util.ssl.SslContextFactory(
keyStorePath: 'src/main/resources/spdy.jks',
keyStorePassword: 'password',
protocol: 'TLSv1'))
connector.port = 8443
addConnector connector
handler = new org.eclipse.jetty.server.handler.ResourceHandler(
resourceBase: 'src/main/resources/webcontent')
start()
join()
// https://localhost:8443/spdy.html
// chrome://net-internals/#spdy
}
WebSocket
- websocket-api
- websocket-common
- websocket-client
- websocket-servlet
- websocket-server
WebSocketの位置づけ
- アプリケーションでは直接使うべきではないもの。
- CometD の様な抽象度が高いフレームワークを使うべき。
- WebSocketはフレームワークを作る人間が叩くAPI
websocket-api
- 実装はほぼ無くinterfaceの定義が中心。
- Futureパターンによる非同期I/O
- JettyでWebSocketするなら理解する必要がある。
- JavaEE7ではWebSocketが使える様になる。
websocket-common
- WebSocketプロトコルを実装しているモジュール
- RFC6455実装
- 以前は様々なバージョンのWebSocketに対応していたがJetty9で大胆に削除
websocket-common package構成
- org.eclipse.jetty.websocket.common
- Parser見とけばJavaでのWebSocket実装は大体分かる。
- org.eclipse.jetty.websocket.common.events
- WebSocketにおけるサーバとアプリケーションのGlueコードが記述されている。
- org.eclipse.jetty.websocket.common.extensions.compress
- org.eclipse.jetty.websocket.common.extensions.fragment
- org.eclipse.jetty.websocket.common.extensions.identity
- fragmentとidentityは、よく分からない。
- org.eclipse.jetty.websocket.common.extensions.mux
websocket-client
- 非同期I/OベースのWebSocketクライアントライブラリ。
- multiplexing対応のコードもある。
websocket-servlet
- ServletとしてWebSocketアプリケーションをデプロイする為のライブラリ。
- JettyでWebSocketするなら、このモジュールを使う。
websocket-server
- Jettyのサーバフレームワーク上に実装されているWebSocketのサーバ実装。
- multiplexing対応を含むWebSocket用TCPコネクションの管理コード。
- ExampleEchoServer.javaを見れば使い方は大体分かる。
WebSocketサーバを実行する
@org.eclipse.jetty.websocket.api.annotations.WebSocket
class Echo {
@org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage
void onText(org.eclipse.jetty.websocket.api.Session session, String msg) {
session.getRemote().sendStringByFuture(msg)
}
}
new org.eclipse.jetty.server.Server(8080).with {
handler = new org.eclipse.jetty.websocket.server.WebSocketHandler.Simple(Echo)
handler.handler = new org.eclipse.jetty.server.handler.ResourceHandler(
resourceBase: 'src/main/resources/webcontent')
start()
join()
// http://localhost:8080/
}
WebSocket on SPDY
@org.eclipse.jetty.websocket.api.annotations.WebSocket
class DoubleEcho {
@org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage
void onText(org.eclipse.jetty.websocket.api.Session session, String msg) {
session.getRemote().sendStringByFuture("$msg $msg")
}
}
new org.eclipse.jetty.server.Server().with {
def connector = new org.eclipse.jetty.spdy.server.http.HTTPSPDYServerConnector(it,
new org.eclipse.jetty.util.ssl.SslContextFactory(
keyStorePath: 'src/main/resources/spdy.jks',
keyStorePassword: 'password',
protocol: 'TLSv1'))
connector.port = 8443
addConnector connector
handler = new org.eclipse.jetty.websocket.server.WebSocketHandler.Simple(DoubleEcho)
handler.handler = new org.eclipse.jetty.server.handler.ResourceHandler(
resourceBase: 'src/main/resources/webcontent')
start()
join()
// https://localhost:8443/
// chrome://net-internals/#spdy
}
まとめ
- Javaでプロトコルパーザを書くと酷い
- Jettyは全体的に非同期I/O
- JettyのWebSocketはCometD越しに使うのがオススメ
- SPDYの上にWebSocket乗せるのは楽勝