携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第6天,点击查看活动详情
前言
之前讲过netty的基本介绍,今天带大家熟悉一下netty的具体使用方法。年初公司就要求我们做一个TCP服务给设备使用,主要目的是与设备建立通讯和设备长链接,这长链接还踩了个坑,我们公司使用的云服务器厂商是阿里云。由于阿里云的服务器长链接建立时会出现4分钟后管道没有建立链接,那么就会自动断开链接,导致客户端tcp无法收到信息。巨坑!请大家使用长链接时注意!
创建run线程
先初步与大家讲一下netty,netty的处理方式与往常java开发不一样,主要是netty采用了管道的形式来开发,就大家可以想象成流水线,从初始端到结束端是一套完整的流水线,每一个hanlder是在流水线上的工人。
public void run(){
bossGroup = new NioEventLoopGroup(config.getBossThread());
workerGroup = new NioEventLoopGroup(config.getWorkerThread());
try {
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.option(ChannelOption.SO_BACKLOG, 1024)
.option(NioChannelOption.SO_REUSEADDR, true)
.childOption(ChannelOption.SO_KEEPALIVE, true)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
//包解析 入站
ch.pipeline().addLast(new LengthFieldBasedFrameDecoder(2048, 13, 2, 5, 0),
new OtaPackageCheckDecoder());
//编码 出站
ch.pipeline().addLast(new OtaEncoder());
//解码 入站
ch.pipeline().addLast(new ConnectionServerHandler(config.getDefaultTimeout(), config.getContainer()),
new OtaDeviceDataHandler(config.getContainer()));
//异常处理
ch.pipeline().addLast(new ExceptionHandler(config.getContainer()));
}
});
ChannelFuture f = b.bind(config.getPort()).sync();
f.channel().closeFuture().sync();
}catch (Exception e){
log.warn(">>>>>>>>OtaTcpServer出现异常:{}", e.getMessage());
} finally {
stop();
}
}
这里我们可以看到上面的代码中这两个线程 bossGroup = new NioEventLoopGroup(config.getBossThread()); workerGroup = new NioEventLoopGroup(config.getWorkerThread());
这两个是工人组 和boss组,boss组主要任务是接受请求他不做具体的处理的,他会把任务分配给下面的工人组线程去执行,所以一般配置都是 boss组 8个,worker组16个形成1:2的线程,这里注意如果boss组多分配形成 2:1那么效率会减慢,就好比都是老板谁去干活?如果工人太多 形成 2:1 那只有一个老板会导致多个工人闲置下来,浪费空间效率也不好,所以一般推荐boss:worker 2:1.。