【RocketMQ源码分析】生产者

简单使用

public class SyncProducer {
   
    public static void main(String[] args) throws Exception {
   
        //使用ProducerGroup初始化Producer
        DefaultMQProducer producer = new
            DefaultMQProducer("group");
        // 指定namesrv
        producer.setNamesrvAddr("localhost:9876");
        producer.start();
        for (int i = 0; i < 100; i++) {
   
            //创建消息
            Message msg = new Message("Topic" /* Topic */,
                "TagA" /* Tag */,
                ("Hello RocketMQ " + i).getBytes(RemotingHelper.DEFAULT_CHARSET) /* Message body */
            );
            //发送消息
            SendResult sendResult = producer.send(msg);
            System.out.printf("%s%n", sendResult);
        }
        //关闭Producer
        producer.shutdown();
    }
}

上面是同步发送消息的简单使用,主要是初始化DefaultMQProducer,调用start()方法和send()方法.接下来具体分析生产者发送消息的具体过程。

DefaultMQProducer

DefaultMQProducer就是消息生产者的客户端,DefaultMQProducer的定义如下:

public class DefaultMQProducer extends ClientConfig implements MQProducer {
   
  ...
}

可以看到DefaultMQProducer实现了MQProducer接口并继承了ClientConfig类。

  • MQProducer接口
    在MQProducer接口定义了Producer的一些操作,并且继承了MQAdmin,在MQAdmin主要是一些管理功能接口,MQProducer中定义了各种发送消息的结构,同步发送,异步发送,oneway发送,批量发送和事务消息的发送。
public interface MQProducer extends MQAdmin {
   
    void start() throws MQClientException;

    void shutdown();

    List<MessageQueue> fetchPublishMessageQueues(final String topic) throws MQClientException;

    SendResult send(final Message msg) throws MQClientException, RemotingException, MQBrokerException,
        InterruptedException;

    // 省略一系列send方法

    // 失误相关的发送消息
    TransactionSendResult sendMessageInTransaction(final Message msg,
        final LocalTransactionExecuter tranExecuter, final Object arg) throws MQClientException;

    TransactionSendResult sendMessageInTransaction(final Message msg,
        final Object arg) throws MQClientException;

    //for batch
    SendResult send(final Collection<Message> msgs) throws MQClientException, RemotingException, MQBrokerException,
        InterruptedException;

    // 省略一系列的batch send的方法
}
public interface MQAdmin {
   

    void createTopic(final String key, final String newTopic, final int queueNum)
        throws MQClientException;

    void createTopic(String key, String newTopic, int queueNum, int topicSysFlag)
        throws MQClientException;

    long searchOffset(final MessageQueue mq, final long timestamp) throws MQClientException;

    long maxOffset(final MessageQueue mq) throws MQClientException;

    long minOffset(final MessageQueue mq) throws MQClientException;

    long earliestMsgStoreTime(final MessageQueue mq) throws MQClientException;

    MessageExt viewMessage(final String offsetMsgId) throws RemotingException, MQBrokerException,
        InterruptedException, MQClientException;

    QueryResult queryMessage(final String topic, final String key, final int maxNum, final long begin,
        final long end) throws MQClientException, InterruptedException;
  
    MessageExt viewMessage(String topic,
        String msgId) throws RemotingException, MQBrokerException, InterruptedException, MQClientException;

}
  • ClientConfig类
    ClientConfig根据类名称大概也能猜到,主要是负责一些配置信息。
public class ClientConfig {
   
    public static final String SEND_MESSAGE_WITH_VIP_CHANNEL_PROPERTY = "com.rocketmq.sendMessageWithVIPChannel";
    private String namesrvAddr = NameServerAddressUtils.getNameServerAddresses();
    private String clientIP = RemotingUtil.getLocalAddress();
    private String instanceName = System.getProperty("rocketmq.client.name", "DEFAULT");
    private int clientCallbackExecutorThreads = Runtime.getRuntime().availableProcessors();
    protected String namespace;
    protected AccessChannel accessChannel = AccessChannel.LOCAL;

    private int pollNameServerInterval = 1000 * 30;
   
    private int heartbeatBrokerInterval = 1000 * 30;
   
    private int persistConsumerOffsetInterval = 1000 * 5;
    private boolean unitMode = false;
    private String unitName;
    private boolean vipChannelEnabled = Boolean.parseBoolean(System.getProperty(SEND_MESSAGE_WITH_VIP_CHANNEL_PROPERTY, "false"));

    private boolean useTLS = TlsSystemConfig.tlsEnable;

    private LanguageCode language = LanguageCode.JAVA;
}

大致了解了一下DefaultMQProducer的结构,DefaultMQProducer有两个核心方法start()、send()方法。

start()

DefaultMQProducer初始化完成后,会调用start()方法,start方法主要是负责建立网络通信、初始化配置。它的具体实现最终是交给defaultMQProducerImpl#start()方法了。

public void start(final boolean startFactory) throws MQClientException {
   
    // 根据serviceState处理不同逻辑,初始化都是CREATE_JUST
    switch (this.serviceState) {
   
        case CREATE_JUST:
            this.serviceState = ServiceState.START_FAILED;
            // 检查配置信息,主要是ProducerGroup的,不重要
            this.checkConfig();
                        // 判断ProducerGroup是否是CLIENT_INNER_PRODUCER_GROUP,如果是将 ClientConfig#instanceName 改为进程PID,什么情况下是CLIENT_INNER_PRODUCER_GROUP呢?接下来会接触到,由于我们都会指定自己的group,所以这里会进入到if语句里面修改ClientConfig#instanceName为进程PID
            if (!this.defaultMQProducer.getProducerGroup().equals(MixAll.CLIENT_INNER_PRODUCER_GROUP)) {
   
                this.defaultMQProducer.changeInstanceNameToPID();
            }
                        // 创建一个MQClientInstance,这个是重点,就是它完成了和broker的通信
            // 创建完成后MQClientManager会保存ClientId -> MQClientInstance的映射
            this.mQClientFactory = MQClientManager.getInstance().getAndCreateMQClientInstance(this.defaultMQProducer, rpcHook);
                        // 注册Producer,就是将 ProducerGroup -> DefaultMQProducerImpl 的关系保存到MQClientInstance中
            boolean registerOK = mQClientFactory.registerProducer(this.defaultMQProducer.getProducerGroup(), this);
            if (!registerOK) {
   
                // 如果注册失败,抛异常结束,终止启动
            }
                        // topicPublishInfoTable 初始化一个topic的路由信息,这个CreateTopicKey就是MixAll.AUTO_CREATE_TOPIC_KEY_TOPIC,这个topic和Broker的AutoCreateTopicEnable进行配置使用,后面会详细介绍
            this.topicPublishInfoTable.put(this.defaultMQProducer.getCreateTopicKey(), new TopicPublishInfo());
                        // startFactory这时是true,所以会调用MQClientInstance的start()方法
            if (startFactory) {
   
                mQClientFactory.start();
            }

            log.info("the producer [{}] start OK. se
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值