一、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之间用分号连接。
将官方提供的代码拷贝到创建好的项目中,最终目录如下
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
b)、第二步设置nameServer地址
c)、第三步设置消息体指定:topic、tag、消息体
Message msg = new Message("TopicTest" /* Topic */, "TagA" /* Tag */, ("Hello RocketMQ " + i).getBytes(RemotingHelper.DEFAULT_CHARSET) /* Message body */ );
运行main方法就可以将消息发送到RocketMQ,看运行返回状态
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();
执行结果
通过消费详情,可以看到消息已经全部消费
3.1.2 异步发送消息
3.1.2.1 发送消息
这个示例有个比较有趣的地方就是引入了一个countDownLatch来保证所有消息回调方法都执行完了再关闭Producer。 所以从这里可以看出,RocketMQ的Producer也是一个服务端,在往Broker发送消息的时候也要作为服务端提供服务
通过通过Producer.send来发送消息,不同的是多了 new SendCallback()回调函数,这样发送的时候不关心消息是否成功,当消息成功的时候回调到onSuccess()方法,失败异常的时候回调onException()方法
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。