RocketMQ发送消息原理分析

1.  路由注册

RocketMQ路由注册是通过Broker与NameServer的心跳功能实现的。Broker启动后每隔30s向集群中所有NameServer发送心跳包,然后Name Server每隔10s扫描Broker信息,如果连续120s没有收到心跳包,NameServer将移除该Broker的路由信息。

2.  消息发送

  •  同步发送:发送者向MQ发送消息时,同步等待,直到消息服务器返回发送结果。
  •  异步发送:发送者向MQ发送消息时,指定回调函数后便返回,消息发送者线程不阻塞。
  •  单向发送:发送者向MQ发送消息时,直接返回,不在乎消息是否成功存储在消息服务器上。

2.1  DefaultMQProducer的创建流程

  从start()方法作为入口,简单分析源码

  

  1. 创建MQClientInstance实例。整个JVM实例中只存在一个MQClientManager实例,MQClientManager维护一个MQClientInstance缓存表。MQClientInstance对应唯一的clientId,clientId由客户端IP + instanceName(一般会是进程ID)组成。(且同一个JVM中的不同消费者和不同生产者在启动时获取到的MQClientInstane实例都是同一个)
  2. 将当前生产者加入到MQClientInstance管理中,方便后续调用网络请求、进行心跳检测等。
  3. 启动MQClientInstance。

2.2  消息发送基本流程

  消息发送流程主要的步骤:验证消息、查找路由、消息发送(包含异常处理机制)。

  默认消息发送以同步方式发送,默认超时时间为3s。

  以sendMessage作为入口,简单分析源码

   

  1. 消息发送之前,首先确保生产者处于运行状态,然后验证消息是否符合相应的规范,具体的规范要求是主题名称、消息体不能为空、消息长度不能等于0且默认不能超过允许发送消息的最大长度4M。
  2. 其次获取主题的路由信息,只有获取了这些信息我们才知道消息要发送到具体的Broker节点。

    a)  如果获取不到主题路由信息(未创建主题)时,则使用默认的主题去查询,并将路由信息中的读写队列个数设置为produce默认的队列个数。

    

    b)  将查询到的主题路由信息和本地缓存进行比较,如果发生改变则更新本地的broker,然后会更新该MQClientInstance所管辖的所有消息发送关于topic的路由信息。
    

  3. 消息路由查找完之后,选择具体的消息队列。

    a)   本地对于每个topic会记录一个sendWhichQueue,选择消息队列后自增。

    b)   发送消息会采用重试机制,在收到发送失败结果执行回调之前会进行循环执行。当对某个broker的一个队列发送失败时,会跳过该broker。

    DefaultMQProducerImpl#sendDefaultImpl

    

    MQClientAPIImpl#onExceptionImpl

    

注意:从代码可以看出同步模式下只有在成功收到响应,且结果不是SEND_OK后才会触发重试机制;异步模式则是在通信异常后触发重试机制,响应结果只要不为空都会正常返回!也就是说同步模式下我们需要自己决定出现通信异常时如何处理,异步模式我们则需要自己决定响应结果不是SEND_OK时如何处理。

这里和书上说的刚好相反!

    c)   在多次消息发送过程中利用故障检测机制(即在一定的时间内规避不可用的broker)暂时排除故障broker。

  4. 发送消息核心入口,DefaultMQProducerImpl#sendKernelImpl

  1. 根据MessageQueue获取Broker的网络地址。如果MQClientInstance的brokerAddrTable未缓存该Broker的信息,则从NameServer主动更新一下topic的路由信息。
  2. 为消息分配全局唯一ID,如果消息体默认超过4K,会对消息体采用zip压缩,并设置消息的系统标记为MessageSysFlag.COMPRESSED_FLAG。如果是事务Prepared消息,则设置消息的系统标记为MessageSysFlag.TRANSACTION_PREPARED_TYPE。
  3. 处理before钩子函数,即可以在消息发送前增加一些额外处理。
  4. 构建消息发送请求包。
  5. 根据消息发送方式,同步、异步、单向方式进行网络传输。
  6. 处理after钩子函数,即使发送异常也会处理。

参考《RocketMQ技术内幕》

posted @ 2020-05-15 18:02  余快  阅读(1390)  评论(0编辑  收藏  举报