Netty源码学习-ChannelHandler

一般来说,“有状态”的ChannelHandler不应该是“共享”的,“无状态”的ChannelHandler则可“共享”
例如ObjectEncoder是“共享”的, 但 ObjectDecoder 不是
因为每一次调用decode方法时,可能数据未接收完全(incomplete),
它与上一次decode时接收到的数据“累计”起来才有可能是完整的数据,是“有状态”的


public class SomePipelineFactory implements ChannelPipelineFactory {

//共享
private final StringEncoder stringEncoder = new StringEncoder(CharsetUtil.UTF_8);

//定义成static的也可以
//private static final StringEncoder stringEncoder = new StringEncoder(CharsetUtil.UTF_8);

@Override
public ChannelPipeline getPipeline() throws Exception {
ChannelPipeline pipeline = Channels.pipeline();
pipeline.addLast("stringEncoder", stringEncoder);

//不共享
pipeline.addLast("handler", new SomeHandler());
return pipeline;
}
}


因此,每一次ChannelPipelineFactory.getPipeline被调用时,
如果ChannelHandler是“不共享”的,则会新创建一个ChannelHandler的实例

ChannelPipelineFactory.getPipeline在以下方法中调用:



//NioServerSocketPipelineSink.Boss.registerAcceptedChannel
//SocketChannel(创建了pipeline):
private void registerAcceptedChannel(SocketChannel acceptedSocket, Thread currentThread) {

//调用PipelineFactory.getPipeline
ChannelPipeline pipeline =
channel.getConfig().getPipelineFactory().getPipeline();
NioWorker worker = nextWorker();
worker.register(new NioAcceptedSocketChannel(
channel.getFactory(), pipeline, channel,
NioServerSocketPipelineSink.this, acceptedSocket,
worker, currentThread), null);

}

//ServerBootstrap.bind
//ServerSocketChannel(创建了pipeline):
public Channel bind(final SocketAddress localAddress) {

ChannelPipeline bossPipeline = pipeline();
bossPipeline.addLast("binder", binder);
Channel channel = getFactory().newChannel(bossPipeline);
}



可见:
1.ServerSocketChannel与SocketChannel的pipeline实例不是同一个
每一个Channel都创建一个pipeline
2.ServerSocketChannel只有一个(如果同时绑定两个端口,例如同时提供80和443服务,则有两个)
与之关联的pipeline也只有一个,这pipeline里面的ChannelHandler只有“binder”(通常情况下)
3.SocketChannel会有多个:
socketChannelA--pipelineA(sharedHandler,newHandlerA0, newHandlerB0)
socketChannelB--pipelineB(sharedHandler,newHandlerA1, newHandlerB2)

socketChannelA和socketChannelB可能交由不同的workerThread来处理

因此如果ChannelHandler是“有状态”且“共享”,那就要注意线程同步的问题:


public class SharedHandler extends SimpleChannelUpstreamHandler {

private volatile int someState;
//...
}


但查看org.jboss.netty.example.proxy.HexDumpProxyInboundHandler:

public class HexDumpProxyInboundHandler extends SimpleChannelUpstreamHandler {
private volatile Channel outboundChannel;
//...
}

public ChannelPipeline getPipeline() throws Exception {
ChannelPipeline p = pipeline(); // Note the static import.
p.addLast("handler", new HexDumpProxyInboundHandler(cf, remoteHost, remotePort));
return p;
}


不是很理解,照理说,HexDumpProxyInboundHandler是“不共享”的,应该不存在
线程同步的问题,但为什么outboundChannel要定义成“volatile”呢?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值