Alligator 系列:MQ RPC
1. 概览
在 Alligator 系统中,网关与业务系统之间是通过 MQ
进行通信。为了简化开发成本,基于 MQ, 实现了一套 RPC
调用,其封装了超时、同步调用及异步调用等功能,调用模型如下图所示:
- 使用两个 MQ 队列来存储信息,分别是请求及响应信息;
- 在请求端维护一个 request id,在响应信息中带上 request id,从而将请求与响应对应起来;
- 在请求端为每一个请求设置一个超时任务,避免长时间未响应结果。
在 Alligator 系统中,网关与业务系统之间是通过 MQ
进行通信。为了简化开发成本,基于 MQ, 实现了一套 RPC
调用,其封装了超时、同步调用及异步调用等功能,调用模型如下图所示:
RocketMQ 是阿里推出的一款消息系统,用来取代 Kafka 及 RabbitMQ. 在
Alligator 中支持使用 RocketMQ, 其概念模型如下所示:
RabbitMQ 是一种消息系统,相比较其它消息系统,除了 queue,它多了一个
exchange 交换器的概念,在 Alligator 中支持使用 RabbitMQ,
其整体结构如下图所示:
在操作系统中内存管理的基本单位是 page, page 大小一般是
4k。为了满足不同场景,分配不同大小的内存,操作系统提供了丰富的内存管理方法。从分层的角度来说,可以用下面的层次图来表示。
EventLoop 是 Reactor 模式中的执行者,首先它持有 Selector 对象,监听多路 SocketChannel 的网络 I/O 事件,并对 I/O 事件分发处理。同时,它持有一个 Thread 对象,除了监听网络 I/O 事件, EventLoop 也可以执行提交的任务,包括定时任务,总结来说,EventLoop 具有如下三大功能:
ChannelPipeline 可以理解为一个 ChannelHandler 列表,而 ChannelHandler 是一个能够独立处理 channel 入站 (inbound) 事件或出站 (outbound) 操作的处理器。ChannelPipeline 实现了 "Intercepting Filter" 模式,它给用户提供了事件处理及 ChannelHandler 之间交互的能力,用户可以根据业务场景定义 ChannelHandler,以类似插件的方式添加到 ChannelPipeline 中。
因 Netty 中大量使用异步的调用方式,启动流程中的代码在不同的线程中执行,给分析其启动的顺序带来了一定的麻烦。这篇文章主要是对 ServerBootstrap 服务器启动流程做一个整体性的讲述,分析了每一个步骤所承担的工作,以及前后步骤的触发关系,即前一个步骤怎么调用后一个步骤,仍然以服务器启动的代码为例,分析其流程。
Reactor
模式是一种服务器网络编程模式,它根据网络数据接收的特点,将连接的建立、网络数据的读写分离,用
mainReactor 线程处理网络的连接,用 subReactor
处理数据的读写,同时为了有效利用 CPU 多核的优势,subActor
可以有多个。它的整体结构如下图所示:
特点:
Netty 中所有的的 I/O 操作都是异步的。I/O 操作是比较耗时的,为了不阻塞调用线程,Netty 提供了 ChannelFuture 接口,使用 addListener()方法注册一个 ChannelFutureListener 监听器,可以在 I/O 操作结束之后进行通知返回结果。在下面的代码中,bind 操作返回一个 ChannelFuture 对象,可以继续执行后续操作,也可以调用 sync() 方法同步等待执行结果,给程序开发带来了更多的开发模式,结合不同的业务场景,可以方便选择异步还是同步模式。
在长连接系统中,客户端及服务器之间需要通过发送心跳包来感知对方的存活状态,一般来说,心跳包不承载业务信息,不过在一些场景中,会把当前服务的状态推送给对方。在 Alligator 系统中统一在客户端发送心跳包,服务器会检测当前连接的空闲时间(即多久未收到数据),若超过一定时间,则判定为连接断线。在客户端,会检测连接的空闲写时间,超过一定时间,则触发发送心跳包,同时对服务端的响应做计数,超时一定次数未收到心跳响应,则判定服务器下线,触发重连操作。在注册中心系统中,客户端发送的心跳包中,会带上当前客户端的负载信息(连接数或用户数),注册中心根据这些负载信息,可以实现流量的有效负载。