- 概述
- Netty是什么
- Netty是一个异步(非异步IO)的、基于事件驱动的网络应用框架,用于快速开发可维护、高性能的网络服务器和客户端
- Netty的优势
- Netty vs NIO,工作量大,bug多
- 需要自己构建协议
- 解决TCP传输问题,如粘包、半包
- epoll空轮询导致CPU100%
- 对API进行增强,使之更易用,如FastThreadLocal⇒ThreadLocal,ByteBuf⇒ByteBuffer
- Netty vs 其他网络框架
- Mina由apache维护,将来3.x版本可能会有较大重构,破坏API向下兼容性,Netty的开发迭代更迅速。
- Netty vs NIO,工作量大,bug多
- Netty是什么
- 实现Netty简单通信
- 服务器
public static void main(String[] args) {
// 1、服务器端启动器,负责组装netty组件,启动服务器
new ServerBootstrap()
// 2、group 组, BossEventLoop,WorkerEventLoop(selector,thread)事件选择器及对应的线程
.group(new NioEventLoopGroup())
// 3、选择服务器的ServerSocketChannel实现
.channel(NioServerSocketChannel.class)
// 4、boss负责处理连接,worker(child)负责处理读写, 决定了worker(child)能执行哪些操作(handler)
.childHandler(
// 5、代表和客户端进行客户端进行数据读写的通道 Initializer初始化,负责添加别的handler
new ChannelInitializer<NioSocketChannel>() {
@Override //初始化操作,当客户端连接建立时会被调用
protected void initChannel(NioSocketChannel ch) throws Exception {
// 6、添加具体的handler
ch.pipeline().addLast(new StringDecoder()); //将ByteBuf 转换为字符串
ch.pipeline().addLast(new ChannelInboundHandlerAdapter(){ //自定义 handler
@Override //读事件
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
// 打印上一步转换好的字符串
System.out.println(msg);
super.channelRead(ctx, msg);
}
});
}
// 7、绑定监听端口
}).bind(8080);
}
- 客户端
public static void main(String[] args) throws InterruptedException {
// 1、客户端启动类
new Bootstrap()
// 2、添加EventLoop
.group(new NioEventLoopGroup())
// 3、选择客户端 channel 实现
.channel(NioSocketChannel.class)
// 4、添加处理器
.handler(new ChannelInitializer<NioSocketChannel>() {
@Override //在连接建立后被调用
protected void initChannel(NioSocketChannel ch) throws Exception {
ch.pipeline().addLast(new StringEncoder()); //把字符串编码成ByteBuffer发送
}
})
// 5、连接到服务器
.connect(new InetSocketAddress("localhost",8080))
.sync()
.channel()
// 6、向远程服务器发送数据
.writeAndFlush("Hello world");
}
💡 具体执行逻辑
- 把channel理解为数据的传输通道
- 把msg理解为流动的数据,最开始输入是ByteBuf,但经过pipeline(流水线)的加工,会变成其他类型对象,最后输出又变成ByteBuf
- 把handler理解为数据的处理工序
- 工序有躲到,合在一起就是pipeline,pipeline负责发布事件(读,读取完成…)传播给每个handler,handler对组件感兴趣的事件进行处理(重写了相应事件处理方法)
- handler分lnbound(入站) 和 Outbound(出站)两类
- 把eventLoop理解为处理数据的工人
- 工人可以管理多个channel的io操作,并且一旦工人负责了某个channel,就要负责到底(绑定)
- 工人既可以执行io操作,也可以进行任务处理,每位工人有任务队列,队列里可以堆放多个channel的待处理任务,任务分为普通任务,定时任务
- 工人按照pipeline顺序,依次按照handler的规划(代码)处理数据,可以为每道工序指定不同的工人