从tcp到netty(二)

(二)

Netty源码分析

做一套rpc长连接框架,架构上其实没有多么难,只要具体里面的步骤包括即可:

一、全双工的socket连接;

二、心跳检测

三、超时重连、重传

四、白名单

五、编解码

  这里还有相当多的技术规范与技术点,比如tcp消息封装定义消息头、消息体;定义反射类与方法用于远程方法执行;主从线程与线程池的设定;编解码序列的定义;粘包、拆

包,涉及到tcp报文包的分片;网络的流量、拥塞控制;编解码中的大小端;buffer数据解析等。

  其实,我不得不吐槽一下,netty源码分析那本书有些地方并不好,有些地方没有按照思维逻辑去讲解,而是按照执行顺序,这样其实并不符合这么一个项目的构建过程!

  还有一点,讲太细致,太深入,如果要全部分析完成,恐怕会非常耗时,其实很多只需要整体把握,如果有时间再慢慢消化!

全双工连接

  对于java来说,原生的java nio,其存在固有的复杂性与bug,难以令人满意!而netty则将用户边界做了封装,降低用户的开发难度,实际上我对于netty这本书的讲解流程并不满

意,因为它是按照代码的执行顺序讲解的,实际上并不符合人的思维逻辑;接下来我将会先从书中将的内容顺序梳理,然后再通过思维流程进行梳理一遍。

  首先要通过epoll理解buffer与channal!这两者是不同的,channal从物理上将是位于机器的内核空间,处于一个接收网络数据、本地文件数据等一系列前置底层的数据操作!

buffer则不然,对于java来说,就是为了将这些数据进行结构化,同时在物理上讲这是一种位于用户空间,也就是java进程中为了与对应java基本数据类型等的映射!

Server端:

一、根据netty权威指南,ServerBootstrapsocket服务端的启动辅助类,用途是封装启动参数

二、使用绑定Reactor线程池,处理多路复用的管道channal (netty书上说使用EventLoopGroup,但是我没有找到对应类的源码,可能读的不够深吧),也就是连接;

三、使用ServerSocketChannel嫁接数据 =》处理活跃连接的管道上,处理活跃连接;

四、ChannalPipeline这一步应该并不归于建立连接!用于处理请求数据的,比如验证信息、编码解码、心跳检测、流量控制等;

五、绑定监听端口,ServerSocketChannal注册到Selector(多路复用器,也就是为了处理epoll中的epoll_wait活跃事件)

六、轮询Selector,找出对应的Channal;

最终建立连接会有一个listen方法传入文件描述符、backlog,具体的实现类方法可以看

这个类,会发现一个这样的方法

  最终调用native的c函数获取操作系统的描述符,建立连接。关于backlog这个参数

是内核为此套接字排队的最大连接的个数。

  然后关于建立连接使用的两个队列:未连接队列、已连接队列,就是涉及到tcp的相关知识了!如果是建立连接的时候客户端发送syn报文段,此时未连接队列创建一个节点,当

server端发送syn与ack报文段之后一直到server端收到client端的ack报文段之前一直处于未连接队列;如果server端收到client的第三次握手ack,则将未连接队列的此节点移动到已完

成连接队列的队尾。系统默认为5,一般都会进行设置用以支持高并发!

  正是因为不同的操作方式,所以有了不同的操作位!SelectionKey,中有四个常量分别为OP_READ、OP_WRITE、OP_ACCEPT、OP_CONNECT,用于表示不同的事件。这

样切合了事件机制。这四种常量分别为针对1的位操作,分别为1、4、8、16,对应二进制位为0001、0100、1000、10000;书上指定是说错了的!使用位操作的优势,说是方便网

络操作位状态的判断与修改,这我可以理解,因为如果都转成二进制的话,在数据结构上更方便转换,但是我不理解的是为什么不适用0001、0010、0100、1000呢?后续再考量这

到底是怎么回事!

  基本上整体思路就是这样,具体到内部还有很多相关于java的内容,比如为什么ChannalHanlder使用volatile?Volatile只保证了可见性,没有保证原子性,我也没有找到它需要

保证原子性的操作,那么是它不需要保证原子性还是再更深处的地方做了处理?

Client端:

终于到了client端了!关于这块暂时不具体考虑netty的实现,而且不再按照书上说的代码执行顺序讲,具体的后续补发!

一、建立双工连接,可以使用NioSocketChannal、SocketChannal;

二、根据tcp的三次握手报文段,确认SelectionKey的枚举类型;

三、如果进入ChannalActive阶段,也就是epoll中epoll_waite活跃的连接,则设置网络操作位为SelectionKey.OP_READ阶段,否则连接到selector(多路复用器)阶段;

 ==========================================================================================================================

 

 

                      篇章二 - 定义request、response

                      篇章三 - 超时重传、心跳检测

                      篇章四 - 负载均衡

                      篇章五 - 服务平台管理

原文地址:https://www.cnblogs.com/kevinfuture/p/8558406.html