使用ChannelGroup优雅的关闭netty

    在netty中,接受连接请求和对请求进行业务处理分别有两个线程执行器bossExecutor 和 workerExecutor,除了关闭这两个外还需要关闭channel。

    通常正常的关闭netty需要三步:

unbind netty创建的所有channel。//channel.unbind()
close netty创建的所有channel。//channel.close()
shutdown netty的线程执行器。//factory.releaseExternalResources()

    对于netty生成的channel,可以使用ChannelGroup管理,关于channelGroup,可以参考其代码注释:

    A thread-safe Set that contains open Channels and provides various bulk operations on them. Using ChannelGroup, you can categorize Channels into a meaningful group (e.g. on a per-service or per-state basis.) A closed Channel is automatically removed from the collection, so that you don't need to worry about the life cycle of the added Channel. A Channel can belong to more than one ChannelGroup.

Broadcast a message to multiple Channels

    If you need to broadcast a message to more than one Channel, you can add the Channels associated with the recipients and call ChannelGroup.write(Object):

 ChannelGroup recipients = new DefaultChannelGroup();
 recipients.add(channelA);
 recipients.add(channelB);
 //.. 
 recipients.write(ChannelBuffers.copiedBuffer(
         "Service will shut down for maintenance in 5 minutes.",
         CharsetUtil.UTF_8));

Simplify shutdown process with ChannelGroup

    If both ServerChannels and non-ServerChannels exist in the same ChannelGroup, any requested I/O operations on the group are performed for the ServerChannels first and then for the others.

This rule is very useful when you shut down a server in one shot:

 ChannelGroup allChannels = new DefaultChannelGroup();
 public static void main(String[] args) throws Exception {     
     ServerBootstrap b = new ServerBootstrap(..);
     //...
     // Start the server
     b.getPipeline().addLast("handler", new MyHandler());     
     Channel serverChannel = b.bind(..);     
     allChannels.add(serverChannel);
     
     //... Wait until the shutdown signal reception ...
     // Close the serverChannel and then all accepted connections.     
     allChannels.close().awaitUninterruptibly();
     b.releaseExternalResources();
 }
 public class MyHandler extends SimpleChannelUpstreamHandler {     
     @Override
     public void channelOpen(ChannelHandlerContext ctx, ChannelStateEvent e) {
         // Add all open channels to the global group so that they are
         // closed on shutdown.         
         allChannels.add(e.getChannel());
     }
 }