arcanum_jp’s blog

おっさんの日記

Nettyをちょいと勉強

先日からきしださんがJJUGなどでServletオワコンと言っていたので、、、


多分これは最近きしださんが講演で発表したこの資料からだと思われる

speakerdeck.com

自分もこの資料(jjug行けない地方民は資料から察するしかないのです(笑))は見ていて、あぁそういう世界もあるんだなと、Helidonなんかは簡単にサンプルを実行させてみたりしてたのですが、Servletはもうオワコンと言う。

根拠の一つはすでにServletベースのフレームワークが出ていない、と言う事、そう言えばみんな大好きなSpringBootもServletベースだがこれも出てから何年たったのだろう。あとそれ以降Servletベースのフレームワークで新しいのを聞かない。

じゃぁJavaでWebをするときこれからは何を使えばいいの?ってなった時に多分、Oracleが公開しているHelidonなんかなんだろうと思うんだけど、そうすると仕事でやる上では疑問が起きてくる。

今までは、

1.Servletベースのフレームワークが使える

2.Servletベースからフレームワークが作れる

と言う知識が必要だったんだけど、これに、

3.Servletに拠らないフレームワークが使える

4.Servletに拠らないフレームワークが作れる

という知識が必要になってくるんじゃないかと、もちろん急激に1、2が廃れるはずもなく、今後Servletベースの知識は使えるとは思うけど、それ以外に3、4を学ばなくてはならない、少なくとも3は個人的にも知識、経験があるよと言えるようになってないといけないんではないかと。資料だとHelidonやMicronaut Framework、Quarkusあたり。

それらのフレームワークは色々な人がWebでエントリを公開していたりするけどじゃぁ4、のServletに拠らないフレームワークってどう作るんだろ?って思ったわけです。WebSocketから作るのか?そりゃ地獄だろ・・・という感覚しかない。きしださん曰く、どのフレームワークもベースはNettyとのこと、Netty?なんだろ?と思いちょいと勉強。(前置きが長すぎ)


Nettyの本家サイトはこちら。
netty.io

Nettyはこちらを参考にしました。
snuffkin.hatenablog.com

Nettyは、イベントドリブンな非同期通信を行うアプリケーションを開発するためのフレームワークです。ソケット周りを直接触る処理はNettyが行ってくれて、イベントドリブンで接続・切断時の処理を記述したり、電文受信時の処理を記述することができ、簡潔で見通しの良いネットワークプログラミングができます。また、Nettyには電文処理を行うアプリケーションを開発するときに必要なライブラリが用意されているため、オリジナルプロトコルを使う場合にもNettyを使えば開発しやすいです。

独自プロトコルのちょっとしたサンプル

今回も例によって例のごとく、人様の書いたエントリを教科書に勉強していきます。サンプルとしてこちらを確認してみました。

第1回
http://acro-engineer.hatenablog.com/entry/20130321/1363881318: title

第2回
http://acro-engineer.hatenablog.com/entry/20130327/1364394979: title

第3回
http://acro-engineer.hatenablog.com/entry/20130403/1364953739: title



3回構成で、1回目でサーバ側のコードを示して、2回目でクライアント側のコードを示しています。2回目まで作ると実行できる仕組みですね。3回目は1、2回目のソースを利用したNettyの解説です。クライアントから送信されたデータがサーバを伝ってクライアントにクルッと戻される感覚がわかります。


ソースコードはNettyの3系なのでpom.xmlに依存性追加するときは注意ですね。自分はMavenプロジェクトを作って適当にインポートされてるクラスを検索したらここが引っかかったので、依存性を追加して上記サイトのソースを入れて実行してみました。

Maven Repository: org.jboss.netty » netty » 3.2.0.Final

<!-- https://mvnrepository.com/artifact/org.jboss.netty/netty -->
<dependencies>
	<dependency>
    	<groupId>org.jboss.netty</groupId>
    	<artifactId>netty</artifactId>
    	<version>3.2.0.Final</version>
	</dependency>	
</dependencies>

Nettyは3系と4系でパッケージがガラリと変わっているので注意ですね。org.jboss.nettyで始まっていたら3系より以前、io.nettyで始まっていたら4系以降ということになります。Webで見つけられるサンプルが結構この辺苦労しました。コピペしたけど動かねぇ!なんでだ!みたいな。


上記サイトで記載しているサンプルは、サーバ側を実行してからクライアント側を起動すると標準出力にハローワールドが出ます。単純なサンプルでクライアントがサーバーに送った文字列をオウム返しにしています。著者が言うにはこの例で簡単な独自プロトコルの実装になっているそうです。サーバーもクライアントも送信と受信で、電文長+電文本体、という形式でやり取りしていて下記のような動きになっています。


クライアントが文字列送信
 ↓
サーバーが文字列受信
 ↓
サーバが文字列送信
 ↓
クライアントが文字列受信(標準出力に出力)


意外と面白いですが結構難しい。エントリではNettyの基本的な概念を教えてくれて助かります。パイプライン、アップストリーム、ダウンストリーム、ハンドラ、この辺をまず覚える必要がありますね。先ほどのブログの3回目に同じような概念図がありますが、実行したサンプルの流れを自分なりに大雑把に書くとこんな感じでしょうか。


f:id:arcanum_jp:20190629124956j:plain

パイプライン

 Nettyは送受信にパイプラインを作成して処理を行うそうです。クライアントサーバー間に確率されたトンネルみたいなイメージでしょうか。

ダウンストリーム、アップストリーム

 上記の図では、クライアント側もサーバー側もいずれも送信は情報の流れが下に、情報の受信が上になっているため、送信=ダウンストリーム、受信=アップストリームというそうです。

ハンドラ

 Nettyによって送信されてきたメッセージを処理するためのクラス。Nettyはネットワークでイベントドリブンとありましたがこれを言っているのでしょうか?ちょっと気になります。


ちなみにクライアントのこの部分をこんな風に変えるとクライアント側で送信した”Hello, World!”という文字列がサーバー側でクライアント側の情報が付加されて"handler : Hello, World!"と表示されます。ハンドラーで送信側の情報などが取れるみたいですね。

EchoServerHandler.java

public void messageReceived(ChannelHandlerContext ctx, MessageEvent event) {
    String msg = (String) event.getMessage(); // 受信電文を取りだす
    ctx.getChannel().write(ctx.getName() + " : " +msg); // クライアントに送信
}


でも自分は独自プロトコルなネットワークプログラミングをしたいわけではなく、HTTPな処理を実装するにはどうするか?なので次回にNettyでのHTTPの実装を調べてみたいと思います。