本文主要内容:

  • Netty的技术和体系结构方面的内容
  • Channel、EventLoop和ChannelFuture
  • ChannelHandler和ChannelPipeline
  • 引导

学习Netty是因为它是基于Java NIO 的异步事件驱动的实现,保证了高负载下应用程序性能的最大化和可伸缩性;同时它包含了一组设计模式,实现了应用程序逻辑从网络层解耦,简化了开发过程,最大限度地提高了可测试性、模块化以及代码的可重用性。

1. Channel、EventLoop和ChannelFuture

  • Channel:Socket;

  • EventLoop:控制流、多线程处理、并发;

  • ChannelFuture:异步通知

Channel接口

基本的I/O操作(bind、connect、read、write)都依赖于底层网络传送所提供的原语,也就是Socket,而Netty中的Channel就是简化Socket编程的复杂性

EventLoop接口

用于处理连接的生命周期中所发生的事件

在这里插入图片描述

其关系是:

  • 一个EventLoopGroup包含一个或多个EventLoop;
  • 一个EventLoop在它的生命周期内只和一个Thread绑定;
  • 所有由EventLoop处理的I/O事件都将在它专有的Thread上被处理(消除了对同步的需求
  • 一个Channel在它的生命周期内只注册于一个EventLoop;
  • 一个EventLoop可能会被分配给一个或多个Channel。

ChannelFuture

正因为Netty中所有的I/O操作都是异步的,其执行结果不会立即返回,所以Netty提供了ChannelFuture接口,其addListener()方法注册了一个ChannelFutureListener,以便在某个操作完成时(无论是否成功)都能得到通知。

2. ChannelHandler和ChannelPipeline

管理数据流以及执行应用程序处理逻辑的组件

ChannelHandler接口

充当了所有处理入站和出站数据的应用程序逻辑的容器,因为ChannelHandler的方法是由网络事件触发的。

ChannelPipeline接口

提供了ChannelHandler链的容器,并定义了用于在该链上传播入站和出站事件流的API,当Channel被创建时,他会被自动的分配到它专属的ChannelPipeline。

//在创建Channel时向ChannelPipeline中添加一个EchoClientHandler实例
.handler(new ChannelInitializer<SocketChannel>() {
    @Override
    protected void initChannel(SocketChannel socketChannel) throws Exception {
        socketChannel.pipeline().addLast(new EchoClientHandler());
    }
});

在这里插入图片描述

执行顺序由添加顺序所决定,ChannelHandler处理完后将数据传递给链中的下一个ChannelHandler,该ChanelHandler不一定会去修改数据,如果数据到达ChannelPipeline一端,也就说明处理结束。

当ChannelHandler被添加到ChannelPipeline时,它将会被分配一个ChannelHandlerContext,其代表了ChannelHandler和ChannelPipeline之间的绑定,主要用于写出站数据。

在Netty中有两种发送消息的方式,直接写到Channel中,也可以写到ChannelHandlerContext对象中,前一种方式将会导致消息从ChannelPipeline的尾端开始流动,后者将导致消息从ChannelPipeline中的下一个ChannelHandler开始流动。

编码器和解码器

因为网络数据总是一系列的字节,而我们写的代码是一些对象

所有由Netty提供的编码器/解码器适配器类都实现了ChannelInboundHandler接口或者ChannelOutboundHandler接口。

抽象类SimpleChannelInboundHandler

当我们利用一个ChannelHandler来接收解码消息,并对该数据应用业务逻辑,基本上只需要扩展基类SimpleChannelInboundHandler,其中T就是我们要处理的Java类型。

@ChannelHandler.Sharable
public class EchoClientHandler extends SimpleChannelInboundHandler<ByteBuf> {
//这里的ByteBuf应该是跟服务端代码没有关系的,根据我们自身的业务需求来定的
    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf) throws Exception {
        System.out.println("Client received: "+ byteBuf.toString(CharsetUtil.UTF_8));
    }

引导

Netty的引导类为应用程序的网络层配置提供了容器,有两种类型的引导:一种用于客户端,另一种用于服务器,区别如下:

区别 BootStrap ServerBootStrap
网络编程中的作用 连接到远程主机和端口 绑定到一个本地端口
EventLoopGroup的数目 1 2

为什么ServerBootStrap需要两个EventLoopGroup呢?

因为服务器需要两组不同的Channel,第一组将只包含一个ServerChannel,代表服务器自身的已绑定到某个本地端口的正在监听的套接字,而第二组将包含所有已创建的用来处理传入客户端连接的Channel

在这里插入图片描述


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!

4.Netty--传输 Previous
2.Netty--你的第一款Netty应用 Next