Netty的版本是:
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.6.Final</version>
</dependency>
服务端启动代码:
public class Server {
public static void main(String[] args) throws Exception {
// 配置服务端的 NIO线程组
// boss线程组用于网络事件的监听
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
// worker线程组用于SocketChannel的网络读写
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
// NIO服务端的辅助启动类,目的是降低服务端开发的复杂度
ServerBootstrap b = new ServerBootstrap();
// 配置两大线程组
b.group(bossGroup, workerGroup)
// 配置服务端channel
.channel(NioServerSocketChannel.class)
// 配置TCP基本属性
.childOption(ChannelOption.TCP_NODELAY, true)
// 客户端创建连接时绑定基本属性
.childAttr(AttributeKey.newInstance("childAttr"), "childAttrValue")
// 配置服务端启动过程逻辑处理器
.handler(new ServerHandler())
// 配置业务处理链 handler pipeline
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) {
// 配置业务处理handler,对数据流进行读写等处理
// ch.pipeline().addLast()
}
});
// 前面都是一些属性配置的逻辑,真正的服务端启动在此处开始
// 绑定端口,正式启动server端服务
ChannelFuture f = b.bind(8888).sync();
// 同步等待,直至服务端监听端口关闭
f.channel().closeFuture().sync();
} finally {
// 优雅退出,释放线程池资源
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
}
ServerHandler
public class ServerHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelActive(ChannelHandlerContext ctx) {
System.out.println("channelActive");
}
@Override
public void channelRegistered(ChannelHandlerContext ctx) {
System.out.println("channelRegistered");
}
@Override
public void handlerAdded(ChannelHandlerContext ctx) {
System.out.println("handlerAdded");
}
@Override
public void channelRead(final ChannelHandlerContext ctx, Object msg) throws Exception {
super.channelRead(ctx, msg);
new Thread(new Runnable() {
@Override
public void run() {
// 耗时的操作
String result = loadFromDB();
ctx.channel().writeAndFlush(result);
ctx.executor().schedule(new Runnable() {
@Override
public void run() {
// ...
}
}, 1, TimeUnit.SECONDS);
}
}).start();
}
private String loadFromDB() {
return "hello world!";
}
}
通过代码中的注释可以了解到,服务启动是通过ServerBootstrap类的bind方法触发的,而前面的逻辑都是在组装服务启动所需要的配置,如线程组、TCP参数、服务启动handler,业务处理handler pipeline等。后面会具体分析服务启动的逻辑。