producer 发送流程
producer 在消息发送时,肯定要先知道 topic 的信息,以及 topic 在哪个 broker 上,那么 producer 是如何做的呢?
还记得在 01 开篇说的吗? namesrv
提供一个通过 topic
获取路由信息的接口(RouteInfoManager#pickupTopicRouteData
). producer
就是根据该接口返回的 TopicRouteData
, 知道要将 topic
发送至哪个 broker
.
TopicRouteData
private String orderTopicConf;
private List<QueueData> queueDatas;
private List<BrokerData> brokerDatas;
private HashMap<String/* brokerAddr */, List<String>/* Filter Server */> filterServerTable;
从返回的结构来看,知道了 broker 地址,还有 topic
下有哪些队列,接下来就可以发消息了。
producer
获取了 topic
的信息,会将这些信息封装为另外一个数据结构
class TopicPublishInfo {
...
private List<MessageQueue> messageQueueList = new ArrayList<MessageQueue>();
private volatile ThreadLocalIndex sendWhichQueue = new ThreadLocalIndex();
...
}
class MessageQueue {
private String topic;
private String brokerName;
private int queueId;
}
messageQueueList
大概长这样子
[
{
"brokerName":"broker-a",
"queueId":0,
"topic":"TBW102%zouLeTopic"
},
{
"brokerName":"broker-a",
"queueId":1,
"topic":"TBW102%zouLeTopic"
},
{
"brokerName":"broker-a",
"queueId":2,
"topic":"TBW102%zouLeTopic"
},
{
"brokerName":"broker-a",
"queueId":3,
"topic":"TBW102%zouLeTopic"
},
{
"brokerName":"broker-b",
"queueId":0,
"topic":"TBW102%zouLeTopic"
},
{
"brokerName":"broker-b",
"queueId":1,
"topic":"TBW102%zouLeTopic"
},
{
"brokerName":"broker-b",
"queueId":2,
"topic":"TBW102%zouLeTopic"
},
{
"brokerName":"broker-b",
"queueId":3,
"topic":"TBW102%zouLeTopic"
}
]
可以看到,上面的 topic TBW102%zouLeTopic
在 broker-b, broker-a
都存在
我们知道了 topic 可以有很多队列,那么 producer 在发消息时,如何选择哪个队列发送呢?
答案是 从 messageQueueList
中轮询选择一个队列进行发送(每个线程,都有自己的计数器)。
TopicPublishInfo#selectOneMessageQueue(final String lastBrokerName)
public MessageQueue selectOneMessageQueue(final String lastBrokerName) {
if (lastBrokerName == null) {
// 大部分情况走这个函数
return selectOneMessageQueue