Netty実戦IMインスタント通信システム(5)クライアント起動プロセス

6039 ワード

##
Netty実戦IMインスタント通信システム(5)クライアント起動プロセス
ゼロ、ディレクトリ
  • IMシステム概要
  • Netty概要
  • Netty環境構成
  • サービス側起動プロセス
  • 実戦:クライアントとサービス側の双方向通信
  • データ伝送キャリアByteBuf紹介
  • クライアントとサービス側通信プロトコルコーデック
  • クライアントログイン
  • を実現する.
  • クライアントとサービス側の送受信メッセージ
  • を実現する.
  • pipelineとchannelHandler
  • クライアントとサービス側pipeline
  • を構築する
  • 解包粘包理論と解決策
  • channelHandlerのライフサイクル
  • channelHandlerのホットスワップを使用してクライアント認証
  • を実現する.
  • クライアント対話の原理と実現
  • グループチャットの開始と通知
  • グループチャットのメンバー管理(加入と退出、メンバーリスト取得)
  • グループチャットメッセージの送受信およびNettyパフォーマンスの最適化
  • 心拍と空き検出
  • まとめ
  • 拡張
  • 五、クライアント起動プロセス
  • クライアント起動demo
     /**
      *        
      * */
     public class Test_05_        {
     	public static void main(String[] args) {
     		NioEventLoopGroup workerGroup = new NioEventLoopGroup();
     		
     		Bootstrap bootstrap = new Bootstrap();
     		bootstrap
     			//       
     			.group(workerGroup)
     			//   IO   
     			.channel(NioSocketChannel.class)
     			//         
     			.handler(new ChannelInitializer() {
     
     				@Override
     				protected void initChannel(NioSocketChannel ch) throws Exception {
     					
     				}
     			});
     		//     
     		bootstrap.connect("127.0.0.1" , 8000)
     			.addListener(future ->{
     				if(future.isSuccess()) {
     					System.out.println("    ");
     				}else {
     					System.out.println("    ");
     				}
     			});
     	}
     
     }
    
  • 上記のコードから分かるように、クライアントの起動ブートクラスはBootStrapであり、クライアントの起動とサービス側の接続を担当しているが、上記のセクションでは、サービス側の起動について説明する際に、このブートクラスはServer BootStrapであり、ブートクラスの作成が完了した後、クライアント起動プロセスについて説明する.
  • まず、サービス側の起動プロセスと同様に、接続されたデータの読み書き
  • を駆動する特定のスレッドモデルを指定する必要があります.
  • 次に、IOモデルをNioSocketChannelと指定し、IOモデルがNIO
  • であることを示した.
  • 次に、ブートクラスにhandlerを指定します.ここでは主に接続のビジネス処理ロジックを定義します.理解しないでください.後で
  • を詳しく説明します.
  • スレッドモデル、IOモデル、ビジネス処理ロジックを構成した後、connect()メソッドを呼び出して接続すると、connect()メソッドには2つのパラメータがあり、1つ目のパラメータはIPまたはドメイン名を記入することができ、2つ目のパラメータはポート番号を記入することができ、connect()メソッドはFutureを返すため、つまりこのメソッドは非同期である.addListener法により接続が成功するか否かを傍受し、接続状態
  • を印刷することができる.
  • ここまで1つのクライアントのdemoが完成しましたが、実はクライアントSocketプログラミングモデルに対応すれば、ここの3つの概念は非常に簡単に見えます
  • 失敗再接続
  • ネットワークが悪い場合、クライアントの最初の接続が失敗する可能性があります.このとき、再接続を試みる可能性があります.再接続された論理は、接続に失敗した論理ブロックに書かれています.
     //     
     bootstrap.connect("127.0.0.1" , 8000)
     	.addListener(future ->{
     		if(future.isSuccess()) {
     			System.out.println("    ");
     		}else {
     			System.out.println("    ");
     			
     			//TODO:       
     		}
     	});
    
  • 再接続時は依然として同じ論理を呼び出すので,接続したコードを抽出し,コード多重化を実現し,接続に失敗した場合に再帰的な方法で再接続
     public static void connect(Bootstrap bootstrap, String IP, int port) {
     	//     
     	bootstrap.connect(IP, port).addListener(future -> {
     		if (future.isSuccess()) {
     			System.out.println("    ");
     		} else {
     			System.out.println("    ,    ");
     			connect(bootstrap, IP, port);
     		}
     	});
     }
    
    を実現する.
  • 以上のコードは再接続メカニズムを実現しているが、通常は接続に失敗してもすぐに再接続するのではなく、1秒、2秒、4秒、8秒おきに2の乗で接続を確立し、一定回数に達した後に再接続を放棄する指数退避方式である.
  • 上記のコードから,接続に成功したか否かおよび残りの再試行回数を判断することによって,それぞれ異なる論理を実行することが分かる.
  • 接続が成功すると、接続成功メッセージ
  • が印刷される.
  • 接続が失敗したが、再試行回数が切れた場合は接続を放棄する
  • .
  • 接続が失敗したが、接続が切れていない場合は、次の再試行間隔を計算し、タイミング再接続
  • を実行する.
  • 上記のコードから、タイミングタスクはbootstrapを呼び出すことであることがわかります.config().group().ここでbootStrap.config()この方法はBootStrapConfigを返します.彼はBootStrapパラメータの構成を抽象化し、ootstrap.config().group()は,我々が最初に設定したスレッドモデルworkerGroupを返し,最後にschedule()メソッドを呼び出すことでタイミングタスクロジックを実現できる.



  • クライアントが他のメソッドを起動
  • attr():attr()メソッドは、クライアントchannel、すなわちNioSocketChannelにカスタム属性をバインドし、channelを通過することができる.attr()プロパティを取り出します.はっきり言ってNioSocketChannelにMapを1つ維持しただけだ
     	connect(bootstrap , "127.0.0.1" , 8000 , 5);
    
     	public static void connect(Bootstrap bootstrap, String IP, int port ,int maxRetry , int... retryIndex) {
     	//     
     	bootstrap.connect(IP, port).addListener(future -> {
     		//                                              
     		int[] finalRetryIndex ;
     		if (future.isSuccess()) {
     			System.out.println("    ");
     		} else if(maxRetry == 0){
     			System.out.println("        ,    ");
     		}else {
     			//          
     			if(retryIndex.length == 0) {
     				finalRetryIndex = new int[] {0};
     			}else {
     				finalRetryIndex = retryIndex;
     			}
     			//      
     			int delay = 1 << finalRetryIndex[0];
     			//     
     			System.out.println(new Date()+"    ,      :"+maxRetry+","+delay+"     "+(finalRetryIndex[0]+1)+"   ...");
     			bootstrap.config().group().schedule(()->{
     				connect(bootstrap, IP, port , maxRetry-1 , finalRetryIndex[0]+1);
     			}, delay, TimeUnit.SECONDS);
     		}
     	});
     }
     
    
         :
     Thu Dec 27 11:04:19 CST 2018    ,      :5,1     1   ...
     Thu Dec 27 11:04:21 CST 2018    ,      :4,2     2   ...
     Thu Dec 27 11:04:24 CST 2018    ,      :3,4     3   ...
     Thu Dec 27 11:04:29 CST 2018    ,      :2,8     4   ...
     Thu Dec 27 11:04:38 CST 2018    ,      :1,16     5   ...
             ,    
    
  • option():option()は、接続にTCP下位層の関連属性を設定することができる:(ChannelOption関連パラメータは、前節「サービス側起動プロセス」に接続アドレスがあることを詳細に説明する)
     //    
     bootstrap.attr(AttributeKey.newInstance("clientName"), "NettyClient");
     //    
     bootstrap.handler(new ChannelInitializer() {
    
     	@Override
     	protected void initChannel(NioSocketChannel ch) throws Exception {
     		//     
     		Attribute attr = ch.attr(AttributeKey.valueOf("clientName"));
     		System.out.println("     :"+attr.get());
     	}
     });
    
  • まとめ:
  • このセクションでは、Nettyクライアントが起動するプロセスを学習しました.一言で言えば、ブートクラスを作成し、スレッド、IOモデル、ビジネスロジックを指定し、特定のIP:portクライアントに接続すると
  • が起動します.
  • その後connect()法の非同期化を学び,非同期コールバック機構により指数的退避再接続機構を実現できた.
  • 最後に、クライアントチャネルにカスタム属性をバインドすることを含む限り、TCP下位パラメータを設定するNettyクライアント起動の追加パラメータについて議論した.

  • 質問:
  • クライアントチャネルによって設定されたattrは、サービス側によって受信され、必要なパラメータ伝達されるかどうか.
  • 回答:クライアントチャネルはサービス側に受信されます.