《netty实战》笔记 1-8章

第1章

 --------------------------------

 

 

  --------------------------------

   --------------------------------

 

 

 --------------------------------

 

 

  --------------------------------

 

此方式(java API阻塞方式):一个客户端——一个线程

当客户端连接非常多时很不理想
 
Java NIO——非阻塞

  --------------------------------

 

 

  --------------------------------

 

 

  --------------------------------

 

 回调就是ChannelHandler的方法(一个Handler包含多个回调)

事件是 按照它们与入站或出站数据流的相关性进行分类的。即网络事件
连接激活或连接失活
数据读取
用户事件
错误事件
 
打开或关闭到远程节点的连接
将数据写到或者冲刷到套接字
注册,绑定,写入,写入并冲刷等操作后都有返回ChannelFuture
Bootstrap方法(绑定或连接成功后netty执行自己定义的Listener回调方法)和ChannelOutboundInvoker方法(ChannelInitializer自己实现方法initChannel 先后注册Handler到pipelinenetty自动根据顺序处理这些Handler,Handler调用这些自己实现的回调方法

  --------------------------------

 

 

  --------------------------------

 

 

 一个回调其实就是一个方法,一个指向已经被提供给另外一个方法的方法的引用,多种事件有多种回调【如建立连接,断开连接】

  --------------------------------

 

 Channel 类型——EpollServerSocketChannel(Linux) 或 NioServerSocketChannel

 --------------------------------

 

 

 --------------------------------

 

 

 --------------------------------

 

 连接回调后:Future添加Listener处理连接的多种情况(连接成功,发生错误等),即Future是回调的精细化处理

 --------------------------------

 

 第2章 你的第一款netty应用程序

********************************第2章 客户端和服务端主要两个东西 1ChannelHandler逻辑 2EventLoop引导

 --------------------------------

 EventLoop:顾名思义 事件循环

EventLoop中有一个死循环的run方法,每时每刻都在检查绑定在自己身上的socket是否有事件发生,并处理这些事件;

 --------------------------------

 

 

 --------------------------------

 

 

 --------------------------------

 

 

 --------------------------------

 

 

 --------------------------------

 

 一个ChannelPipeline有一个ChannelHandler实例链,即:一个Channel有一个ChannelHandler实例链(ChannelHandler集合)

 --------------------------------

 

 

  --------------------------------

 

 

 --------------------------------

 

 

 --------------------------------

 

 引导ServerBootstrap

 --------------------------------

 

 

 --------------------------------

 

 

 --------------------------------

 

 

 --------------------------------

 

 

/**
 * 启动函数,地址和端口号
 */
public boolean start(String address, int port, ChannelHandler handler) {
   boolean isEpoll = Epoll.isAvailable();
   int cpuNum = Runtime.getRuntime().availableProcessors();

   if (isEpoll) {
      bossGroup = new EpollEventLoopGroup(cpuNum);
      workGroup = new EpollEventLoopGroup(cpuNum * 2 + 1);
   } else {
      bossGroup = new NioEventLoopGroup(cpuNum);
      workGroup = new NioEventLoopGroup(cpuNum * 2 + 1);
   }
   try {
      ServerBootstrap bootstrap = new ServerBootstrap();
      bootstrap.group(bossGroup, workGroup);
      bootstrap.channel(isEpoll ? EpollServerSocketChannel.class : NioServerSocketChannel.class);
      bootstrap.handler(new LoggingHandler(LogLevel.INFO));
      bootstrap.childHandler(handler);

      // TIME_WAIT时可重用端口,服务器关闭后可立即重启,此时任何非期
      // 望数据到达,都可能导致服务程序反应混乱,不过这只是一种可能,事实上很不可能
      bootstrap.option(ChannelOption.SO_REUSEADDR, true);
      // 设置了ServerSocket类的SO_RCVBUF选项,就相当于设置了Socket对象的接收缓冲区大小,4KB
      bootstrap.option(ChannelOption.SO_RCVBUF, 1024 * 8);
      // 请求连接的最大队列长度,如果backlog参数的值大于操作系统限定的队列的最大长度,那么backlog参数无效
      bootstrap.option(ChannelOption.SO_BACKLOG, 1024);

      // 使用内存池的缓冲区重用机制
      bootstrap.option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT);

      // 当客户端发生断网或断电等非正常断开的现象,如果服务器没有设置SO_KEEPALIVE选项,则会一直不关闭SOCKET。具体的时间由OS配置
      bootstrap.childOption(ChannelOption.SO_KEEPALIVE, true);
      // 在调用close方法后,将阻塞n秒,让未完成发送的数据尽量发出,netty中这部分操作调用方法异步进行。我们的游戏业务没有这种需要,所以设置为0
      bootstrap.childOption(ChannelOption.SO_LINGER, 0);
      // 数据包不缓冲,立即发出
      bootstrap.childOption(ChannelOption.TCP_NODELAY, true);
      // 发送缓冲大小,默认8192
      bootstrap.childOption(ChannelOption.SO_SNDBUF, 1024 * 8);
      // 使用内存池的缓冲区重用机制
      bootstrap.childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT);

      bootstrap.childOption(ChannelOption.WRITE_BUFFER_WATER_MARK, new WriteBufferWaterMark(1024 * 64, 1024 * 128));

      channelFuture = bootstrap.bind(new InetSocketAddress(address, port));
      channelFuture.sync();//阻塞,知道绑定操作完成为止

      Log.info("NettyComponentSocket->start, service start success address:{} port:{} isEpoll:{}", address, port, isEpoll);
      return true;
   } catch (Exception e) {
      Log.error("NettyComponent->start, init netty exception, address:{} port:{}", address, port, e);
      return false;
   }
}

 --------------------------------

 

 

 --------------------------------

 

 

 --------------------------------

 

 最大的区别在于SimpleChannelInboundHandler会对没有外界引用的资源进行一定的清理,并且入站的消息可以通过泛型来规定。

--------------------------------
ChannelInboundHandlerAdapter是ChannelInboundHandler一个简单实现,默认情况下不会做任何处理。只是简单的将操作通过fire方法传到ChannelPipeline中的下一个ChannelHandler中让链中的下一个ChannelHandler去处理。但是需要注意的是信息经过channelRead方法处理之后不会自动释放(是因为信息不会被自动释放所以能将信息传给下一个ChannelHandler处理。其次,在实现类Handler中,你仍然需要将传入消息回送给发送者,而 write() 操作是异步的,直到 channelRead() 方法返回后可能仍然没有完成。为此,实现类Handler扩展了 ChannelInboundHandlerAdapter ,其在这个时间点上不会释放消息。)
 
 
SimpleChannelInboundHandler支持泛型的消息处理,默认情况下消息处理完之后将会自动释放,无法提供fire*方法传递给ChannelPipeline中的下一个ChannelHandler.在客户端,当 channelRead0() 方法完成时,你已经有了传入消息,并且已经处理完它了。当该方法返回时,SimpleChannelInboundHandler负责释放指向保存该消息的ByteBuf的内存引用(自动调用Bytebuffer.release())。而为何服务器端不能用呢,因为我们想让服务器把客户端请求的数据发送回去,而服务器端有可能在channelRead方法返回前还没有写完数据,因此不能让它自动release。
 

 

项目中服务端也用了,有点奇怪?——可能是s2s用到。

 --------------------------------

 引导Bootstrap,服务端是local,客户端是remoteAddress

 --------------------------------

 

 

 --------------------------------

 

 --------------------------------

 

 第3章 Netty的组件和设计

********************************第3章 Netty的组件和设计
 

--------------------------------
引导——网络层配置容器

 

 

 --------------------------------

 

 

 --------------------------------

 

 --------------------------------

 

 一个线程——一个selector(注册表作用) —— 多个客户端——多个Channel

 --------------------------------

 

 --------------------------------

 

 --------------------------------

 

 --------------------------------

 

 

 --------------------------------

 

 

 --------------------------------

 

 --------------------------------

 

 

 --------------------------------

 

 --------------------------------

 服务端两组Channel(EventLoopGroup),一组管理服务端ServerChannel,一组管理传入的客户端连接的Channel。

 --------------------------------

 第4章 传输

 --------------------------------

 

 --------------------------------

 --------------------------------

 

 --------------------------------

 --------------------------------

 每个Channel都将会分配一个ChannelPipeline和ChannelConfig

 --------------------------------

 拦截过滤器——执行一遍注册的拦截器(Handler方法)

 
1、先基于长度的解码器LengthFieldBasedFrameDecoder【继承自ByteToMessageDecoder
(2 3)、服务端多两个Handler(心跳监测IdleStateHandler,心跳日志处理ChannelInboundHandlerAdapter
2、再编解码器CombinedChannelDuplexHandler 的容器。
3、最后是接收处理消息的Handler

 --------------------------------

 

 基于长度的解码器LengthFieldBasedFrameDecoder【继承自ByteToMessageDecoder

读取到的数据是基于流的, 而且是有方向的. 然而数据是没有边界的, 不知道从哪儿到哪儿是一个完整的数据, 下一个数据又是从哪个到哪个. 因此应用层需要设定规则, 根据规则就可以知道数据的边界在哪儿.
如何根据规则知道数据边界:规则一般是什么样的

 --------------------------------

 

 如上图, 便是根据设定的规则, 就可以’筛选’出来真正有意义的数据(data)在哪个. 而且允许每个data的长度是不一样大小.

 
那么就要说下这个规则是什么了. 规则是由4个主要的属性构成, lengthFieldOffset, lengthFieldLength, lengthAdjustment, initialBytesToStrip. 通过一个数据块为例介绍这4个属性.

 --------------------------------

 

如上图, 从红色箭头指向的位置开始读取数据.
lengthFieldOffset表示长度字段的偏移量, 经过lengthFieldOffset之后, 箭头指向了下一个位置. 如果lengthFieldOffset=3, 那么箭头需要向右边走3个字节.

 --------------------------------

 

 

 --------------------------------

 

 --------------------------------

 

 --------------------------------

 

 --------------------------------

 

 --------------------------------

 零拷贝特性。nio和 epoll类型传输时才可使用。ByteBuf内置的复合缓冲区类型 零拷贝。

 --------------------------------

 

 --------------------------------

 

 --------------------------------

 

 第 5 章 ByteBuf

 --------------------------------

 

 --------------------------------

 

 

 --------------------------------

 slice:片,切片

 --------------------------------

 尽量使用slice替换copy方法,减少复制开销,但是要注意 共享数据问题。

 

 --------------------------------

 

 

 --------------------------------

 

 --------------------------------

 

 --------------------------------

 

 --------------------------------

 

 

 --------------------------------

 

 --------------------------------

 

 

 --------------------------------

 

 --------------------------------

 

 --------------------------------

 

 

 --------------------------------

 

 --------------------------------

 第 6 章 ChannelHandler 和 ChannelPipeline

 --------------------------------

 

 --------------------------------

 

 --------------------------------

 

 --------------------------------

 

 --------------------------------

 

 --------------------------------

 

 

 --------------------------------

 

 --------------------------------

 

 --------------------------------

 

 --------------------------------

 

 --------------------------------

 

 --------------------------------

 

 --------------------------------

 

 --------------------------------

 

 --------------------------------

 

 --------------------------------

 

 --------------------------------

 

ChannelHandlerContext的高级用法。

 --------------------------------

 

 --------------------------------

 

 --------------------------------

 

 

 --------------------------------

 

 

 --------------------------------

 

 

 --------------------------------

 

 

 --------------------------------

 

 

 --------------------------------

 

 第 7 章 EventLoop 和 线程模型

 --------------------------------

 

 --------------------------------

 

 --------------------------------

 

 --------------------------------

 

 --------------------------------

 

 

 --------------------------------

 

 

 --------------------------------

 

 

 --------------------------------

 

 

 --------------------------------

 

 

 --------------------------------

 

 

 --------------------------------

 

 

 --------------------------------

 

 

 --------------------------------

 

 第8章 引导

 --------------------------------

 

 

 --------------------------------

 

 

 --------------------------------

 

 --------------------------------

 

 --------------------------------

 

 --------------------------------

 

 

 --------------------------------

 

 --------------------------------

 

 

 --------------------------------

 

 --------------------------------

 

 

 --------------------------------

 

 --------------------------------

 

 --------------------------------

 

 --------------------------------

 

 

 --------------------------------

 

 --------------------------------

 

 --------------------------------

 

 --------------------------------

 

 --------------------------------

 

 --------------------------------

 

 --------------------------------

 

 --------------------------------

 

 --------------------------------

 

 

 

 

 

 

posted @ 2023-03-02 10:50  好Wu赖  阅读(97)  评论(0编辑  收藏  举报