网络通信相关功能
作为客户端,要和 NameServer、Broker通信, 所以要建立连接,通信要有协议,网络上传输/接收需要序列化/反序列化。
5.X 使用 gRpc 和 protobuf,这里讲下 4.X 的实现。
RocketMQ 采用了 Netty 进行网络通信,客户端的具体实现是 NettyRemotingClient。
序列化/反序列化: 参考官网SDK发送消息。4.X版本的请求头默认使用 json 序列化,body 是字节数组,不需要序列化。
下图是请求头的序列化方法。
心跳检测
心跳检测是服务端和客户端间探活的一种机制。一般通过 ping-pong(乒乓,有来有回) 的方式进行探测。
从下边的两张图可以看到,client 和 server 都关闭了 TCP 的 keepAlive。
这是方式的缺点是配置不灵活,属于 TCP 层面的配置,对所有应用都生效;而且仅检测连接是否可用,对端能否正常工作是不知道的。RocketMQ 使用的是应用层面的探活机制。
生产者和消费者心跳
生产者和消费者会定期向 Broker 发送心跳请求,请求数据如下图
Broker
Broker 定时向 NameServer 注册
Broker 定时会关闭不活跃的连接
NameServer
NameServer 会定时关闭不活跃的连接
重试机制
重试机制官网描述很清晰,就不赘述了。官网:消息发送重试机制
负载均衡
生产者
topic 是个逻辑概念,队列才是消息的实际容器,大部分消息队列都有这个概念,如 kafka 称为分区。
这里顺带说下,在队列粒度场景下,队列主要是为了水平扩容。一个队列只能由同一消费者组内的单一消费者处理,如果数据量大的话,可以扩容队列数量,提升消费能力。5.X 版本支持多个消费者消费一个队列。
对于要求消息有序的场景,生产端重要的一点就是需要指定写入的队列,以保证消息的有序性。
默认是轮询,自定义需要实现 MessageQueueSelector 接口。
消费者
在 RocketMQ 中,有两种消费模式,下方左图为广播消费,右图为消费者组内共享消费。
广播消费场景下,每个消费者分组内只有一个消费者组,因此不涉及消费者的负载均衡。
消费者负载均衡指的是,消息按哪种逻辑分配给哪个消费者。感兴趣的可以看下重平衡的实现
集群消费默认策略是 AllocateMessageQueueAveragely
发送消息
发送就四种
- 同步
- 异步
- oneWay
- 事务消息:参见官网事务消息
其它功能
- ssl
- 压缩:默认 body 大于等于4k时压缩
- 延迟
消费消息
4.X 参见官网文章 消费者分类
5.X 参见官网文章 消费者分类