Netty入門学習(5)-タイムアウト処理


サービス側とクライアントは、次のコードを同時に追加します.
		Timer trigger=new HashedWheelTimer();
		final ChannelHandler timeOutHandler=new ReadTimeoutHandler(trigger,60);
//		final ChannelHandler idleStateHandler=new IdleStateHandler(trigger,60,5,0);
		
		//                  (Handler)
		bootstrap.setPipelineFactory(new ChannelPipelineFactory(){
			@Override
			public ChannelPipeline getPipeline() throws Exception {
				return Channels.pipeline(timeOutHandler,new LengthFieldPrepender(2),
						new LengthFieldBasedFrameDecoder(64*1024,0,2,0,2),
						new BusinessHandler());
			}			
		});

ReadTimeoutHandlerというHandlerが設定され、60 S間隔でデータが読み出されていない場合は、ReadTimeoutExceptionが放出され、デフォルトではデータ送信に影響しません.
NIOは非同期処理であるため,クライアントが応答してチャネルを閉じることができるが,サービス側はクライアントチャネルを閉じるタイミングを明確に知ることができないため,タイムアウト異常(後に心拍メカニズムなど)をキャプチャしてクライアントチャネルの閉じる問題を共同で処理するのが一般的である.
タイムアウトは、idleStateHandler、idleStateHandlerがリードタイムアウト、ライトタイムアウト、リードライトブレンドタイムアウトの処理ポリシーを提供し、ReadTimeOutHandlerとは異なり、idleStatehandlerはアイドルイベントを後方に渡すようにタイムアウトを処理し、idleStateHandlerを使用する場合は一般的にIdleStateAwareChannelHandlerを使用してステータスをキャプチャして処理する.
		Timer trigger=new HashedWheelTimer();
		final ChannelHandler timeOutHandler=new ReadTimeoutHandler(trigger,60);
		final ChannelHandler idleStateHandler=new IdleStateHandler(trigger,60,5,0);
        //                     (Handler)
        bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
            @Override
            public ChannelPipeline getPipeline() throws Exception {
                return Channels.pipeline(timeOutHandler,
                		idleStateHandler,
                		new SocketLinkState(),
                		new LengthFieldPrepender(2),
                		new LengthFieldBasedFrameDecoder(64*1024,0,2,0,2),
                		new RequestHandler());
            }
        });
	private static class SocketLinkState extends IdleStateAwareChannelHandler{
		  @Override
		  public void exceptionCaught(ChannelHandlerContext ctx,ExceptionEvent e) throws Exception{
		    // JavaUtil.callLevels();
		    Throwable throwed=e.getCause();
		    throwed.printStackTrace();
		    // throwed.printStackTrace(System.err);
		    if(throwed instanceof ReadTimeoutException){
		      ctx.getChannel().close();
		    }
		    else if(throwed instanceof IOException){
		      ctx.getChannel().close();
		    }
		    else{
		      super.exceptionCaught(ctx,e);
		    }
		  }
		  
		  @Override
		  public void channelIdle(//
		  ChannelHandlerContext ctx,//
		  IdleStateEvent e) throws Exception{

		    super.channelIdle(ctx,e);

		    Channel channel=e.getChannel();

		    switch(e.getState()){
		      case READER_IDLE: {//       
		        // e.getChannel().close();//       

		        // new RuntimeException().printStackTrace();
		        break;
		      }
		      case WRITER_IDLE: {//       
		        SocketHeartBeat.sendHeartBeat(channel);
		        break;
		      }
		    }
		  }
	}

ReadTimeOutHandlerの役割は、リードタイムに異常を後方に伝えることです
idleStatehandlerの役割は、リードタイムアウトまたはライトタイムアウトがアイドルイベントを後方に渡すことです.
SocketLinkStateは、ReadTimeOutHandlerとidleStatehandlerを処理し、ReadTimeOutHandlerが投げ出した異常をexceptionCaughtで処理し、channelを閉じ、channelIdleは関連イベントをキャプチャして処理し、この例ではReadTimeOutHandlerで処理していない.書き込みタイムアウトに対して,心拍数メカニズムを用いて起動した.
心拍数メカニズムは次節で議論する.