发送消息流程
Producer端-client模块
- 找到往哪台机器上发。根据消息中的Topic,获取到其路由信息(包括Broker地址)
- 找到往哪个消息队列发。负载均衡平均发到每个消息队列,且有容错机制,保证了高可用
- 创建消息。生成msgId
- 创建RemotingCommand-requestCommand
- 生成opaqueId(自增1),每次创建会自增2,Broker接收到消息后会序列化导致再次+1
- 生成code码,不同的code码代表不同的Neety请求处理器,以及不同的线程池,Producer#start会进行初始化
Producer端-remoting模块
- RemotingClient发送消息。
- 创建ResponseFuture返回对象。以opaque为key,返回对象为value,放到responseTable中。
- 通过Netty的通道将请求发送到Broker端,等待处理结果。利用CountDownLatch阻塞等待response,当ResponseFuture中被设置了response,CountDownLatch就会解锁,就会获取到response
Broker端-remoting模块
- 分配任务。通道接收到后消息,丢给工作线程进行处理
- 保存消息
- 通过code码获取到发送消息处理器与线程池
- 异步执行保存逻辑,生成offsetId,保存到commitlog中,再保存到topic的对应队列中,生成queueId
- 创建RemotingCommand-responseCommand
- 通过Netty通道将响应发送到Producer端
Producer端-remoting模块
- 释放7步的等待锁。接收到处理结果,释放7步的等待锁
- 消息发送会进行重试。异步1次,同步3次,BrokerException、InterruptedException不会重试
发送消息时如何选择消息队列?
TopicPublishInfo.sendWhichQueue
每次自增ThreadLocal维护的变量,用该变量跟消息队列数量 取余。
发送消息的broker故障延迟机制?
因为NameServe不会主动告诉Producer有Broker宕机,而Client每30s才会更新Broker的信息,
在这期间内会重复向宕机的Broker发送消息。为了实现发送消息高可用就有了故障延迟机制
Producer内存中维护了一个以BrokerName为key的Map,当消息发送失败后存储到Map中,
且有Broker的下次恢复时间,在这期间内会跳过故障的Broker。
之前代运营使用eip,发消息总是提示超时是怎么回事