使用RocketMQ原生API实现消息的发送

366 阅读4分钟

一、RocketMQ原生API使用

​ 使用RocketMQ的原生API开发是最简单也是目前看来最牢靠的方式。这里我们用SpringBoot来搭建一系列消息生产者和消息消费者,来访问我们之前搭建的RocketMQ集群。

1、测试环境搭建

 首先创建一个基于Maven的SpringBoot工程,引入如下依赖(后面使用官方提供的example,因此需要将相关的包都导入):

<dependency>
    <groupId>org.apache.rocketmq</groupId>
    <artifactId>rocketmq-client</artifactId>
    <version>4.9.1</version>
</dependency>
<dependency>
    <groupId>org.apache.rocketmq</groupId>
    <artifactId>rocketmq-acl</artifactId>
    <version>4.9.1</version>
</dependency>

<dependency>
    <groupId>org.apache.rocketmq</groupId>
    <artifactId>rocketmq-openmessaging</artifactId>
    <version>4.9.1</version>
</dependency>

<dependency>
    <groupId>org.apache.rocketmq</groupId>
    <artifactId>rocketmq-srvutil</artifactId>
    <version>4.9.1</version>
</dependency>
<dependency>
    <groupId>io.jaegertracing</groupId>
    <artifactId>jaeger-core</artifactId>
    <version>1.6.0</version>
</dependency>
<dependency>
    <groupId>io.jaegertracing</groupId>
    <artifactId>jaeger-client</artifactId>
    <version>1.6.0</version>
</dependency>

​ 另外还与一些依赖,例如openmessage、acl等扩展功能还需要添加对应的依赖。具体可以参见RocketMQ源码中的example模块。在RocketMQ源码包中的example模块提供了非常详尽的测试代码,也可以拿来直接调试。

RocketMQ的官网上有很多经典的测试代码,这些代码虽然依赖的版本比较老,但是还是都可以运行的。所以我们还是以官网上的顺序进行学习。

​ 但是在调试这些代码的时候要注意一个问题:这些测试代码中的生产者和消费者都需要依赖NameServer才能运行,只需要将NameServer指向我们自己搭建的RocketMQ集群,而不需要管Broker在哪里,就可以连接我们自己的自己的RocketMQ集群。而RocketMQ提供的生产者和消费者寻找NameServer的方式有两种:

​ 1、在代码中指定namesrvAddr属性。例如:

consumer.setNamesrvAddr("192.168.253.131:9876");

​ 2、通过NAMESRV_ADDR环境变量来指定。多个NameServer之间用分号连接。

将官方提供的代码拷贝到创建好的项目中,最终目录如下

image.png

2、RocketMQ的编程模型

​ 然后RocketMQ的生产者和消费者的编程模型都是有个比较固定的步骤的,掌握这个固定的步骤,对于我们学习源码以及以后使用都是很有帮助的。

  • 消息发送者的固定步骤

1.创建消息生产者producer,并制定生产者组名

2.指定Nameserver地址

3.启动producer

4.创建消息对象,指定主题Topic、Tag和消息体

5.发送消息

6.关闭生产者producer

  • 消息消费者的固定步骤

1.创建消费者Consumer,制定消费者组名

2.指定Nameserver地址

3.订阅主题Topic和Tag

4.设置回调函数,处理消息

5.启动消费者consumer

3、RocketMQ的消息样例

3.1 基本样例

我们使用消息生产者分别通过三种方式发送消息,同步发送、异步发送以及单向发送

同步发送:发送的时候同步等待消息结果

异步发送:发送的时候不同步等待消息发送结果、消息执行完之后进行回调

单选发送:不关心消息发送是否成功,没有返回结果

3.1.1 同步发送消息

example\src\main\java\org\apache\rocketmq\example\quickstart
3.1.1.1 发送消息

a)、第一步修改group

image.png

b)、第二步设置nameServer地址

image.png

c)、第三步设置消息体指定:topic、tag、消息体

Message msg = new Message("TopicTest" /* Topic */, "TagA" /* Tag */, ("Hello RocketMQ " + i).getBytes(RemotingHelper.DEFAULT_CHARSET) /* Message body */ );

运行main方法就可以将消息发送到RocketMQ,看运行返回状态

image.png

3.1.1.2 接收消息

a)、第一步修改group组

DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("baseGroup");

b)、第二步设置nameServer

consumer.setNamesrvAddr("192.168.253.131:9876");

c)、设置消息的消费位置

consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET);

d)、设置消息消费的topic及tag的过滤条件

consumer.subscribe("TopicTest", "*");

e)、获得消息

通过设置:ConsumeConcurrentlyStatus.CONSUME_SUCCESS,可以告诉MQ消息已消费,这样就不会再向其他消费者推送,类似RabbitMQ的ACK机制

consumer.registerMessageListener(new MessageListenerConcurrently() { 
    @Override 
    public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs, ConsumeConcurrentlyContext context) {
        System.out.printf("%s Receive New Messages: %s %n", Thread.currentThread().getName(), msgs); 
        return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; 
    } 
 });

f)、启动消费

consumer.start();

执行结果

image.png

通过消费详情,可以看到消息已经全部消费

image.png

3.1.2 异步发送消息

3.1.2.1 发送消息

这个示例有个比较有趣的地方就是引入了一个countDownLatch来保证所有消息回调方法都执行完了再关闭Producer。 所以从这里可以看出,RocketMQ的Producer也是一个服务端,在往Broker发送消息的时候也要作为服务端提供服务

通过通过Producer.send来发送消息,不同的是多了 new SendCallback()回调函数,这样发送的时候不关心消息是否成功,当消息成功的时候回调到onSuccess()方法,失败异常的时候回调onException()方法

image.png

3.1.3 单向发送消息

3.1.3.1 发送消息

通过sendOneway(mgs)就可以发送没有返回值的单向消息

producer.sendOneway(msg);

3.1.4 使用消费者消费消息。

​ 消费者消费消息有两种模式,一种是消费者主动去Broker上拉取消息的拉模式,另一种是消费者等待Broker把消息推送过来的推模式。

​ 拉模式的样例见:org.apache.rocketmq.example.simple.PullConsumer

​ 推模式的样例见:org.apache.rocketmq.example.simple.PushConsumer

通常情况下,用推模式比较简单。实际上RocketMQ的推模式也是由拉模式封装出来的。DefaultMQPullConsumerImpl这个消费者类已标记为过期,但是还是可以使用的。替换的类是DefaultLitePullConsumerImpl。