springboot依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
rocketmq客户端依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-client</artifactId>
<version>4.7.1</version>
</dependency>
消费者
// 指定消费组名为my-consumer
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("my-consumer1");
// 配置namesrv地址
consumer.setNamesrvAddr("139.155.54.93:9876");
// 订阅topic:myTopic001 下的全部消息(因为是*,*指定的是tag标签,代表全部消息,不进行任何过滤)
consumer.subscribe("myTopic001", "*");
// consumer.subscribe("orderTopic", "order1");
// 注册监听器,进行消息消费。
consumer.registerMessageListener(new MessageListenerConcurrently() {
@Override
public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs, ConsumeConcurrentlyContext consumeConcurrentlyContext) {
for (MessageExt msg : msgs) {
String str = new String(msg.getBody());
// 输出消息内容
System.out.println(str);
}
// 默认情况下,这条消息只会被一个consumer消费,这叫点对点消费模式。也就是集群模式。
// ack确认
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
}
});
// 启动消费者
consumer.start();
System.out.println("Consumer start");
同步消息
// 指定生产组名为my-producer
DefaultMQProducer producer = new DefaultMQProducer("my-producer");
// 配置namesrv地址
producer.setNamesrvAddr("139.155.54.93:9876");
// 启动Producer
producer.start();
for (int i = 0; i < 10; i++) {
// 创建消息对象,topic为:myTopic001,消息内容为:hello world
Message message = new Message("orderTopic","order1","order-key", ("hello!" + i).getBytes());
// 发送消息到mq,同步的
SendResult result = producer.send(message);
System.out.println("发送消息成功!result is : " + result);
}
// 关闭Producer
producer.shutdown();
System.out.println("生产者 shutdown!");
异步消息
// 指定生产组名为my-producer
DefaultMQProducer producer = new DefaultMQProducer("my-producer");
// 配置namesrv地址
producer.setNamesrvAddr("139.155.54.93:9876");
// 启动Producer
producer.start();
// 创建消息对象,topic为:myTopic001,消息内容为:hello world async
Message msg = new Message("myTopic001", "hello world async".getBytes());
// 进行异步发送,通过SendCallback接口来得知发送的结果
producer.send(msg, new SendCallback() {
// 发送成功的回调接口
@Override
public void onSuccess(SendResult sendResult) {
System.out.println("发送消息成功!result is : " + sendResult);
}
// 发送失败的回调接口
@Override
public void onException(Throwable throwable) {
throwable.printStackTrace();
System.out.println("发送消息失败!result is : " + throwable.getMessage());
}
});
Thread.sleep(3000);
producer.shutdown();
System.out.println("生产者 shutdown!");
单向消息
// 指定生产组名为my-producer
DefaultMQProducer producer = new DefaultMQProducer("my-producer");
// 配置namesrv地址
producer.setNamesrvAddr("139.155.54.93:9876");
// 启动Producer
producer.start();
// 创建消息对象,topic为:myTopic001,消息内容为:hello world oneway
Message msg = new Message("myTopic001", "hello world oneway".getBytes());
// 效率最高,因为oneway不关心是否发送成功,我就投递一下我就不管了。所以返回是void
producer.sendOneway(msg);
System.out.println("投递消息成功!,注意这里是投递成功,而不是发送消息成功哦!因为我sendOneway也不知道到底成没成功,我没返回值的。");
producer.shutdown();
System.out.println("生产者 shutdown!");
批量消息
// 指定生产组名为my-producer
DefaultMQProducer producer = new DefaultMQProducer("my-producer");
// 配置namesrv地址
producer.setNamesrvAddr("139.155.54.93:9876");
// 启动Producer
producer.start();
String topic = "myTopic001";
String topic2 = "myTopic002";
// 创建消息对象,topic为:myTopic001,消息内容为:hello world1/2/3
Message msg1 = new Message(topic, "hello world1".getBytes());
Message msg2 = new Message(topic, "hello world2".getBytes());
Message msg3 = new Message(topic, "hello world3".getBytes());
// 创建消息对象的集合,用于批量发送
List<Message> msgs = new ArrayList<>();
msgs.add(msg1);
msgs.add(msg2);
msgs.add(msg3);
// 批量发送的api的也是send(),只是他的重载方法支持List<Message>,同样是同步发送。
SendResult result = producer.send(msgs);
System.out.println("发送消息成功!result is : " + result);
// 关闭Producer
producer.shutdown();
System.out.println("生产者 shutdown!");
事务消息
TransactionMQProducer producer = new TransactionMQProducer("my-transation-producer");
producer.setNamesrvAddr("139.155.54.93:9876");
producer.setTransactionListener(new TransactionListener() {
/**
* 本地事务方法
* @param message
* @param arg
* @return
*/
@Override
public LocalTransactionState executeLocalTransaction(Message message, Object arg) {
LocalTransactionState state = null;
//msg-1返回COMMIT_MESSAGE
if(message.getKeys().equals("msg-1")){
state = LocalTransactionState.COMMIT_MESSAGE;
}
//msg-2返回ROLLBACK_MESSAGE
else if(message.getKeys().equals("msg-2")){
state = LocalTransactionState.ROLLBACK_MESSAGE;
}else{
//这里返回unknown的目的是模拟执行本地事务突然宕机的情况(或者本地执行成功发送确认消息失败的场景)
state = LocalTransactionState.UNKNOW;
}
System.out.println(message.getKeys() + ",state:" + state);
return state;
}
/**
* 定时回查方法
* @param messageExt
* @return
*/
@Override
public LocalTransactionState checkLocalTransaction(MessageExt messageExt) {
if (null != messageExt.getKeys()) {
switch (messageExt.getKeys()) {
case "msg-3":
System.out.println("msg-3 unknow");
return LocalTransactionState.UNKNOW;
case "msg-4":
System.out.println("msg-4 COMMIT_MESSAGE");
return LocalTransactionState.COMMIT_MESSAGE;
case "msg-5":
//查询到本地事务执行失败,需要回滚消息。
System.out.println("msg-5 ROLLBACK_MESSAGE");
return LocalTransactionState.ROLLBACK_MESSAGE;
}
}
return LocalTransactionState.COMMIT_MESSAGE;
}
});
producer.start();
//模拟发送5条消息
for (int i = 1; i < 6; i++) {
try {
Message msg = new Message("transactionTopic", null, "msg-" + i, ("测试,这是事务消息! " + i).getBytes());
producer.sendMessageInTransaction(msg, null);
} catch (Exception e) {
e.printStackTrace();
}
}
顺序消息
DefaultMQProducer producer = new DefaultMQProducer("my-order-producer");
producer.setNamesrvAddr("139.155.54.93:9876");
producer.start();
for (int i = 0; i < 10; i++) {
Message message = new Message("orderTopic","order2","order-key", ("hello!" + i).getBytes());
System.out.println("hello!" + i);
producer.send(
// 要发的那条消息
message,
// queue 选择器 ,向 topic中的哪个queue去写消息
new MessageQueueSelector() {
// 手动 选择一个queue
@Override
public MessageQueue select(
// 当前topic 里面包含的所有queue
List<MessageQueue> mqs,
// 具体要发的那条消息
Message msg,
// 对应到 send() 里的 args,也就是2000前面的那个0
// 实际业务中可以把0换成实际业务系统的主键,比如订单号啥的,然后这里做hash进行选择queue等。
// 能做的事情很多,我这里做演示就用第一个queue,所以不用arg。
Object arg) {
// 向固定的一个queue里写消息,比如这里就是向第一个queue里写消息
MessageQueue queue = mqs.get(0);
// 选好的queue
return queue;
}
},
// 自定义参数:0
// 2000代表2000毫秒超时时间
0, 2000);
}
定时消息(延迟消息)
延迟级别
“1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h”
设置延迟队列的level 如
message.setDelayTimeLevel(2);//延迟5秒
message.setDelayTimeLevel(5);//5表示延迟一分钟
// 指定生产组名为my-producer
DefaultMQProducer producer = new DefaultMQProducer("my-producer");
// 配置namesrv地址
producer.setNamesrvAddr("139.155.54.93:9876");
// 启动Producer
producer.start();
// 创建消息对象,topic为:myTopic001,消息内容为:hello world
Message message = new Message("myTopic001", "schedule", "schedule-key", ("Hello schedule!").getBytes());
//设置延迟队列的level,5表示延迟一分钟
message.setDelayTimeLevel(5);
// 发送消息到mq,同步
SendResult result = producer.send(message);
System.out.println("发送消息成功!result is : " + result);
// 关闭Producer
producer.shutdown();
System.out.println("生产者 shutdown!");
代码地址
https://github.com/JsonTom888/MQProject/tree/master/rocketmq