1、什么是 Netty
Netty is an asynchronous event-driven network application framework
for rapid development of maintainable high performance protocol servers & clients.
复制代码
Netty 是一个异步的、基于事件驱动的网络应用框架,用于疾速开发可保护、高性能的网络服务器和客户端
留神:netty的异步还是基于多路复用的,并没有实现真正意义上的异步IO
2、Netty 的劣势
如果应用传统 NIO,其工作量大,bug 多
须要本人构建协定
解决 TCP 传输问题,如粘包、半包
因为 bug 的存在,epoll 空轮询导致 CPU 100%
Netty 对 API 进行加强,使之更易用,如
FastThreadLocal => ThreadLocal
ByteBuf => ByteBuffer
3、入门案例
1、服务器端代码
public class HelloServer {
public static void main(String[] args) { // 1、启动器,负责拆卸netty组件,启动服务器 new ServerBootstrap() // 2、创立 NioEventLoopGroup,能够简略了解为 线程池 + Selector .group(new NioEventLoopGroup()) // 3、抉择服务器的 ServerSocketChannel 实现 .channel(NioServerSocketChannel.class) // 4、child 负责解决读写,该办法决定了 child 执行哪些操作 // ChannelInitializer 处理器(仅执行一次) // 它的作用是待客户端 SocketChannel 建设连贯后,执行 initChannel 以便增加更多的处理器 .childHandler(new ChannelInitializer<NioSocketChannel>() { @Override protected void initChannel(NioSocketChannel nioSocketChannel) throws Exception { // 5、SocketChannel的处理器,应用StringDecoder解码,ByteBuf=>String nioSocketChannel.pipeline().addLast(new StringDecoder()); // 6、SocketChannel的业务解决,应用上一个处理器的处理结果 nioSocketChannel.pipeline().addLast(new SimpleChannelInboundHandler<String>() { @Override protected void channelRead0(ChannelHandlerContext channelHandlerContext, String s) throws Exception { System.out.println(s); } }); } // 7、ServerSocketChannel绑定8080端口 }).bind(8080);}
}
复制代码
2、客户端代码
public class HelloClient {
public static void main(String[] args) throws InterruptedException { new Bootstrap() .group(new NioEventLoopGroup()) // 抉择客户 Socket 实现类,NioSocketChannel 示意基于 NIO 的客户端实现 .channel(NioSocketChannel.class) // ChannelInitializer 处理器(仅执行一次) // 它的作用是待客户端SocketChannel建设连贯后,执行initChannel以便增加更多的处理器 .handler(new ChannelInitializer<Channel>() { @Override protected void initChannel(Channel channel) throws Exception { // 音讯会通过通道 handler 解决,这里是将 String => ByteBuf 编码收回 channel.pipeline().addLast(new StringEncoder()); } }) // 指定要连贯的服务器和端口 .connect(new InetSocketAddress("localhost", 8080)) // Netty 中很多办法都是异步的,如 connect // 这时须要应用 sync 办法期待 connect 建设连贯结束 .sync() // 获取 channel 对象,它即为通道形象,能够进行数据读写操作 .channel() // 写入音讯并清空缓冲区 .writeAndFlush("hello world");}
}
复制代码
3、运行流程
左:客户端 右:服务器端
组件解释
channel 能够了解为数据的通道
msg 了解为流动的数据,最开始输出是 ByteBuf,但通过 pipeline 中的各个 handler 加工,会变成其它类型对象,最初输入又变成 ByteBuf
handler 能够了解为数据的解决工序
工序有多道,合在一起就是 pipeline(传递路径),pipeline 负责公布事件(读、读取实现…)流传给每个 handler, handler 对本人感兴趣的事件进行解决(重写了相应事件处理办法)
pipeline 中有多个 handler,解决时会顺次调用其中的 handler
handler 分 Inbound 和 Outbound 两类
Inbound 入站
Outbound 出站
eventLoop 能够了解为解决数据的工人
eventLoop 能够治理多个 channel 的 io 操作,并且一旦 eventLoop 负责了某个 channel,就会将其与 channel 进行绑定,当前该 channel 中的 io 操作都由该 eventLoop 负责
eventLoop 既能够执行 io 操作,也能够进行工作解决,每个 eventLoop 有本人的工作队列,队列里能够堆放多个 channel 的待处理工作,工作分为一般工作、定时工作
eventLoop 依照 pipeline 程序,顺次依照 handler 的布局(代码)解决数据,能够为每个 handler 指定不同的 eventLoop