今回はJBoss OpenSource Projectの一つであるNetty Projectを紹介します。
Nettyは高性能・高スケーラビリティなネットワークアプリケーションを快速開発するために設計されたNIOクライアント・サーバフレームワークです。
Nettyを使うと複雑なNIO Selector APIを知らなくても簡単に非同期なイベント駆動型のネットワークアプリケーションの作成が可能になります。
簡単とはいえ、APIや使い方の説明になると楽しくないので、
ここでは実際にNettyを利用してMemcachedサーバを作ってみることにします。
動作環境について
・JDK1.5以上
・Nettyの最新バージョン(現時点で3.2.1-Final)
Memcachedサーバの実装について
・Binary Protocolのみ
・GetとSetのみ
・KeyとValueのデータタイプはStringのみ
まずはNettyの特徴について簡単に説明します。
NettyはChannel、ChannelBuffer、EventModelの3つのコンポーネントで構成されています。
NettyはP2P通信に必要なオペレーションをChannelという非同期I/Oインタフェースに抽象化します。
Javaの伝統的なI/O APIは転送タイプごとにメソッドが異なって、転送タイプが変わるとそれぞれ実装が必要ですが、Nettyでは転送タイプごとにChannelFactoryが用意されていて、異なる転送タイプへのPortingもChannelFactoryを変えるだけです。
(例:SocketとDatagramSocketは完全に違う方式でSocket I/Oを行う)
Channel間のデータの交換にはChannelBufferを使います。
Channelで発生するChannelEventはChannelPipelineのChannelHandlerによって処理されます。
ChannelHandlerにはInboundを担当するChannelUpstreamHandlerとOutboundを担当するChannelDownstreamHandlerがあります。
ChannelEventの制御はChannelPipelineを組むことでできます。
例えば、データがソケットから読み込まれるときに何をするか定義します。
それではコードをみてみましょう。
(Getter/Setterは省略)
まずはMemcached Binary Protocol Specを参考して、Protocolを定義します。
Headerは24bytes固定サイズで、その中にBodyのサイズも含まれています。
ここではシンプルに Packet(Header, Body) で定義します。
TCP/IPのようなストリーム基盤転送では、受信データはソケット受信バッファに保存されます。
ストリーム基盤の受信データはBytesなので、それを解析してPacketに変換してくれるプロトコルデコーダが必要です。
NettyのFrameDecoderを拡張して、プロトコルデコーダを作成します。
NettyにはさまざまなCodecが用意されています。
詳しくはNetty Projectサイトのドキュメントを参考してください。
次はデコード済みのPacketでGetやSetを行うビジネスロジックハンドラーを作成します。
キャッシュにConcurrentMapを使っていますが、コード内ThreadSafeなどは考慮されていないので、普通のMapでも構いません。
クライアントにリスポンスを返す時にもPacketをbytesに変換してくれるエンコーダが必要ですが、今回ではビジネスハンドラー内でそのままエンコードして返します。
ここまでのフローを整理すると、
1. Request(Bytes)受信
2. デコード(Bytes ---> Packet)
3. ビジネスロジック実行、Responseをクライアントに返す
上記のフローとおりにPipelineを組みます。
mainメソッドを作成し、サーバを起動します。
Memcachedクライアントを使ってテストしてみましょう。
// client : spymemcached
MemcachedClient c = new MemcachedClient(
new BinaryConnectionFactory(),
AddrUtil.getAddresses("localhost:11211"));
c.set("hello", 0, "world");
System.out.println(c.get("hello"));
c.shutdown(3000, TimeUnit.MILLISECONDS);
終わりに
完璧な実装ではないですが、たった5つのファイルでMemcachedサーバが作れました。
Nettyはシンプルですが強力なアーキテクチャを持つネットワークフレームワークです。
スレッドモデルも提供していて、カスタマイズ(SEDAなど)することも簡単にできます。
Netty Projectサイトにはさまざまなサンプルコードも用意されているので、参考になると思います。
・Netty Project Site
http://jboss.org/netty.html
・Memcached Binary Protocol
http://code.sixapart.com/svn/memcached/branches/binary/server/doc/protocol-binary.txt