Netty實現簡單的Http伺服器
阿新 • • 發佈:2018-12-31
之前在upload伺服器的時候,由於tomcat效能瓶頸的的問題,qps無法達到要求,瞭解到Netty.io的高效能,覺得自己寫一個Http接受資料的伺服器來處理客戶段上報的資料,比較簡單,直接貼程式碼了:
package com.bonree.browser.httpServer.server;
import com.bonree.browser.httpServer.handler.HttpServerHandler;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.*;
import io.netty.channel.epoll.EpollEventLoopGroup;
import io.netty.channel.epoll.EpollServerSocketChannel;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpContentCompressor;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpRequestDecoder;
import io.netty.handler.codec.http.HttpResponseEncoder;
import io.netty.util.concurrent.DefaultThreadFactory;
import org.apache.log4j.Logger;
import java.nio.channels.spi.SelectorProvider;
import java.util.concurrent.ThreadFactory;
/*******************************************************************************
* 版權資訊:博睿巨集遠科技發展有限公司
* Copyright: Copyright (c) 2007博睿巨集遠科技發展有限公司,Inc.All Rights Reserved.
* @author <a href=mailto:[email protected]>徐昌</a>
* Description: 服務端程式
******************************************************************************/
public class NettyServer {
private Logger log = Logger.getLogger(NettyServer.class);
private int port;
private int bossGroupThreadNum = 1;
private int workGroupThreadNum = 0;
private boolean userEPoll = true;
private EventLoopGroup bossGroup = null;
private EventLoopGroup workerGroup = null;
ServerBootstrap server = null;
public NettyServer(int port, int bossGroupThreadNum, int workGroupThreadNum, boolean userEPoll) {
this.port = port;
this.bossGroupThreadNum = bossGroupThreadNum;
this.workGroupThreadNum = workGroupThreadNum;
this.userEPoll = userEPoll;
}
public NettyServer(int port) {
this.port = port;
}
private void init() {
if (userEPoll) {
createEPollServer();
} else {
createNIOServer();
}
}
public void start() {
init();
//server啟動
try {
server = new ServerBootstrap();
server.group(bossGroup, workerGroup)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
// request解密
pipeline.addLast(new HttpRequestDecoder());
//將多個http物件聚合成單一的FullHttpRequest
pipeline.addLast(new HttpObjectAggregator(1024 * 1024));
// response 加密
pipeline.addLast(new HttpResponseEncoder());
//資料壓縮
pipeline.addLast(new HttpContentCompressor());
// 呼叫我們的方法
pipeline.addLast(new HttpServerHandler());
}
});
initChannelOption();
ChannelFuture future = server.bind(port).sync();
log.info("HTTP服務啟動,網址為 http://localhost:" + port);
future.channel().closeFuture().sync();
} catch (Exception e) {
log.error("Server start fail!", e);
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
private void initChannelOption() {
if (userEPoll) {
server.channel(EpollServerSocketChannel.class)
.option(ChannelOption.TCP_NODELAY, false)
.option(ChannelOption.SO_BACKLOG, 511)
.option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
.childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT);
} else {
server.channel(NioServerSocketChannel.class)
.option(ChannelOption.TCP_NODELAY, false)
.option(ChannelOption.SO_BACKLOG, 511)
.option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
.childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT);
}
}
private void createEPollServer() {
if (bossGroup == null) {
EpollEventLoopGroup epollEventLoopGroup = new EpollEventLoopGroup(getBossGoupThreadNum(), getBossGroupThreadFactory());
epollEventLoopGroup.setIoRatio(100);
bossGroup = epollEventLoopGroup;
}
if (workerGroup == null) {
EpollEventLoopGroup epollEventLoopGroup = new EpollEventLoopGroup(getWorkGroupThreadNum(), getWorkGroupThreadFactory());
epollEventLoopGroup.setIoRatio(80);
workerGroup = epollEventLoopGroup;
}
}
private void createNIOServer() {
if (bossGroup == null) {
NioEventLoopGroup nioEventLoopGroup = new NioEventLoopGroup(getBossGoupThreadNum(), getBossGroupThreadFactory());
nioEventLoopGroup.setIoRatio(100);
bossGroup = nioEventLoopGroup;
}
if (workerGroup == null) {
NioEventLoopGroup nioEventLoopGroup = new NioEventLoopGroup(getWorkGroupThreadNum(), getWorkGroupThreadFactory(), getSelectorProvider());
nioEventLoopGroup.setIoRatio(80);
workerGroup = nioEventLoopGroup;
}
}
private SelectorProvider getSelectorProvider() {
return SelectorProvider.provider();
}
private int getBossGoupThreadNum() {
//做成可以配置的
return bossGroupThreadNum;
}
private int getWorkGroupThreadNum() {
//做成可以配置的
return workGroupThreadNum;
}
private ThreadFactory getBossGroupThreadFactory() {
return new DefaultThreadFactory("T_BOSS_GROUP");
}
private ThreadFactory getWorkGroupThreadFactory() {
return new DefaultThreadFactory("T_BOSS_GROUP");
}
}