RocketMQ中的Producer启动流程
1.总体设计
生产者启动的流程比消费者启动的流程更加简单一般用户使用DefaultMQProducer的,构造函数构造一个生产者实例,并设置各种参数,比如,Namesrv地址、生产者组名等,调用start()方法启动生产者实例,start()方法调用了生产者默认实现类的start()方法启动,这里我们主要分析start()方法内部是怎么实现的
2.构造函数初始化实例
这里初始化了namespace、producerGroup以及defaultMQProducerImpl
3.启动生产者实例start()
源码中关键点在于defualtMQProducerImpl的启动方法
调用了重载的start()方法
4.CREATE_JUST。通过switch-case判断当前生产者的服务状态,创建时默认是CREATE_JUST,设置默认启动状态为启动失败
这里可以看到ServiceState第一次初始化出来的时候就是CREATE_JUST
当服务启动时状态肯定是CREATE_JUST,当再次调用start()方法启动时,ServiceState就会发生变化,RUNNING或者SHUTDOWN,RocketMQ,会提示你曾经启动过,无需再次启动
5.将生产者置为启动失败
6.生产者参数校验,执行checkConfig()方法,校验生产者实例设置的各种参数,比如生产者组名是否为空,是否满足命名规则,长度是否满足等等
7.转换组名,创建MQClientInstance
默认生产者组名转换为进行id,执行changeInstanceNameToPID()方法,校验instance name,如果是默认名字则将其修改为进程id.接着调用getOrCreateMQClientInstance(),创建一个MQClientInstance实例,它与ClientId是一一对应,clientId是由ClientIP、instance及unitName,构成的,一般来讲,为了减少客户端的使用资源,如果将所有的instanceName和unitName设置为同样的值,就只会创建一个MQClientInstance实例,而MQClientInstance实例的功能是管理本实例中全部的生产者与消费者的生产和消费行为。同时将调用registerProducer()将生产者放入组中
7.1 MQClientInstance核心组件
- producerTable:当前Client实例的全部生产者的内部实例
- consumerTable:当前client实例的全部消费者的内部实例
- adminExtTable:当前client实例的全部管理实例
- mQClientAPIImpl:其实每个client也是一个NettyServer,也会支持Broker访问,这里实现了全部Client支持的接口
- mQAdminImpl:管理接口的本地实现类
- topicRouteTable:当前生产者、消费者中全部Topic的本地缓存路由信息
- scheduledExecutorService:本地定时任务。比如定期获取当前Namesrv地址、定期同步Namesrv信息、定期更新Topic路由信息、定期发送心跳给Broker、定期清理已下线的Broker、定期持久化消费位点、定期调整消费线程数
- clientRemotingProcessor:请求的处理器,从处理方法processRequest()中我们可以直到目前支持哪些功能接口
- pullMessageService:pull服务,这里是一个兼容写法,Pull服务是由一个状态变量方法this.isStopped()控制的,
这个stopped状态变量默认是false,而pullRequestQueue也是空的,所以这里之启动了pullMessageService,并没有真正地执行Pull操作 - rebalanceService:重新平衡服务,定期执行重新平衡方法this.mqClientFactory.doRebalance(),这里地mqClientFactory就是MQClientInstance实例,通过依次调用MQClientInstance中保存地消费者实例地doRebalance()方法,来感知订阅关系地变化、集群变化等,以达到重新平衡
- consumerStateManager:消费监控,比如拉取RT(Response Time,响应时间)、拉取TPS(Transaction Per Second,每秒处理消息数),消费RT等都可以统计
7.2 MQClientInstance核心方法
- updateTopicRouteInfoFromNameServer:从多个Namesrv中获取最新Topic路由信息,更新本地缓存
- cleanOfflineBroker:清理已下线的Broker
- checkClientInBroker:检查Client是否在Broker中有效
- sendHeartbeatToAllBrokerWithLock:发送客户端的心跳给所有的broker
- registerConsumer:在本地注册一个消费者
- unregisterConsumer:取消本地注册的消费者
- registerProducer:在本地注册一个生产者
- unregisterProducer:取消本地注册的生产者
- registerAdminExt:注册一个管理实例
- rebalanceImmediately:立即执行一次Rebalance.该操作是通过RokcetMQ的一个CountDownLatch2锁来实现的
- doRebalance:对于所有已经注册的消费者实例,执行一次Rebalance
- findBrokerAddressInAdmin:在本地缓存中查找Master或Slave Broker信息
- findBrokerAddressInSubscribe:在本地缓存中查找Slave Broker信息
- findBrokerAddressInPublish:在本地缓存中查找Master Broker地址
- findConsumerIdList:查找消费者id列表
- findBrokerAddressByTopic:通过Topic名字查找Broker地址
- resetOffset:重置消费位点
- getConsumerStastusL获取一个订阅关系中每个队列的消费速度
- getTopicRouteTable:获取本地缓存Topic路由
- consumeMessageDirectly:直接将消息发送给指定的消费者消费,和正常投递不同的是,指定了已经订阅的
消费者组中的一个,而不是全部已经订阅的消费者,一般使用于在消费消息后,某个消费者组想再香妃一次的场景 - consumerRunningInfo:获取消费者的消费统计信息,包含消费RT、消费TPS