Gateway-持有

设计目标

  1. 维护长连接socket状态
  2. 协议解析和消息包转发
  3. 状态统计与上报

技术约束

  1. 稳定性高,极少进行变更,减少重启的次数
  2. 转发过程性能高
  3. 内存占用小,单机持有更多的连接数量:垂直/水平

维护长连接socket状态

如何在连接处于静态状态时,消耗更少的内存资源?

选择tcp长连接作为传输层通信协议,因此需要在服务端维护socket的状态,最简单的办法就是两个协程对应一个socket(bilibili),一个处理此socket的读,一个处理写,并且需要有一个协程作为service socket监听服务端口,执行accept逻辑,因此需要1+2N的写成数来监听维护socket的状态,其中N时gateway的持有连接句柄数量。

这个不满足我们说的内存使用尽可能小的要求,因为一个协程要维护自己的协程栈信息,所以就算是在静止状态没有收发消息时,也需要消耗基本的协程栈的内存占用高达4kb,所以对于一个64GB的机器来说最多可以存储800w的连接,如果我们以一般的内存容量用于避免突发状况为消息手法留足资源,那么也能存储400w的连接,然后加上一下runtime的其他内存使用,以及注册表信息,实际能建立的连接远小于理论值,不超过30w,并且大量的协程为调度器增加了负担,使得整个gateway即使在非活跃时间段也维护着大量的内存资源,造成性能问题。

如果我们使用epoll多路复用技术在业务层再次实现,那么即可通过reactor模式减少在连接静止状态下内存的消耗。

只有当读事件或者写事件发生时才会去协程池获得一个协程去读写socket,当有消息push的时候才会创建一个协程,然后查询注册表信息找到socket进行读写,因此在连接静止状态下将没有协程的资源消耗,大部分的资源消耗会转化为os中epoll的红黑树的内存占用,而内核的性能将远高于业务进程,没有复杂的协程调度整体的GC和阻塞情况都将得到缓解,性能也能得到提升,而且可以做到单机突破百万长连接。

注册表如何维护?

维护一个全局大map,key是did,value是conn对象的指针(这样在下行消息转发时可以少查一跳),仅需要维护这样的一个map即可,在push时使用,整个更新过程都由state server来控制,gateway做的事越少越好,这样才能保证其不会频繁发生变更,不会重启,连接才会被稳定的持有(当然优雅关闭/平滑重启也是需要考虑的)

如何提高单机持有连接的数量?

尽可能少的创建内存结构,socket的内存是不容易节省的,因此去压榨应用层的内存roi极高,整个通信过程中gateway最大的内存消耗在于创建协程以及读取消息的buffer对象上,通过epoll机制我们能解决静态连接占用应用层内存过多的问题,通过多进程架构的思想,我们将心跳定时器等逻辑全部交由state server,让gateway保持简洁,我妈还可以通过内存分配器优化读取消息的buffer结构,尽可能复用内存并确保内存都有相应的池化工厂类非配避免资源耗尽倒置OOM

三个策略

  1. 反应堆模式,异步回调
  2. 工作多进程拆分
  3. 资源池化,对象复用

  1. 多accept机制,为提高吞吐量,我妈可以监听一个listenTCP,但是由多个协程进行accept,这样当某个协程因为未知原因panic后依然可以工作,避免了单点问题,并且有效的提高了整体的并发度。
  2. accept创建conn后交由全局的channel处理fd,然后由多个轮训起:epoller处理,每个epoller由两个协程和一个os层的epoll对象组成,epoller的数量等于cpu的逻辑核数,这样能保证最大的并行度,进一步度优化可以绑定协程到固定的cpu上,避免跨核心任何切换造成的性能损失。
  3. epoller中有一个sub accept监听全局的channel,当channel中有fd后将其消费,然后注册到自身的epoll对象中监听此socket上的读写事件,并且设置为水平触发。
  4. 另一个协程负责轮训epoll对象,并且以200ms为timeout放置忙轮训造成cpu load的拉高。
  5. 当每次wait到conn后,会在tcp基础之上做一层网关层的解析的len+data的简单模式,解析出来的data作为一个完整的消息报交由work pool协程池去处理,协程会发起rpc,将data交由state server去处理,这时他会上报fd+endpoint信息,方便state server知道该设备连接在哪一台网关机上。
  6. gateway,作为rpc server,需要创建一个rpc server容器组件,用来接收state server的操作。
  7. 通常state server会发送一些rpc来操作gateway的行为,state server辉存储did到endpoint+fd到映射,快读定位连接在哪台机器上,然后通过rpc将消息传递过来,携带的fd信息辉快速的定位到具体的conn将消息发送出去。