关于Netty的介绍和分析请看http://www.infoq.com/cn/articles/netty-high-performance
当时用Netty的时候是为了解决Socket长连接,以及多并发。真正上手做的时候找到了一个Demo,感觉这个Demo的扩展性还挺强的,于是以这个Demo为基础,开始搭建,Demo地址https://www.bbsmax.com/A/MyJxypmV5n/
package com.onecat12.activity;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.serialization.ClassResolvers;
import io.netty.handler.codec.serialization.ObjectDecoder;
import io.netty.handler.codec.serialization.ObjectEncoder;
import io.netty.handler.timeout.IdleStateHandler;
import io.netty.util.concurrent.DefaultEventExecutorGroup;
import io.netty.util.concurrent.EventExecutorGroup;
import java.util.concurrent.TimeUnit;
/**
* 对SocketChannel引用ServerBootstrap
*/
public class NettyServerBootstrap {
private int port;
private SocketChannel socketChannel;
public NettyServerBootstrap(int port) throws InterruptedException {
this.port = port;
bind();
}
private void bind() throws InterruptedException {
EventLoopGroup boss = new NioEventLoopGroup(1);
EventLoopGroup worker = new NioEventLoopGroup(Runtime.getRuntime().availableProcessors());
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(boss, worker);
bootstrap.channel(NioServerSocketChannel.class);
/*SO_BACKLOG,Socket参数,连接数,服务端接受连接的队列长度,
如果队列已满,客户端连接将被拒绝。*/
bootstrap.option(ChannelOption.SO_BACKLOG, 128);
/*TCP_NODELAYTCP参数,立即发送数据,默认值为Ture
(Netty默认为True而操作系统默认为False)。
该值设置Nagle算法的启用,改算法将小的碎片数据连接成更大的报文来最小化所发送的报文的数量,
如果需要发送一些较小的报文,则需要禁用该算法。Netty默认禁用该算法,从而最小化报文传输延时。
*/
bootstrap.option(ChannelOption.TCP_NODELAY, true);
//保持长连接状态
bootstrap.childOption(ChannelOption.SO_KEEPALIVE, true);
bootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
// 创建一个线程组来处理耗时的业务逻辑,线程组的个数是获取到的cpu核心数的4倍
private EventExecutorGroup group = new DefaultEventExecutorGroup(Runtime.getRuntime().availableProcessors() * 4);
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
ChannelPipeline p = socketChannel.pipeline();
p.addLast(new ObjectEncoder());
/*添加对象解码器,负责对序列化POJO对象进行解码,
设置对象序列化最大长度为1M,防止内存溢出
设置线程安全的WeakReferenceMap对类加载器进行缓存,
支持多线程并发访问,防止内存溢出
禁止缓存类加载器*/
//添加对客户端读写空闲的监听
p.addLast(new IdleStateHandler(10, 10, 10, TimeUnit.SECONDS));
p.addLast(new ObjectDecoder
(1024 * 1024, ClassResolvers.weakCachingConcurrentResolver(null)));
p.addLast(new NettyServerHandler());
// 将DataProcessHandler中的业务逻辑放到EventExecutorGroup线程组中执行
p.addLast(group, new NettyDataHandler());
}
});
//开启异步操作
ChannelFuture f = bootstrap.bind(port).sync();
if (f.isSuccess()) {
System.out.println("activity start---------------");
}
}
public static void main(String[] args) throws InterruptedException {
//设置启动端口
NettyServerBootstrap bootstrap = new NettyServerBootstrap(5000);
}
}
刚接触这个Demo的时候,大部分程序语句看不懂,于是一条一条上网查,写注释,全查完后对Netty有了大概的了解。
我在Demo基础上添加了一个NettyDataHandler,用来处理耗时业务。
NettyServerHandler用来接收和发送来自客户端的数据,当接收到数据或请求后,交给NettyDataHandler来处理。
当然,NettyDataHandler要继承Netty的一个处理类,既:
public class NettyDataHandler extends ChannelInboundHandlerAdapter