Netty 拆包粘包和服务启动流程分析

Netty 拆包粘包和服务启动流程分析

通过本章学习,笔者希望你能掌握EventLoopGroup的工作流程,ServerBootstrap的启动流程,ChannelPipeline是如何操作管理Channel。只有清楚这些,才能更好的了解和使用Netty。还在等什么,快来学习吧!

知识结构图:

Netty

技术:Netty,拆包粘包,服务启动流程
说明:若你对NIO有一定的了解,对于本章知识来说有很大的帮助!NIO教程
源码:https://github.com/ITDragonBlog/daydayup/tree/master/Netty/netty-stu

Netty 重要组件

这里让你清楚了解 ChannelPipeline,ChannelHandlerContext,ChannelHandler,Channel 四者之间的关系。
这里让你清楚了解 NioEventLoopGroup,NioEventLoop,Channel 三者之间的关系。
这里让你清楚了解 ServerBootstrap,Channel 两者之间的关系。
看懂了这块的理论知识,后面Netty拆包粘包的代码就非常的简单。

Channel

Channel : Netty最核心的接口。NIO通讯模式中通过Channel进行Socket套接字的读,写和同时读写操作。
ChannelHandler : 因为直接使用Channel会比较麻烦,所以在Netty编程中通过ChannelHandler间接操作Channel,从而简化开发。
ChannelPipeline : 可以理解为一个管理ChandlerHandler的链表。对Channel进行操作时,Pipeline负责从尾部依次调用每一个Handler进行处理。每个Channel都有一个属于自己的ChannelPipeline。
ChannelHandlerContext : ChannelPipeline通过ChannelHandlerContext间接管理每个ChannelHandler。

如下图所示,结合代码,在服务器初始化和客户端创建连接的过程中加了四个Handler,分别是日志事务,字符串分割解码器,接受参数转字符串解码器,处理任务的Handler。

Netty 拆包粘包和服务启动流程分析

NioEventLoopGroup

EventLoopGroup : 本质是个线程池,继承了ScheduledExecutorService 定时任务线程池。
NioEventLoopGroup : 是用来处理NIO通信模式的线程池。每个线程池有N个NioEventLoop来处理Channel事件,每一个NioEventLoop负责处理N个Channel。
NioEventLoop : 负责不停地轮询IO事件,处理IO事件和执行任务,类比多路复用器,细化分三件事。
1 轮询注册到Selector上所有的Channel的IO事件
2 处理产生网络IO事件的Channel
3 处理队列中的任务

Netty 拆包粘包和服务启动流程分析

ServerBootstrap

本章重点,Netty是如何通过NIO辅助启动类来初始化Channel的?先看下面的源码。

@Override void init(Channel channel) throws Exception { final Map<ChannelOption<?>, Object> options = options0(); synchronized (options) { setChannelOptions(channel, options, logger); } final Map<AttributeKey<?>, Object> attrs = attrs0(); synchronized (attrs) { for (Entry<AttributeKey<?>, Object> e: attrs.entrySet()) { @SuppressWarnings("unchecked") AttributeKey<Object> key = (AttributeKey<Object>) e.getKey(); channel.attr(key).set(e.getValue()); } } ChannelPipeline p = channel.pipeline(); final EventLoopGroup currentChildGroup = childGroup; final ChannelHandler currentChildHandler = childHandler; final Entry<ChannelOption<?>, Object>[] currentChildOptions; final Entry<AttributeKey<?>, Object>[] currentChildAttrs; synchronized (childOptions) { currentChildOptions = childOptions.entrySet().toArray(newOptionArray(childOptions.size())); } synchronized (childAttrs) { currentChildAttrs = childAttrs.entrySet().toArray(newAttrArray(childAttrs.size())); } p.addLast(new ChannelInitializer<Channel>() { @Override public void initChannel(final Channel ch) throws Exception { final ChannelPipeline pipeline = ch.pipeline(); ChannelHandler handler = config.handler(); if (handler != null) { pipeline.addLast(handler); } ch.eventLoop().execute(new Runnable() { @Override public void run() { pipeline.addLast(new ServerBootstrapAcceptor( ch, currentChildGroup, currentChildHandler, currentChildOptions, currentChildAttrs)); } }); } }); }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wssjgg.html