学习Rocketmq-producer启动(一)

来源:互联网 发布:java调用斑马打印机 编辑:程序博客网 时间:2024/04/28 01:27

最近看了下阿里Rocketmq,里面有很多的东西值得我们学习.

创建Producer

DefaultMQProducer producer = new DefaultMQProducer("cluster");producer.setNamesrvAddr(MyUtils.getNamesrvAddr());producer.start();

一个producer最简单的创建流程为以上几步

  1. new DefaultMQProducer()对象并设置其groupName
  2. 设置namesrvAddr
  3. 启动
public class DefaultMQProducer extends ClientConfig implements MQProducer

查看DefaultMQProducer源码不难发现该类是继承ClientConfig ,并去实现了MQProducer接口.
ClientConfig

private String namesrvAddr = System.getProperty(MixAll.NAMESRV_ADDR_PROPERTY,            System.getenv(MixAll.NAMESRV_ADDR_ENV));//namesrvAddr 地址private String clientIP = RemotingUtil.getLocalAddress();//当前ipprivate String instanceName = System.getProperty("rocketmq.client.name", "DEFAULT");//instanceName

DefaultMQProducer

private String createTopicKey = MixAll.DEFAULT_TOPIC;//默认topic名称private volatile int defaultTopicQueueNums = 4;//默认topic对了数量private int sendMsgTimeout = 3000;//发送超时private int compressMsgBodyOverHowmuch = 1024 * 4;//压缩private int retryTimesWhenSendFailed = 2;//发送重试次数private boolean retryAnotherBrokerWhenNotStoreOK = false;//换别的brokerprivate int maxMessageSize = 1024 * 128;//最大msgBody长度

当创建一个DefaultMQProducer对象时候会去初始化ClientConfig 与DefaultMQProducer中一系列的参数比如从环境变量去拿namesrvAddr地址,当前客户端的ip等.

Producer启动

下图为一个producer启动整个时序图.

这里写图片描述

代码解读

this.checkConfig();

改方法主要是针对producerGroup是否为空,是否占用默认的groupName等一些列的验证.

this.mQClientFactory=MQClientManager.getInstance().getAndCreateMQClientInstance(this.defaultMQProducer,rpcHook);

此处调用了getAndCreateMQClientInstance()方法,并把当前的producer对象,以及rpcHook作为参数传入

    public MQClientInstance getAndCreateMQClientInstance(final ClientConfig clientConfig, RPCHook rpcHook) {        String clientId = clientConfig.buildMQClientId();        MQClientInstance instance = this.factoryTable.get(clientId);        if (null == instance) {            instance =                    new MQClientInstance(clientConfig.cloneClientConfig(),                            this.factoryIndexGenerator.getAndIncrement(), clientId, rpcHook);            MQClientInstance prev = this.factoryTable.putIfAbsent(clientId, instance);            if (prev != null) {                instance = prev;            } else {                // TODO log            }        }        return instance;    }
  1. 创建一个当前producer的clientId格式为ip@pid
  2. 如果当前客户端不在mq客户端实例集合中,则创建一个实例并加入
boolean registerOK=mQClientFactory.registerProducer(this.defaultMQProducer.getProducerGroup(), this);

把当前返回客户端实例注册到producer集合中

this.topicPublishInfoTable.put(this.defaultMQProducer.getCreateTopicKey(), new TopicPublishInfo());

将topic放入topic集合中.createTopicKey其实是在程序配置的一个默认的topic名字.
为什么会传入一个默认的topic名字呢?
应为在创建每一个topic时,程序会去这个默认的topic作为模板,改topic以及所有创建的topic会保存在当前用户目录下的store/config/topics.json文件中.具体创建过程在后面的章节会详细说明.

mQClientFactory.start();

MQClientInstance.start()方法主要分为以下几个部分

  1. 获取nameService地址
  2. 启动client端远程通信
  3. 启动各种定时
    • 更新nameService地址
    • 更新从nameService更新topic路由信息
    • 清理挂掉的broker,向broker发送心跳信息
    • 持久化consumerOffset
    • 调整消费线程池
  4. 启动拉取消息服务
  5. 启动消费端负载均衡服务
  6. 再次调用DefaultMQProducerImpl.start()
  7. 改变serviceState状态
this.mQClientFactory.sendHeartbeatToAllBrokerWithLock();

心跳服务
疑点
1. MQClientInstance.start()方法中最后this.defaultMQProducer.getDefaultMQProducerImpl().start(false);反过来又去调用一次DefaultMQProducerImpl.start()方法这个我比较费解.感觉什么都没做,就调用了一次心跳服务.
2. 在rocketmq中不管是producer,还是consumer都抽象成一个MQClientInstance,启动时都会去调用MQClientInstance.start().该方法启动的server大部分都是和consumer相关,而在producer启动也在调用.
以上两个问题我看代码中比较有疑惑的,请大神们来指点

0 0
原创粉丝点击