3.1 漫谈RocketMQ消息发送
RocketMQ支持3种消息发送方式:同步(sync)、异步(async)和单向(one way)。
1)同步:发送者向RocketMQ执行发送消息API时,同步等待,直到消息服务器返回发送结果。
2)异步:发送者向RocketMQ执行发送消息API时,指定消息发送成功后的回调函数,调用消息发送API后,立即返回,消息发送者线程不阻塞,直到运行结束,消息发送成功或失败的回调任务在一个新的线程中执行。
3)单向:消息发送者向RocketMQ执行发送消息API时,直接返回,不等待消息服务器的结果,也不注册回调函数。简单地说,就是只管发,不在乎消息是否成功存储在消息服务器上。
RocketMQ消息发送需要考虑以下3个问题。
1)消息队列如何进行负载?
2)消息发送如何实现高可用?
3)批量消息发送如何实现一致性?
3.1.1 topic路由机制
消息发送者向某一个topic发送消息时,需要查询topic的路由信息。初次发送时会根据topic的名称向NameServer集群查询topic的路由信息,然后将其存储在本地内存缓存中,并且每隔30s依次遍历缓存中的topic,向NameServer查询最新的路由信息。如果成功查询到路由信息,会将这些信息更新至本地缓存,实现topic路由信息的动态感知。
RocketMQ提供了自动创建主题(topic)的机制,消息发送者向一个不存在的主题发送消息时,向NameServer查询该主题的路由信息会先返回空,如果开启了自动创建主题机制,会使用一个默认的主题名再次从NameServer查询路由信息,然后消息发送者会使用默认主题的路由信息进行负载均衡,但不会直接使用默认路由信息为新主题创建对应的路由信息。使用默认主题创建路由信息的流程如图3-1所示。
图3-1 使用默认主题创建路由信息的流程
注意
RocketMQ中的路由消息是持久化在Broker中的,NameServer中的路由信息来自Broker的心跳包并存储在内存中。
3.1.2 消息发送高可用设计
发送端在自动发现主题的路由信息后,RocketMQ默认使用轮询算法进行路由的负载均衡。RocketMQ在消息发送时支持自定义的队列负载算法,需要特别注意的是,使用自定义的路由负载算法后,RocketMQ的重试机制将失效。
RocketMQ为了实现消息发送高可用,引入了两个非常重要的特性。
1)消息发送重试机制
RocketMQ在消息发送时如果出现失败,默认会重试两次。
2)故障规避机制
当消息第一次发送失败时,如果下一次消息还是发送到刚刚失败的Broker上,其消息发送大概率还是会失败,因此为了保证重试的可靠性,在重试时会尽量避开刚刚接收失败的Broker,而是选择其他Broker上的队列进行发送,从而提高消息发送的成功率。
消息发送的高可用性设计如图3-2所示。
图3-2 消息发送的高可用性设计
在开始消息发送、消息存储、消息消费之前,我们整体了解一下消息发送的流程,如图3-3所示。
图3-3 消息发送的流程