RocketMQ生产者调用start发送消息原理示例

目录
  • RocketMQ发送消息
  • start()里面究竟做了什么操作
  • 小结

RocketMQ发送消息

我们在使用RocketMQ发送消息时,一般都会使用DefaultMQProducer,类型的代码如下:

DefaultMQProducer producer = new DefaultMQProducer("producer_group");
producer.setNamesrvAddr("42.192.50.8:9876");
try {
    producer.start();
    producer.send(new Message("topic", "ping".getBytes(StandardCharsets.UTF_8)));
} catch (Exception e) {
    e.printStackTrace();
} finally {
    producer.shutdown();
}

上述代码中,在消息发送之前调用了start()方法,如果不调用start()方法,直接发送消息,那么会出现以下报错:

报错消息里面很明显地告知我们,目前这个DefaultMQProducer状态没有准备好,还不能发送消息。为了一探究竟,我们得去看看start()里面究竟做了什么操作呢?

start()里面究竟做了什么操作

我们根据源码一路走下来,可以追踪到DefaultMQProducerImpl.start(final boolean startFactory)这个方法:

public void start(final boolean startFactory) throws MQClientException {
        switch (this.serviceState) {
            case CREATE_JUST:
                this.serviceState = ServiceState.START_FAILED;
                this.checkConfig();
                if (!this.defaultMQProducer.getProducerGroup().equals(MixAll.CLIENT_INNER_PRODUCER_GROUP)) {
                    this.defaultMQProducer.changeInstanceNameToPID();
                }
                // 创建MQClientInstance
                this.mQClientFactory = MQClientManager.getInstance().getOrCreateMQClientInstance(this.defaultMQProducer, rpcHook);
                // 注册Producer到MQClientInstance中
                boolean registerOK = mQClientFactory.registerProducer(this.defaultMQProducer.getProducerGroup(), this);
                if (!registerOK) {
                    this.serviceState = ServiceState.CREATE_JUST;
                    throw new MQClientException("The producer group[" + this.defaultMQProducer.getProducerGroup()
                        + "] has been created before, specify another name please." + FAQUrl.suggestTodo(FAQUrl.GROUP_NAME_DUPLICATE_URL),
                        null);
                }
                this.topicPublishInfoTable.put(this.defaultMQProducer.getCreateTopicKey(), new TopicPublishInfo());
                // 启动MQClientInstance实例
                if (startFactory) {
                    mQClientFactory.start();
                }
                log.info("the producer [{}] start OK. sendMessageWithVIPChannel={}", this.defaultMQProducer.getProducerGroup(),
                    this.defaultMQProducer.isSendMessageWithVIPChannel());
                this.serviceState = ServiceState.RUNNING;
                break;
            case RUNNING:
            case START_FAILED:
            case SHUTDOWN_ALREADY:
                throw new MQClientException("The producer service state not OK, maybe started once, "
                    + this.serviceState
                    + FAQUrl.suggestTodo(FAQUrl.CLIENT_SERVICE_NOT_OK),
                    null);
            default:
                break;
        }

上述代码主要做了以下几点:

1.创建MQClientInstance实例;

2.注册Producer到MQClientInstance实例中;

3.启动MQClientInstance实例;

MQClientInstance实例并不是每次都会创建的,它创建出来也会缓存的MQClientManager中,不过根据源码来看的话,每次创建Producer都会对应创建一个新的MQClientInstance实例,所以一般情况下不建议一个应用服务中重复创建Producer

最终start()方法的关键实现逻辑还是需要进入MQClientInstance.start()中:

    public void start() throws MQClientException {
        synchronized (this) {
            switch (this.serviceState) {
                case CREATE_JUST:
                    this.serviceState = ServiceState.START_FAILED;
                    // 如果namesrv地址为null,那么就需要自己找namesrv地址
                    if (null == this.clientConfig.getNamesrvAddr()) {
                        this.mQClientAPIImpl.fetchNameServerAddr();
                    }
                    // 开启一个请求响应渠道,没猜错的话,应该是netty实现的
                    this.mQClientAPIImpl.start();
                    // 开启定时任务
                    this.startScheduledTask();
                    // 开启拉消息服务
                    this.pullMessageService.start();
                    // 开启负载均衡服务
                    this.rebalanceService.start();
                    // 再开启一个默认生产者,这个生产者不需要启动MQClientInstance实例
                    this.defaultMQProducer.getDefaultMQProducerImpl().start(false);
                    log.info("the client factory [{}] start OK", this.clientId);
                    this.serviceState = ServiceState.RUNNING;
                    break;
                case START_FAILED:
                    throw new MQClientException("The Factory object[" + this.getClientId() + "] has been created before, and failed.", null);
                default:
                    break;
            }
        }
    }

看样子,这才是start()方法真正要做的事情:

1.找namesrv地址,应该是后面需要使用namesrv地址查询对应的broker

2.开启Netty客户端的初始化,包括与namesrv建立信道;另外开启两个定时任务,一个清除列表中过期的请求,第二个就是筛选可用的namesrv服务;

3.开启一些定时任务;包括如果没有设置namesrv地址的话,会从指定站点拉namesrv地址;清除下线broker并发送心跳给所有的broker等工作;

4.因为当前是生产者,所以pullMessageService很快就结束;

5.生产者不需要做负载均衡,所以rebalanceService很快也结束;

6.给默认创建的生产者执行一下start()方法,其实啥也没做;

上述大多数任务都是给消费者使用的,作为生产者,唯一起作用的就是前三步,查找namesrv地址、第二步与namesrv建立通信以及第三步对broker的一些定时清理工作;不过没有发生消息之前,是不会从远程获取任何数据的。所以综上所述,start()方法里面只做了以下两件事情:

1.与namesrv建立通信渠道,它甚至都没有从namesrv获取任何数据;

2.启动一些定时任务,包括清理下线的broker;

小结

虽然在生产者中,start()方法里面真正做的事情比较少,但是却是非常有必要的。发送消息之前,我们没有使用start()方法,导致消息发送失败,是因为生产者与namesrv之间的通信渠道没有建立。

以上就是RocketMQ生产者调用start发送消息原理示例的详细内容,更多关于RocketMQ调用start发送消息的资料请关注我们其它相关文章!

(0)

相关推荐

  • RocketMQ消息发送流程源码剖析

    目录 正文 读源码 1 调用defaultMQProducerImpl.send() 2 设置过期时间 3 执行defaultMQProducerImpl.sendDefaultImpl()方法 sendDefaultImpl是发送消息的核心方法. 1 两个校验 2 获取topic路由信息 3 计算重试次数 4 执行队列选择方法 5 发送消息 正文 就是说,我们打了个比方,把RocketMQ比作码头上的一个小房子,来送孩子登船的家长比作生产者,拉走孩子们的船夫比作消费者,所以,RocketMQ的

  • RocketMQ消息生产者是如何选择Broker示例详解

    目录 前言 从NameServer查询Topic信息 如何选择Broker 小结 前言 在RocketMQ中为,我们创建消息生产者时,只需要设置NameServer地址,消息就能正确地发送到对应的Broker中,那么RocketMQ消息生产者是如何找到Broker的呢?如果有多个Broker实例,那么消息发送是如何选择发送到哪个Broker的呢? 从NameServer查询Topic信息 通过Debug消息发送send()方法,我们最终可以定位到DefaultMQProducerImpl.sen

  • RocketMQ消息队列实现随机消息发送当做七夕礼物

    目录 正文 1 下载并启动RocketMQ 1.1 首先启动name server 1.2 然后启动Broker 2 生产者 3 消费者 正文 都在过情人节,前端的小哥哥们给女朋友画个页面,美美的,写个chrome插件,好看的,俺们后端程序员咋办. 我给媳妇写首诗,哈哈 我决定,把想对媳妇说的,今天发送到一个MQ里边,然后在七夕当天,打开消费者,将这一段话给俺媳妇看.你看,这就是我好久前对你说的话,这就是我们后端程序员的浪漫.当然也可以多发送几个,到时候跟根据topic控制到底发什么,哈哈. 这

  • RocketMQ普通消息实战演练详解

    目录 引言 普通消息同步发送 普通消息异步发送 普通消息单向发送 集群消费模式 广播消费模式 引言 之前研究了RocketMQ的源码,在这里将各种消息发送与消费的demo进行举例,方便以后使用的时候CV. 相关的配置,安装和启动在这篇文章有相关讲解  https://www.jb51.net/article/260237.htm 普通消息同步发送 同步消息是指发送出消息后,同步等待,直到接收到Broker发送成功的响应才会继续发送下一个消息.这个方式可以确保消息发送到Broker成功,一些重要的

  • RocketMQ生产消息与消费消息超详细讲解

    目录 1 RocketMQ简介 2 MQ的常见产品 3 环境搭建 4 单生产者单消费者模式 5 单生产者多消费者模式 5.1默认模式(负载均衡) 5.2广播模式 6 多生产者多消费者模式 1 RocketMQ简介 RocketMQ是阿里开源的一款非常优秀中间件产品,脱胎于阿里的另一款队列技术MetaQ,后捐赠给Apache基金会作为一款孵化技术,仅仅经历了一年多的时间就成为Apache基金会的顶级项目.并且它现在已经在阿里内部被广泛的应用,并且经受住了多次双十一的这种极致场景的压力(2017年的

  • RocketMq 消息重试机制及死信队列详解

    目录 生产者消息重试 消费者消息重试 并发消费 顺序消费 并发消费和顺序消费区别 死信队列 实践出真知 公共部分创建 测试并发消费 并发消费状态 测试顺序消费 顺序消费状态 测试死信队列 死信队列特性 生产者消息重试 消息队列中的消息消费时并不能保证总是成功的,那失败的消息该怎么进行消息补偿呢?这就用到今天的主角消息重试和死信队列了. 有时因为网路等原因生产者也可能发送消息失败,也会进行消息重试,生产者消息重试比较简单,在springboot中只要在配置文件中配置一下就可以了. # 异步消息发送

  • RocketMQ延迟消息简明介绍

    目录 前言 核心属性 RMQ_SYS_SCHEDULE_TOPIC FIRST_DELAY_TIME DELAY_FOR_A_WHILE DELAY_FOR_A_PERIOD delayLevelTable offsetTable 核心方法 queueId2DelayLevel delayLevel2QueueId updateOffset computeDeliverTimestamp start() shutdown() load() parseDelayLevel 前言 场景可以是这样的,

  • 详解RocketMQ 消费端如何监听消息

    目录 前言 流程地图 源码跟踪 核心模块(消息拉取) 拉取流程 拉取消息处理 当pullStatus为FOUND,消息进行提交消费的请求 消息消费进度提交 总结 前言 上一篇文章中我们主要来看RocketMQ消息消费者是如何启动的, 那他有一个步骤是非常重要的,就是启动消息的监听,通过不断的拉取消息,来实现消息的监听,那具体怎么做,让我们我们跟着源码来学习一下~ 流程地图 源码跟踪 这一块的代码比较多,我自己对关键点的一些整理,这个图我画的不是很OK 核心模块(消息拉取) 入口:this.pul

  • RocketMQ生产者调用start发送消息原理示例

    目录 RocketMQ发送消息 start()里面究竟做了什么操作 小结 RocketMQ发送消息 我们在使用RocketMQ发送消息时,一般都会使用DefaultMQProducer,类型的代码如下: DefaultMQProducer producer = new DefaultMQProducer("producer_group"); producer.setNamesrvAddr("42.192.50.8:9876"); try { producer.sta

  • Python调用飞书发送消息的示例

    一.创建飞书机器人 自定义飞书机器人操作步骤,具体详见飞书官方文档:<机器人 | 如何在群聊中使用机器人?> 二.调用飞书发送消息 自定义机器人添加完成后,就能向其 webhook 地址发送 POST 请求,从而在群聊中推送消息了.支持推送的消息格式有文本.富文本.图片消息,也可以分享群名片等. 参数msg_type代表消息类型,可传入:text(文本)/ post(富文本)/ image(图片)/ share_chat(分享群名片)/ interactive(消息卡片),可参照飞书接口文档:

  • laravel框架使用阿里云短信发送消息操作示例

    本文实例讲述了laravel框架使用阿里云短信发送消息操作.分享给大家供大家参考,具体如下: 最新需要用到发送短信的功能,所以就在网上搜索一些写好的扩展. 扩展地址: https://github.com/MissMyCat/aliyun-sms 通过composer安装: composer require mrgoon/aliyun-sms dev-master 在 config/app.php 中 providers 加入: Mrgoon\AliSms\ServiceProvider::cl

  • c# rabbitmq 简单收发消息的示例代码

    发布消息:(生产者) /// <summary> /// 发送消息 /// </summary> /// <param name="queue">队列名</param> /// <param name="message">消息内容</param> private static void PublishInfo(string queue, string message) { try { var f

  • Python3调用微信企业号API发送文本消息代码示例

    本文主要向大家分享了Python3调用微信企业号API发送文本消息示例的有关代码,具体如下: #!/usr/bin/env python # -*- coding:utf-8 -*- import urllib.request import json import sys import logging touser = '@all' agentid = 0 corpid = 'wx5aef2da956514535' corpsecret = 'Co17m_OPlvE8Q4P2RKKwtq5oIA

  • RocketMQ事务消息原理与使用详解

    目录 一.RocketMQ事务消息概要 二.RocketMQ事务消息使用案例 (1).定义消息监听器 (2).定义消息生产者 (3).定义消息消费者 (4).观察生产者控制台输出 (5).观察消费者控制台输出 三.RocketMQ事务消息原理 四.RocketMQ事务消息使用限制 一.RocketMQ事务消息概要 RocketMQ事务消息(Transactional Message)是指应用本地事务和发送消息操作可以被定义到全局事务中,要么同时成功,要么同时失败.RocketMQ的事务消息提供类

  • 微服务架构设计RocketMQ进阶事务消息原理详解

    目录 前言 RocketMQ事务流程概要 RocketMQ事务流程关键 实现 基础配置 引入组件 添加配置 发送半消息 执行本地事务与回查 消费消息 测试 总结 前言 分布式消息选型的时候是否支持事务消息是一个很重要的考量点,而目前只有RocketMQ对事务消息支持的最好.今天我们来唠唠如何实现RocketMQ的事务消息! Apache RocketMQ在4.3.0版中已经支持分布式事务消息,这里RocketMQ采用了2PC的思想来实现了提交事务消息,同时增加一个补偿逻辑来处理二阶段超时或者失败

  • iOS消息发送和转发示例详解

    前言 Objective-C 是一门动态语言,它将很多静态语言在编译和链接时期做的事情,放到了运行时来处理.之所以能具备这种特性,离不开 Runtime 这个库.Runtime 很好的解决了如何在运行时期找到调用方法这样的问题.下面话不多说了,来一起学习学习吧. 消息发送 在 Objective-C 中,方法调用称为向对象发送消息: // MyClass 类 @interface MyClass: NSObject - (void)printLog; @end @implementation M

  • 使用Kotlin+RocketMQ实现延时消息的示例代码

    一. 延时消息 延时消息是指消息被发送以后,并不想让消费者立即拿到消息,而是等待指定时间后,消费者才拿到这个消息进行消费. 使用延时消息的典型场景,例如: 在电商系统中,用户下完订单30分钟内没支付,则订单可能会被取消. 在电商系统中,用户七天内没有评价商品,则默认好评. 这些场景对应的解决方案,包括: 轮询遍历数据库记录 JDK 的 DelayQueue ScheduledExecutorService 基于 Quartz 的定时任务 基于 Redis 的 zset 实现延时队列. 除此之外,

  • java开发RocketMQ生产者高可用示例详解

    目录 引言 1 消息 1.1 topic 1.2 Body 1.3 tag 1.4 key 1.5 延迟级别 2 生产者高可用 2.1 客户端保证生产者高可用 2.1.1 重试机制 2.1.2 客户端容错 2.2 Broker端保证生产者高可用 引言 前边两章说了点基础的,从这章开始,我们挖挖源码.看看RocketMQ是怎么工作的. 首先呢,这个生产者就是送孩子去码头的家长,孩子们呢,就是消息了. 我们看看消息孩子们都长啥样. 1 消息 public class Message implemen

随机推荐