package ddth.dasp.servlet.netty.api; import java.net.InetSocketAddress; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import org.apache.commons.lang3.StringUtils; import org.jboss.netty.bootstrap.ServerBootstrap; import org.jboss.netty.channel.group.ChannelGroup; import org.jboss.netty.channel.group.DefaultChannelGroup; import org.jboss.netty.channel.socket.nio.NioServerBossPool; import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory; import org.jboss.netty.channel.socket.nio.NioWorkerPool; import org.jboss.netty.util.HashedWheelTimer; import org.jboss.netty.util.ThreadNameDeterminer; import org.jboss.netty.util.Timer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import ddth.dasp.servlet.utils.NetUtils; public class DaspNettyJsonApiServer { public static ChannelGroup ALL_CHANNELS = new DefaultChannelGroup( DaspNettyJsonApiServer.class.getCanonicalName()); private final Logger LOGGER = LoggerFactory.getLogger(DaspNettyJsonApiServer.class); private long readTimeoutMillisecs = 5000, writeTimeoutMillisecs = 10000; private int maxRequestSize = 64 * 1024; private int numWorkers = 32; private String portStr = "8082"; private Timer timer; private ServerBootstrap nettyServer; public DaspNettyJsonApiServer() { } public long getReadTimeoutMillisecs() { return readTimeoutMillisecs; } public DaspNettyJsonApiServer setReadTimeoutMillisecs(long readTimeoutMillisecs) { this.readTimeoutMillisecs = readTimeoutMillisecs; return this; } public long getWriteTimeoutMillisecs() { return writeTimeoutMillisecs; } public DaspNettyJsonApiServer setWriteTimeoutMillisecs(long writeTimeoutMillisecs) { this.writeTimeoutMillisecs = writeTimeoutMillisecs; return this; } public int getMaxRequestSize() { return maxRequestSize; } public DaspNettyJsonApiServer setMaxRequestSize(int maxRequestSize) { this.maxRequestSize = maxRequestSize; return this; } public int getNumWorkers() { return numWorkers; } public DaspNettyJsonApiServer setNumWorkers(int numWorkers) { this.numWorkers = numWorkers; return this; } public String getPort() { return portStr; } public DaspNettyJsonApiServer setPort(String portStr) { this.portStr = portStr; return this; } public void start() { Integer port = 8082; if (!StringUtils.isBlank(portStr)) { // find free port String[] tokens = portStr.split("[\\s,]+"); int[] ports = new int[tokens.length]; for (int i = 0; i < tokens.length; i++) { ports[i] = Integer.parseInt(tokens[i]); } port = NetUtils.getFreePort(ports); } timer = new HashedWheelTimer(Executors.defaultThreadFactory(), 10, TimeUnit.MILLISECONDS, 8192); NioServerBossPool serverBossPool = new NioServerBossPool(Executors.newCachedThreadPool(), 1, new ThreadNameDeterminer() { private AtomicInteger COUNTER = new AtomicInteger(1); @Override public String determineThreadName(String currentThreadName, String proposedThreadName) throws Exception { int counter = COUNTER.getAndIncrement(); return "DNJAPI server boss #" + counter; } }); NioWorkerPool workerPool = new NioWorkerPool(Executors.newCachedThreadPool(), numWorkers, new ThreadNameDeterminer() { private AtomicInteger COUNTER = new AtomicInteger(1); @Override public String determineThreadName(String currentThreadName, String proposedThreadName) throws Exception { int counter = COUNTER.getAndIncrement(); return "DNJAPI worker #" + counter; } }); nettyServer = new ServerBootstrap(new NioServerSocketChannelFactory(serverBossPool, workerPool)); nettyServer.setPipelineFactory(new JsonApiPipelineFactory(timer, readTimeoutMillisecs, writeTimeoutMillisecs, maxRequestSize)); nettyServer.setOption("child.tcpNoDelay", true); nettyServer.setOption("child.keepAlive", false); nettyServer.bind(new InetSocketAddress(port)); if (LOGGER.isInfoEnabled()) { LOGGER.info("DASP Netty Json API interface is listening on port: " + port + " / Read timeout: " + readTimeoutMillisecs + " / Write timeout: " + writeTimeoutMillisecs + " / Num workers: " + numWorkers); } } public void destroy() { try { if (nettyServer != null) { nettyServer.releaseExternalResources(); } } catch (Exception e) { LOGGER.warn(e.getMessage(), e); } try { if (timer != null) { timer.stop(); } } catch (Exception e) { LOGGER.warn(e.getMessage(), e); } try { ALL_CHANNELS.close(); } catch (Exception e) { LOGGER.warn(e.getMessage(), e); } } }