RocketMQ--消息生产者的启动以及消息的发送

  先看一个官网提供的rockermq发送同步消息的案例代码,以这个发送消息的案例代码为线索来探究rockermq发送消息到brocker的流程

public class SyncProducer {
    public static void main(String[] args) throws Exception {
        //Instantiate with a producer group name.
        DefaultMQProducer producer = new
            DefaultMQProducer("please_rename_unique_group_name");
        // Specify name server addresses.
        producer.setNamesrvAddr("localhost:9876");
        //Launch the instance.
        producer.start();
        for (int i = 0; i < 100; i++) {
            //Create a message instance, specifying topic, tag and message body.
            Message msg = new Message("TopicTest" /* Topic */,
                "TagA" /* Tag */,
                ("Hello RocketMQ " +
                    i).getBytes(RemotingHelper.DEFAULT_CHARSET) /* Message body */
            );
            //Call send message to deliver message to one of brokers.
            SendResult sendResult = producer.send(msg);
            System.out.printf("%s%n", sendResult);
        }
        //Shut down once the producer instance is not longer in use.
        producer.shutdown();
    }
}

一、创建DefaultMQProducer对象,这里由于是发送同步消息,所以调用的是生产者一个参数的构造函数,参数为生成者的group名称,如果是异步则调用带有回调钩子函数的构造函数。构造函数中主要做的事情就是初始化了生产者的具体实现类,并且创建了一个异步发送消息任务的线程池。

生产者的核心属性:

#DefaultMQProducer
    /**
     * topic的默认队列个数
     */
    private volatile int defaultTopicQueueNums = 4;

    /**
     * 消息发送的超时时间,默认是3秒
     */
    private int sendMsgTimeout = 3000;

    /**
     * 当消息大于4k的时候进行消息压缩
     */
    private int compressMsgBodyOverHowmuch = 1024 * 4;

    /**
     * 同步消息默认消息失败之后的重试次数,所以消息失败的情况下,默认最多发送3次,这会导致消息的重复,需要开发人员进行处理
     */
    private int retryTimesWhenSendFailed = 2;

    /**
     * 异步消息默认失败之后重试次数,也会导致消息重复发送
     */
    private int retryTimesWhenSendAsyncFailed = 2;

    /**
     * Indicate whether to retry another broker on sending failure internally.
     */
    private boolean retryAnotherBrokerWhenNotStoreOK = false;

    /**
     * Maximum allowed message size in bytes.
     */
    private int maxMessageSize = 1024 * 1024 * 4; // 4M

二、设置nameserver地址,调用start()方法启动生产者。查看具体的启动代码,初次启动的启动状态为CREATE_JUST

2.1 检查配置,这里主要是检查group名称是否合法

2.2 主要看一下getOrCreateMQClientInstance方法,这里是创建MQClientlnstance 实例,MQClientInstance封装了rocketMq网络处理API,是消息生产者( Producer )、消息消费者
( Consumer )与NameServ町、Broker 打交道的网络通道。

 先给MQClientInstance创建一个clientId,先从factoryTable中,如果没有则创建并将实例放入到factoryTable中,这样可以保证启动一个生产者的时候只有一个MQClientInstance。创建完成之后,将MQClientInstance以group为key值放入到producerTable中,如果之前这个group名称已经创建过MQClientInstance实例则抛出错误。

2.3 在topicPublishInfoTable初始化当前topic的路由信息。此时的TopicPublishInfo还没有具体的路由信息。TopicPublishInfo是生产者消息发送到brocker所依赖路由的主要依据。与NameServer的路由信息管理RouteInfoManager是相互同步的。看一下路由表中的主要信息TopicPublishInfo。

 

TopicRouteData中的详细信息

2.4  启动消息生产者,并且启动定时任务,定时拉取nameserver地址,从broker拉取消息的服务和均衡消息队列服务,负责分配消费者可消费的消息队列,生产者的pullMessageService以及rebalanceService由于启动的是一个deamon线程,并且通过源码查看,任务队列中并没有任务,而且rocketmq的负载均衡是在客户端自己做的,所以这里我不大了解到底是做了什么,待进一步查看,这里就不看了。

三、消息的发送

3.1 创建消息Message,查看消息中的主要内容

3.2 消息的发送,先进行消息的检查,查看消息的topic是否合法,以及消息的内容是否合法(消息长度之类的)最终调用DefaultMQProducerImpl#sendDefaultImpl方法来发送消息。这里查看消息发送的部分主要代码内容

 3.2.1 选择消息发送的队列

每次选择的发送队列都是上次选择队列的id加1,然后通过hash算法选择一个队列,这样可以是的消息均匀的分布到每个队列。选择队列之后判断队列所在的brocker是否正常,如果不正常则选择另外一个队列,如果都不正常,则在所有不正常的broker列表中选择最后一个进行发送。

3.2.2 选择broker之后最后通过brokerName在brokerAddrTable获取broker的ip加端口信息,创建请求,然后发送消息请求

总结:生产者主要是通过从nameserver中定时获取路由信息,并将信息维护在topicPublishInfoTable中,然后每次发送消息的时候,从这个路由表中获取具体发送的broker以及队列信息,并且有容错机制以及重试机制。这里只是简单的分析了一下同步消息的发送,至于异步消息,事物消息都没有分析

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值