package org.act.tstream.message.netty; import java.net.InetSocketAddress; import java.util.List; import java.util.Map; import java.util.concurrent.Executors; import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import org.jboss.netty.bootstrap.ServerBootstrap; import org.jboss.netty.channel.Channel; import org.jboss.netty.channel.ChannelFactory; import org.jboss.netty.channel.group.ChannelGroup; import org.jboss.netty.channel.group.DefaultChannelGroup; import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.act.tstream.utils.JStormUtils; import backtype.storm.Config; import backtype.storm.messaging.IConnection; import backtype.storm.messaging.TaskMessage; import backtype.storm.utils.DisruptorQueue; import backtype.storm.utils.Utils; class NettyServer implements IConnection { private static final Logger LOG = LoggerFactory .getLogger(NettyServer.class); @SuppressWarnings("rawtypes") Map storm_conf; int port; DisruptorQueue recvQueue; // private LinkedBlockingQueue message_queue; volatile ChannelGroup allChannels = new DefaultChannelGroup("jstorm-server"); final ChannelFactory factory; final ServerBootstrap bootstrap; // ayncBatch is only one solution, so directly set it as true private final boolean isSyncMode; @SuppressWarnings("rawtypes") NettyServer(Map storm_conf, int port, boolean isSyncMode) { this.storm_conf = storm_conf; this.port = port; this.isSyncMode = isSyncMode; // Configure the server. int buffer_size = Utils.getInt(storm_conf .get(Config.STORM_MESSAGING_NETTY_BUFFER_SIZE)); int maxWorkers = Utils.getInt(storm_conf .get(Config.STORM_MESSAGING_NETTY_SERVER_WORKER_THREADS)); //asyncBatch = ConfigExtension.isNettyTransferAsyncBatch(storm_conf); ThreadFactory bossFactory = new NettyRenameThreadFactory("server" + "-boss"); ThreadFactory workerFactory = new NettyRenameThreadFactory("server" + "-worker"); if (maxWorkers > 0) { factory = new NioServerSocketChannelFactory( Executors.newCachedThreadPool(bossFactory), Executors.newCachedThreadPool(workerFactory), maxWorkers); } else { factory = new NioServerSocketChannelFactory( Executors.newCachedThreadPool(bossFactory), Executors.newCachedThreadPool(workerFactory)); } bootstrap = new ServerBootstrap(factory); bootstrap.setOption("reuserAddress", true); bootstrap.setOption("child.tcpNoDelay", true); bootstrap.setOption("child.receiveBufferSize", buffer_size); bootstrap.setOption("child.keepAlive", true); // Set up the pipeline factory. bootstrap.setPipelineFactory(new StormServerPipelineFactory(this)); // Bind and start to accept incoming connections. Channel channel = bootstrap.bind(new InetSocketAddress(port)); allChannels.add(channel); LOG.info("Successfull bind {}, buffer_size:{}, maxWorkers:{}", port, buffer_size, maxWorkers); } @Override public void registerQueue(DisruptorQueue recvQueu) { this.recvQueue = recvQueu; } /** * enqueue a received message * * @param message * @throws InterruptedException */ public void enqueue(TaskMessage message) { recvQueue.publish(message); } /** * fetch a message from message queue synchronously (flags != 1) or * asynchronously (flags==1) */ public TaskMessage recv(int flags) { try { if ((flags & 0x01) == 0x01) { return (TaskMessage) recvQueue.poll(); // non-blocking } else { return (TaskMessage) recvQueue.take(); } } catch (Exception e) { LOG.warn("Occur unexception ", e); return null; } } /** * register a newly created channel * * @param channel */ protected void addChannel(Channel channel) { allChannels.add(channel); } /** * close a channel * * @param channel */ protected void closeChannel(Channel channel) { channel.close().awaitUninterruptibly(); allChannels.remove(channel); } /** * close all channels, and release resources */ public synchronized void close() { LOG.info("Begin to shutdown NettyServer"); if (allChannels != null) { new Thread(new Runnable() { @Override public void run() { try { // await(5, TimeUnit.SECONDS) // sometimes allChannels.close() will block the exit thread allChannels.close().await(1, TimeUnit.SECONDS); LOG.info("Successfully close all channel"); factory.releaseExternalResources(); }catch(Exception e) { } allChannels = null; } }).start(); JStormUtils.sleepMs(1 * 1000); } LOG.info("Successfully shutdown NettyServer"); } @Override public void send(List<TaskMessage> messages) { throw new UnsupportedOperationException( "Server connection should not send any messages"); } @Override public void send(TaskMessage message) { throw new UnsupportedOperationException( "Server connection should not send any messages"); } @Override public boolean isClosed() { // TODO Auto-generated method stub return false; } public boolean isSyncMode() { return isSyncMode; } }