package com.ctriposs.baiji.rpc.server.netty; import com.ctriposs.baiji.rpc.server.HttpRequestRouter; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; import io.netty.channel.socket.SocketChannel; import io.netty.handler.codec.http.HttpObjectAggregator; import io.netty.handler.codec.http.HttpRequestDecoder; import io.netty.handler.codec.http.HttpResponseEncoder; import io.netty.handler.logging.LoggingHandler; import io.netty.util.concurrent.Future; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public abstract class HttpServer { private static final Logger _logger = LoggerFactory.getLogger(HttpServer.class); protected final HttpRequestRouter _requestRouter; private final ServerBootstrap _bootstrap; private int _maxContentLength = 1048576; private ChannelFuture _serverShutdownFuture; protected HttpServer(ServerBootstrap bootstrap, HttpRequestRouter requestRouter) { _bootstrap = bootstrap; _requestRouter = requestRouter; } public void start() throws Exception { startWithoutWaitingForShutdown(); _serverShutdownFuture.sync(); } public void startWithoutWaitingForShutdown() throws Exception { _bootstrap.childHandler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) throws Exception { ch.pipeline() .addLast("logger", new LoggingHandler()) .addLast("decoder", new HttpRequestDecoder()) .addLast("aggregator", new HttpObjectAggregator(_maxContentLength)) .addLast("encoder", new HttpResponseEncoder()); addRouterToPipeline(ch); } }); Channel channel = _bootstrap.bind().sync().channel(); _logger.info("Started netty http module at port: " + channel.localAddress()); Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() { @Override public void run() { try { stop(); } catch (InterruptedException e) { _logger.error("Error while shutting down.", e); } } })); _serverShutdownFuture = channel.closeFuture(); } public void stop() throws InterruptedException { _logger.info("Shutting down server."); Future<?> acceptorTermFuture = _bootstrap.group().shutdownGracefully(); Future<?> workerTermFuture = _bootstrap.childGroup().shutdownGracefully(); _logger.info("Waiting for acceptor threads to stop."); acceptorTermFuture.sync(); _logger.info("Waiting for worker threads to stop."); workerTermFuture.sync(); _logger.info("Shutdown complete."); } public int getMaxContentLength() { return _maxContentLength; } public void setMaxContentLength(int _maxContentLength) { if (_maxContentLength > 0) { this._maxContentLength = _maxContentLength; } } protected abstract void addRouterToPipeline(SocketChannel ch); }