エンコーダーのエンコード メソッドは同時に実行されますか? エンコード方法が異なるスレッドによって並行している可能性があることに気付きました。パイプラインは次のように定義します。
Channels.pipeline(
idleHandler,
new AmfDecoder<GameEvent>(GameEvent.class),
new AmfEncoder<GameEvent>(),
concurrencyHandler,
new WebHandler());
エンコーダー:
public class AmfEncoder<T extends IAmfEvent> extends OneToOneEncoder{
private final SerializationContext serializationContext = new SerializationContext();
private final Amf3Output amfout = new Amf3Output(serializationContext);
@Override
protected Object encode(ChannelHandlerContext arg0, Channel arg1,
Object arg2) throws Exception {
T e = (T)arg2;
ByteArrayOutputStream byteoutStreamSize = new ByteArrayOutputStream();
amfout.setOutputStream(byteoutStreamSize);
amfout.writeObject(e.getBody());
// byteoutStreamSize has small probability become empty at here, in debug mode I can sure e.getBody() has data
// I thought byteoutStreamSize might be empty by another thread call "amfout.flush()" or "amfout.reset()"
amfout.flush();
//...
amfout.reset();
}
}
Channel.write の呼び出しは、スレッドが netty のワーカー スレッドまたは Exeutionhandler 内のスレッドに属するだけではありません。自分で作成したスレッド プールがあり、Channel.write() を呼び出します。amfout と serializationContext の 2 つの変数を encode() 関数に移動してローカル変数にすると、問題はなくなります。
Doc によると、ChannelPipeline はスレッド セーフです。netty 3.4.5 で「追加」、「削除」が見つかりました...操作はロックされていますが、sendDownstream と sendUpstream にはロックがありません。したがって、ワーカー スレッド プールまたは ExecutionHandler スレッド プールに属さないスレッドがあり、これらすべてのスレッドが Channel.write() を呼び出すと、デコーダーとエンコーダーで同時発生の問題が発生します。