2

私は Netty 3.6.6.Final を使用しており、タイムアウト時に特定の応答を書き込む必要があるように、ハンドラーの書き込みタイムアウトを実装しようとしています。さらに、パイプラインで現在実行中 (または実行予定) の別の書き込み応答をキャンセルする必要があります。

これが私の現在のパイプラインです:

bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
      public ChannelPipeline getPipeline() throws Exception {
         return Channels.pipeline(LOGGER,
            new HttpServerCodec(), 
            new MyHttpContentDecoder(), 
            new IdleStateHandler(timer, 0, 1000, 0, TimeUnit.MILLISECONDS),
            handler.get());
         }
});

ハンドラーは、書き込みタイムアウトをチェックするメソッドを拡張IdleStateAwareChannelHandlerして実装します。channelIdle

if (e.getState() == IdleState.WRITER_IDLE) {
             e.getChannel().write(SOME_RESPONSE).addListener(new ChannelFutureListener() {          
         public void operationComplete(ChannelFuture future)  throws Exception {
            future.getChannel().close();                
        }});
} 

messageReceived問題は、タイムアウトが発生しない場合にメソッドで計画した書き込みをキャンセルする方法です。このような問題に対処するための Netty の慣例はありますか?

編集

経由でのキャンセルChannelFutureは機能しません。私が理解している限り、ほとんどの場合、書き込みはキャンセルされません。私のテスト中は常に、つまりcancel()常に false が返されました。ですから、この方法でそれを達成するのは本当に難しいと思います。

最後に、コードを最新リリースの 4.0.9.Final (はるかに優れた API) に更新しました。そして突然、書き込みタイムアウトの結果として応答を受け取りました。3.6.6.Final ではこの方法は機能しませんでした。

4.0.9.Final では、書き込みタイムアウトを処理するコードが少し異なりますが、タイムアウト時に常に 2 回目の書き込みが行われます (ctx.writeAndFlush以下にコメントすると、から書き込みが行われchannelRead0ます)。

public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
         if (evt instanceof IdleStateEvent) {
             IdleStateEvent e = (IdleStateEvent) evt;
             if (e.state() == IdleState.WRITER_IDLE) {

                   //the following condition was always false 
                   //(channelFuture is a state  variable of my handler for previous write)
                   if (channelFuture != null && channelFuture.isCancellable()) {
                       System.out.println("Cancel "+channelFuture.cancel(true));
                   }

                  ctx.writeAndFlush(SOME_RESPONSE);

             }
         }
}

タイムアウトが発生したときに最初の書き込み試行を「上書き」するのが正しい方法であるかどうかはわかりません。なぜそれが機能するのか、このシナリオに関して最新のリリースで何が変更されたのかを誰かが説明できれば幸いです。

4

2 に答える 2

1

メッセージがフラッシュされると、約束はキャンセルできないように設定されます。メッセージが 1 バイト書き出されると、デコーダーがストリームベースのトランスポートを処理できるように、メッセージを完全に書き込む必要があります。

于 2017-11-01T11:35:20.587 に答える
0

書き込み操作によって返された ChannelFuture をチャネリングすることができます。

于 2013-09-11T18:46:51.970 に答える