生产者
三种消息:普通消息(并发消息)、顺序消息、事务消息。
-
普通消息:无序,并发发送,性能最好
-
顺序消息:
- 分区有序消息:在单个分区中是有序的
- 全局有序消息:在全局范围里保持顺序,性能较差
-
事务消息:生产者先发送半消息,此时对消费者不可见。当commit时才可见。
三种发送方式:同步发送 sync、异步发送 async、单向发送 oneway。
-
同步:消息发送后一直等到服务器响应时才返回
-
异步:发送后直接返回,服务器响应后调用回调函数处理发送结果
-
单向:发送后直接返回,不关注发送结果,也不会处理响应
Message 包含的信息:
-
topic:主题名
-
flag:消息类型
-
properties:扩展属性
- tag:用于消息过滤
- keys:可包含多个key,用于根据key快速索引消息
- waitStoreMsgOK:是否等到存储完成后再返回
- delayTimeLevel:消息延迟级别,用于定时消息或消息重试。
-
消息内容
生产者启动流程:
-
检查productGroup是否符合要求;并改变生产者的instanceName为进程ID。
-
创建MQClientInstance实例。clientId为客户端IP+instance(默认为进程ID)+(unitname可选)
-
向MQClientInstance注册,将当前生产者加入到MQClientInstance管理中,方便后续调用网络请求、进行心跳检测等。
-
启动MQClientInstance
消息发送流程:
-
验证消息:主题名称、消息体不能为空、消息长度不能等于0且默认不能超过允许发送消息的最大长度4M
-
查找路由:查看本地是否缓存topic的路由信息且包含消息队列,否则向NameServer查询该topic的路由信息并缓存
-
选择消息队列:根据自增index取模选择列表里的borker,负载均衡
-
发送消息 & 异常处理
消息发送如何实现高可用?
-
普通网络问题:超时重试机制,retryTimesWhenSendFailed可设置重试次数,默认2
-
broker故障:标记此broker故障避免二次选择,从borker列表里再选择其他broker
消费者
基本概念:
-
消费者组:一组消费者共同处理一批数据,可订阅多个主题
- 集群模式:每条数据只被这个组里的一个消费者消费。
- 广播模式:每条数据被组里所有消费者消费
-
推模式:Server主动把数据推給消费者
-
拉模式:消费者主动从Server拉取数据
消费者启动流程:
-
构建主题订阅信息SubscriptionData并加入到RebalanceImpl的订阅消息中。
-
初始化MQClientInstance、RebalanceImple(消息重新负载实现类)等。
-
初始化消息进度。如果消息消费是集群模式,那么消息进度保存在Broker上;如果是广播模式,那么消息消费进度存储在消费端。
-
根据是否是顺序消费,创建消费端消费线程服务。ConsumeMessageService主要负责消息消费,内部维护一个线程池。
-
向MQClientInstance注册消费者,并启动MQClientInstance,在一个JVM中的所有消费者、生产者持有同一个MQClientInstance, MQClientInstance只会启动一次。
消息拉取流程
-
客户端消息拉取请求封装
- 从PullRequest中获取ProcessQueue,如果处理队列当前状态未被丢弃,则更新ProcessQueue的lastPullTimestamp为当前时间戳;如果当前消费者被挂起,则将拉取任务延迟1s再次放入到PullMessageService的拉取任务队列中,结束本次消息拉取。
- 进行消息拉取流控。对消息消费数量与消费间隔
- 拉取该主题订阅信息,如果为空,结束本次消息拉取,关于该队列的下一次拉取任务延迟3s。
- 构建消息拉取系统标记,根据brokerName、BrokerId从MQClientInstance中获取Broker地址,在每次拉取消息后,会给出一个建议,下次拉取从主节点还是从节点拉取
-
消息服务端Broker组装消息
- 根据订阅信息,构建消息过滤器。调用MessageStore.getMessage查找消息
- 根据主题名称与队列编号获取消息消费队列。消息偏移量异常情况校对下一次拉取偏移量。
- 如果待拉取偏移量大于minOffset并且小于maxOffset,从当前offset处尝试拉取32条消息,根据消息队列偏移量(ConsumeQueue)从commitlog文件中查找消息
- 根据主从同步延迟,如果从节点数据包含下一次拉取的偏移量,设置下一次拉取任务的brokerId。
- 如果commitlog标记可用并且当前节点为主节点,则更新消息消费进度
- 服务端消息拉取处理完毕,将返回结果到拉取消息调用方。
-
客户端处理返回的消息
-
根据响应结果解码成PullResultExt对象,调用pullAPIWrapper的processPullResult将消息字节数组解码成消息列表填充msgFoundList,并对消息进行消息过滤(TAG)模式。
-
更新PullRequest的下一次拉取偏移量,如果msgFoundList为空,则立即将PullReqeuest放入到PullMessageService的pullRequestQueue,以便PullMessageSerivce能及时唤醒并再次执行消息拉取。
-
将拉取到的消息存入ProcessQueue,然后异步将拉取到的消息提交到Consume-MessageService中供消费者消费
-
将消息提交给消费者线程之后PullCallBack将立即返回,拉取完成
-
消息推送机制
-
消费者循环向Server发生拉取请求,Server有数据就返回,看起来像是Server主动推送给消费者
Rebalance机制
- 目的:应对broker异常、消费者异常、Topic扩容等情况下的所有队列的正常消费以及负载均衡