Consider the following server bootstrapping code:
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();
}
And 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());
}
}
Now- MyHandshakeHandler() listens for messages, and those messages need to interact with the database.
Before we go further- is the above code the correct way to do this? (namely- the way I used EventExecutorGroup for this blocking type of handler)
Assuming for now that it is correct, here’s my question- while it’s true that MyHandshakeHandler() needs to interact with the database, this is only during the initial negotiation with the client and upon channel close. The rest of the time- namely after handshake is completed and before the channel is closed- all that is needed is to bounce ping/pong/heartbeat/keepalive type messages which do not require the database. Therefore- should that A) be a separate handler (let’s call it “MyPingHandler”) which is added to the pipeline before MyHandshakeHandler or B) should I just add that logic to MyHandshakeHandler?
If A) how do I stop the message from propagating further so that MyHandshakeHandler is not needlessly called, unless it is specifically the channel close event (i.e. channelInactive())? As a bonus point- it would be nice if MyPingHandler were only added to the pipeline after handshake is complete so that it is not needlessly called as well.
If B) I don’t understand the purpose of EventExecutorGroup in this case. These connections are the only type which this server will power…. so it seems strange to me to set a dedicated group of threads which will be used for every single handler rather than just use the default. So if B is the way to go- for this specific case- should I just add the handler to the pipeline normally without EventExecutorGroup (if not- why not)?
The answer is (A).
To propagate an event to its next handler, you usually call a
ctx.fireXXX()method. If you don’t call any of them, the event will not be propagated. So, in your case, you can just swallow event in most case after handshake is complete by NOT callingctx.fireXXX()methods.Also, the pipeline can be dynamically configures. You can add or remove a handler to/from a pipeline at anytime. Therefore, you can either remove the handshake handler after handshake is over or add the ping handler after handshake is over (or perhaps both).