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