Netty実戦IMインスタント通信システム(四)サービス側起動プロセス
6595 ワード
##
Netty実戦IMインスタント通信システム(四)サービス側起動プロセス
ゼロ、ディレクトリ IMシステム概要 Netty概要 Netty環境構成 サービス側起動プロセス 実戦:クライアントとサービス側の双方向通信 データ伝送キャリアByteBuf紹介 クライアントとサービス側通信プロトコルコーデック クライアントログイン を実現する.クライアントとサービス側の送受信メッセージ を実現する. pipelineとchannelHandler クライアントとサービス側pipeline を構築する解包粘包理論と解決策 channelHandlerのライフサイクル channelHandlerのホットスワップを使用してクライアント認証 を実現する.クライアント対話の原理と実現 グループチャットの開始と通知 グループチャットのメンバー管理(加入と退出、メンバーリスト取得) グループチャットメッセージの送受信およびNettyパフォーマンスの最適化 心拍と空き検出 まとめ 拡張 ###四、サービス側起動プロセスサービス側Demo まず、従来のIOスレッドの2つの大きなスレッドグループと見なすことができる2つのNioEventLoopGroupを作成しました. bossGroup:リスニングポートが新たに接続を受信するスレッドグループを示すインタフェーススレッドグループは、一般的に1つのスレッドを構成すればよい.NioEventLoopGroupのデフォルトの個数はCPUコア数*2 である. workerGroup:接続ごとにデータの読み書きを処理するスレッドグループを示します(ここでは、前のセクション「Netty」を振り返ることができますが、理解できません) 生活の例で言えば、1つの工場が運営されるには、必ず1人のボスが外で仕事をしなければならない.それから多くの従業員が具体的な仕事を担当しなければならない.ボスたちはbossGroupが1人でも複数でもいい.従業員たちはworkerである.bossGroupは接続を受信し、workerGroupの具体的な処理 に渡す.
次に、サービス側の起動作業を導くブートクラスServerBootStrapを作成しました. serverBootstrapを通ります.group(bossGroup,workerGroup)は、ブートクラスに2つのスレッドグループを構成するために使用され、このブートクラスのスレッドモデルも に定型化されている.その後、サービス側のIOモデルをNIOと指定し、serverBootstrapを通過した.チャンネル(NioServerSocketChannel.class)はIOモデルを指定します.もちろん、ここでは他の選択肢もあります.IOモデルをBIOと指定したい場合は、OioServerSocketChannelを構成します.classタイプでいいです.一般的にはそうしません.Nettyの優位性はNIOにあるからです. 次にchildHandler()メソッドを呼び出し、このブートクラスにChannelInitializerを作成します.ここでは主に各接続のデータ読み書き、ビジネス処理ロジックを定義します.理解しなくても大丈夫です.後で詳しく分析します.ChannelInitializerというクラスには、NettyのNIOタイプへの接続の抽象である汎用パラメータNioSocketChannelがあることに気づいた.このクラスはNettyのNIOタイプへの接続の抽象であり、私たちの前のNioServerSocketChannelもNIOタイプへの接続の抽象であり、NioServerSocketChannelとNioSocketChannelの概念はBIOモデルのServerSocketとSocketに相当する.
ここでパラメータ構成を最小化すると完了します.要約すると、Nettyサービス端子を起動するには、スレッドモデル、IOモデル、処理ロジックの3つのクラス属性を指定する必要があります.この3つがあればbind(8000)を呼び出し、8000ポートをローカルにバインドして起動することができます. 自動バインドインクリメンタルポート 上記のコードでは、8000ポートを直接バインドしました.次に、1000などの開始ポートを指定し、バインドに成功したかどうかを判断し、成功しなければ1001をバインドし、成功するまでバインドします. serverBootStrap.Bind()このメソッドは非同期で、呼び出された直後に結果を返しますが、バインドに成功したかどうかは分かりません.彼の戻り値はChannelFutureです.このChannelFutureにリスナーGenericFutureListenerを追加して、GenericFutureListenerのoperationCompleteメソッドでポートのバインドに成功したかどうかを傍受することができます.次に、ポートが正常にバインドされたかどうかを検出します:/** 自動インクリメントバインド有効ポート @author outman */private static void bind(ServerBootstrap serverBootstrap, int port) { serverBootstrap.bind(port).addListener(new GenericFutureListener>() {
}実行結果:(mysqlが3306ポートを占有しているため、3306バインドに失敗しました)バインドポートに失敗しました:3306正常バインドポート:3307サービス側起動に関する他の方法 handler():handler()メソッドは、以前に分析されたchildHandler()に対応することができ、childHandler()は、新しい接続データを処理するビジネスロジックを指定するために使用され、handlerは、サービス側起動中のいくつかのロジック を指定するために使用される. attr():attr()メソッドは、サービス側のchannel、すなわちNioServerSocketChannelにカスタム属性を指定し、channelを使用することができる.attr()このプロパティを取り出します.たとえば、サービス側channelにserverNameプロパティを指定できます.プロパティ値NettyServerです.つまり、NioServerSocketChannelにmap: を維持します. childAttr():childAttrを使用して各接続にカスタム属性 を設定できます. childOption():childOptionメソッドは、各接続にTCP下位層に関連するプロパティを設定できます. ChannelOption.SO_KEEPALIVEはTCP下部心拍機構を開くかどうかを示し、trueは を開く. ChannelOptionその他のパラメータの詳細:https://www.cnblogs.com/googlemeoften/p/6082785.html
option():サービス側channelにいくつかの属性を設定します: まとめ このセクションでは、まずNettyのサービス側起動プロセスを学習しました.一言で言えば、ブートクラスを作成し、スレッドモデルを設定し、IOモデルを設定し、接続後のデータのビジネス処理ロジックを設定し、最後にポートをバインドしてサービスを開始します. その後,ブートクラスのbind法が非同期であることを学び,この非同期機構によりポート自動増分バインドを実現できた. 最後に、Nettyサービス側起動の追加パラメータについて議論した.主に、サービス側チャネルまたはクライアントチャネルに属性値を設定し、下位TCPパラメータを設定することを含む. ここで説明するのが簡単だと思ったら、深く勉強したいなら、ドアを転送します.https://coding.imooc.com/class/chapter/230.html#Anchor
質問: 従来のBIOモデルでは、新しい接続を受信するたびに新しいスレッドが作成され、Nettyを使用してIOモデルをNIOと指定すると、新しい接続を受信するたびに前のスレッドが多重化されてビジネスロジックが処理されます.疑問:Nettyを使用してIOモデルをBIOと指定すると、前のスレッドが多重化されますか、それとも新しいスレッドが作成されますか.
Netty実戦IMインスタント通信システム(四)サービス側起動プロセス
ゼロ、ディレクトリ
public class NettyServer {
public static void main(String[] args) {
NioEventLoopGroup bossGroup = new NioEventLoopGroup(1);
NioEventLoopGroup workerGroup = new NioEventLoopGroup();
ServerBootstrap serverBootstrap = new ServerBootstrap();
serverBootstrap
.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer() {
protected void initChannel(NioSocketChannel ch) {
}
});
serverBootstrap.bind(8000);
}
}
@Override
public void operationComplete(Future super Void> future) throws Exception {
if(future.isSuccess()) {
System.out.println(" :"+port);
}else {
System.out.println(" :"+ port);
bind(serverBootstrap, port+1);
}
}
}); }実行結果:(mysqlが3306ポートを占有しているため、3306バインドに失敗しました)バインドポートに失敗しました:3306正常バインドポート:3307
serverBootstrap.handler(new ChannelInitializer() {
@Override
protected void initChannel(NioServerSocketChannel ch) throws Exception {
System.out.println(" ...");
}
});
//
serverBootstrap.attr(AttributeKey.newInstance("serverName"), "NettyServer");
serverBootstrap.handler(new ChannelInitializer() {
@Override
protected void initChannel(NioServerSocketChannel channel) throws Exception {
//
Attribute
//
serverBootstrap.childAttr(AttributeKey.newInstance("clientName"), "NettyClient");
serverBootstrap.childHandler(new ChannelInitializer() {
@Override
protected void initChannel(NioSocketChannel childChannel) throws Exception {
//
childChannel.attr(AttributeKey.valueOf("clientName"));
}
});
serverBootstrap.childOption(ChannelOption.SO_KEEPALIVE, true);
serverBootstrap.childOption(ChannelOption.SO_BACKLOG, 10);
serverBootstrap.option(ChannelOption.SO_BACKLOG, 1024)
// , , , 。