Rocket MQ系列三 - 生产者启动流程
DefaultMQProducer是RocketMQ中默认的生产者实现,DefaultMQProducer的类之间的继承关系如下所示:
可以看到这个生产者在实现时包含生产者的操作和配置属性,这是典型的类对象设计。
以下是一些核心属性:
namesrvAddr:继承自ClientConfig,表示RocketMQ集群的Namesrv地址,如果是多个则用分号分开。
clientIP:使用的客户端程序所在机器的IP地址,支持IPv4和IPv6,IPv4排除了本地的环回地址和私有内网地址。这了需要注意的是,如果Client运行在Docker容器中,获取的IP地址是容器所在得IP地址,而非宿主机的IP地址。
instanceName:实例名,每个实例都需要取唯一的名字,因为有时我们会在同一个机器上部署多个程序进程,如果名字有重复就会导致启动失败。
vipChannelEnabled:这是一个boolean值,表示是否开启VIP通道。VIP通道和非VIP通道区别是:在通信过程中使用的端口号不同。
clientCallBackExecutorThreads:客户端回调线程数。该参数表示Netty通信层回调线程的个数,默认值Runtime.getRuntime().availableProcessors() 表示当前CPU的有效个数。
pollNameServerInterval:获取Topic路由信息的间隔时长,单位为ms,默认为30000ms。
heartbeatBrokerInterval:与Broker心跳间隔的时长,单位为ms,默认为30000ms。
defaultMQProducerImpl:默认生产者的实现类,其中封装了Broker的各种API。如果你想自己实现一个生产者,可以添加一个新的实现,保持DefaultMQProducer对外接口不变,用户完全没有感知。
producerGroup:生产者组名,这是一个必须传递的参数。RocketMQ-way表示同一个生产者组中的生产者实例行为需要一致。
sendMsgTimeout:发送超时时间,单位为ms。
compressMsgBodyOverHowmuch:消息体的容量上限,超过该上限时消息体会通过ZIP进行压缩,该值默认为4MB。该参数在Client中是如何生效的呢?具体实现代码如下:
retryTimesWhenSendAsyncFailed:异步发送失败后重试的次数。默认是2次。异步重试是有条件的重试,并不是每次发送失败后都重试。
以下是一些核心方法:
start():这是启动整个生产者实例的入口,主要负责校验生产者的配置参数是否正确,并启动通信通道、各种定时计划任务、Pull服务、Rebalance服务、注册生产者到Broker等操作。
shutdown():关闭本地已注册的生产者,关闭已注册到Broker的客户端。
fetchPublishMessageQueue(Topic):获取一个Topic有哪些Queue。在发送消息、Pull消息时需要调用。
send(Messgae msg):同步发送普通消息。
send(Message msg, long timeout):同步发送普通消息(超时设置)
send(Message msg,SendCallBack sendCallBack):异步发送普通消息
send(Message msg,SendCallBack sendCallBack, long timeout):异步发送普通消息(超时设置)
sendOneway(Message msg):发送单向消息。只负责发送消息,不管发送结果
send(Message msg,MessageQueue mq):同步向指定队列发送消息
send(Message msg,MessageQueue mq, long timeout):同步向指定队列发送消息(超时设置)
同步向指定队列发送消息时,如果只有一个发送线程,在发送到某个指定队列中时,这个指定队列中的消息是有顺序的,那么就按照发送时间排序;如果某个Topic的队列都是这种情况,那么我们称该Topic的全部消息是分区有序的。
send(Message msg,MessageQueue mq, SendCallBack sendCallBack):异步发送消到指定队列
send(Message msg,MessageQueue mq, SendCallBack sendCallBack, long timeout):异步发送消到指定队列(超时设置)
send(Message msg,MessageQueueSelector selector,Object arg,SendCallBack sendCallBack):自定义消息发送到指定队列。通过实现MessageQueueSelector接口来选择消息发送到哪个队列。
send(Collection<Message> msgs):批量发送消息
下面介绍两个核心管理接口
createTopic(String key,String newTopic,int queueName):创建Topic
viewMessage(String offsetMsgId):根据消息id查询消息内容
生产者启动的流程比消费者启动的流程更加简单,一般用户使用DefaultMQProducer的构造函数构造一个生产者实例,并设置各种参数。比如Namesrv地址、生产者组等,调用start()方法启动生产者实例,start()方法调用了生产者默认实现类的start()方法启动,这里我们主要讲实现类的start()方法的实现:
第一步:通过switch-case判断当前生产者的服务状态,创建时默认状态是CREATE_JUST,设置默认启动状态为启动失败。
第二步:执行checkConfig()方法。校验生产者实例设置的各种参数。比如生产者组名是否为空,是否满足命名规则、长度是否满足等。
第三步:执行changeInstanceNameToPID()方法。校验 instance name,如果是默认名字则将其修改为进程id。
第四步:执行getAndCreateMQClientInstance()方法,根据生产者组名获取获者初始化一个MQClientInstance。初始化代码如下:
MQClientInstance实例的功能是管理本实例中全部生产者与消费者的生产和消费行为。
下面对该实例中变量进行说明
