【发布时间】:2012-10-19 16:27:21
【问题描述】:
考虑以下服务器引导代码:
ChannelFuture f;
ServerBootstrap b = new ServerBootstrap();
try {
b.group(new NioEventLoopGroup(), new NioEventLoopGroup())
.channel(NioServerSocketChannel.class)
.localAddress(1234)
.childOption(ChannelOption.TCP_NODELAY, true)
.childHandler(new MyChannelInitializer(new DefaultEventExecutorGroup(10)));
f = b.bind().sync();
f.channel().closeFuture().sync();
}
还有MyChannelInitializer.java:
public class MyChannelInitializer extends ChannelInitializer<SocketChannel> {
private EventExecutorGroup executorGroup;
public MyChannelInitializer(EventExecutorGroup _executorGroup) {
executorGroup = _executorGroup;
}
@Override
public void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast("framer", new DelimiterBasedFrameDecoder(8192, Delimiters.nulDelimiter()));
pipeline.addLast("decoder", new StringDecoder(CharsetUtil.UTF_8));
pipeline.addLast("encoder", new StringEncoder(CharsetUtil.UTF_8));
// and then business logic.
pipeline.addLast(this.executorGroup, "handler", new MyHandshakeHandler());
}
}
现在- MyHandshakeHandler() 监听消息,这些消息需要与数据库交互。
在我们继续之前,上面的代码是正确的方法吗? (即,我使用 EventExecutorGroup 处理这种阻塞类型的处理程序的方式)
现在假设它是正确的,这是我的问题 - 虽然 MyHandshakeHandler() 确实需要与数据库交互,但这仅在与客户的初始协商期间和通道关闭时.其余时间——即在握手完成之后和通道关闭之前——所需要的只是反弹不需要数据库的 ping/pong/heartbeat/keepalive 类型的消息。因此,A)应该是一个单独的处理程序(我们称之为“MyPingHandler”),它在 MyHandshakeHandler 或 B)之前添加到管道中,我应该将该逻辑添加到 MyHandshakeHandler 吗?
如果 A)我如何阻止消息进一步传播,以免不必要地调用 MyHandshakeHandler,除非它专门是通道关闭事件(即 channelInactive())?作为奖励点 - 如果 MyPingHandler 仅在握手完成后添加到管道中会很好,这样它就不会被不必要地调用。
如果 B) 在这种情况下,我不明白 EventExecutorGroup 的目的。这些连接是该服务器将支持的唯一类型....所以我觉得设置一组专用的线程组将用于每个单独的处理程序而不是只使用默认值似乎很奇怪。因此,如果 B 是解决这个特定案例的方法——我是否应该在没有 EventExecutorGroup 的情况下正常地将处理程序添加到管道中(如果不是——为什么不呢)?
【问题讨论】: