• 从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

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

                          篇章四 - 负载均衡

                          篇章五 - 服务平台管理

  • 相关阅读:
    l1-010
    l1-009
    L1-008修改
    l1-008
    Codeforces Round #406 (Div. 2)
    求N!的长度【数学】 51nod 1058 1130
    51nod 1090 & 1267 【二分简单题】
    Codeforces Round #405 (Div. 2)
    Codeforces Round #404 (Div. 2)
    PAT 天梯赛真题集(L2、L3)
  • 原文地址:https://www.cnblogs.com/kevinfuture/p/8558406.html
Copyright © 2020-2023  润新知