1. 添加rocketmq依赖
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-client</artifactId>
<version>4.1.0-incubating</version>
</dependency>
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-common</artifactId>
<version>4.1.0-incubating</version>
</dependency>
2. rocketmq配置
#消费者的组名
apache.rocketmq.consumer.PushConsumer=orderConsumer
#生产者的组名
apache.rocketmq.producer.producerGroup=Producer
#nameserver地址,虚拟机的地址加 rocketmq端口号,需要linux开放该端口号
apache.rocketmq.namesrvAddr=192.168.0.126:9876
# 修改端口号,rocketmq 可视化控制台端口默认为8080
server.port=8081
3.生产者代码
package com.example.springbootdemo5.rocketmq;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.springframework.beans.PropertyValue;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
/**
* rocketmq 消息生产者
*/
@Component
public class MsgProducer {
/**
* 生产者组名
*/
@Value("${apache.rocketmq.producer.producerGroup}")
private String producerGroup;
/**
* nameserver地址
*/
@Value("${apache.rocketmq.namesrvAddr}")
private String namesrvAddr;
/**
* 发送消息使用
*/
private DefaultMQProducer producer;
public DefaultMQProducer getProducer(){
return this.producer;
}
/**
* 使用@PostConstruct注解进行初始化,当一个类加载进service容器之前,会调用标记了@PostConstruct注解的方法进行一些资源的初始化操作; 一般应该放在servletContext容器初始化时调用该方法,可以放在自定义监听器里面实现
*/
@PostConstruct
public void init(){
producer=new DefaultMQProducer(producerGroup);
// 指定nameserve,多个地址以分号隔开
producer.setNamesrvAddr(namesrvAddr);
//
producer.setVipChannelEnabled(false);
try {
//Producer使用前必须初始化,且只能初始化一次
producer.start();
} catch (Exception e){
e.printStackTrace();
}
// producer.shutdown();
}
}
Controller代码:
package com.example.springbootdemo5.rocketmq.controller;
import com.example.springbootdemo5.rocketmq.MsgProducer;
import org.apache.rocketmq.client.exception.MQBrokerException;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.remoting.common.RemotingHelper;
import org.apache.rocketmq.remoting.exception.RemotingException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.UnsupportedEncodingException;
@RestController
@RequestMapping("/api/v1")
public class RocketMQController {
@Autowired
private MsgProducer producer;
/**
* 模拟微信支付成功后回调/order接口,order接口将消息内容发送到rocketmq中,由消费者慢慢去消费,提高并发支付能力!
* @param msg 要发送的消息,如支付信息
* @param tag 消息二级分类
* @return
* @throws UnsupportedEncodingException
* @throws InterruptedException
* @throws RemotingException
* @throws MQClientException
* @throws MQBrokerException
*/
@RequestMapping("/orders")
public Object order(String msg,String tag) throws UnsupportedEncodingException, InterruptedException, RemotingException, MQClientException, MQBrokerException {
Message message = new Message("testTopic", tag, msg.getBytes(RemotingHelper.DEFAULT_CHARSET));
SendResult result = producer.getProducer().send(message);
System.out.println("发送响应:MsgId:" + result.getMsgId() + ",发送状态:" + result.getSendStatus());
return "success";
}
}
消费者代码:
package com.example.springbootdemo5.rocketmq;
import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus;
import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.common.consumer.ConsumeFromWhere;
import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.remoting.common.RemotingHelper;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.io.UnsupportedEncodingException;
@Component
public class MsgConsumer {
@Value("${apache.rocketmq.consumer.PushConsumer}")
private String comsumerGroup;
@Value("${apache.rocketmq.namesrvAddr}")
private String namesrvAddr;
/**
* 初始化消费者
*/
@PostConstruct
public void inintConsumer() {
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer(comsumerGroup);
consumer.setNamesrvAddr(namesrvAddr);
try {
// 设置consumer所订阅的topic和tag, *表示订阅所有tag
consumer.subscribe("testTopic", "*");
// 默认策略,从该队列最尾开始消费,跳过历史消息
consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_LAST_OFFSET);
consumer.registerMessageListener((MessageListenerConcurrently) (list, context) -> {
for (MessageExt messageExt : list) {
try {
// 输出消息内容
System.out.println("messageExt:" + messageExt);
String messageBody = new String(messageExt.getBody(), RemotingHelper.DEFAULT_CHARSET);
System.out.println("消费响应:" + messageExt.getMsgId() + ",messageBody:" + messageBody);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
// 消费消息失败,稍后重试
return ConsumeConcurrentlyStatus.RECONSUME_LATER;
}
}
// 告诉topic消息消费成功,topic会将消息移除
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
});
consumer.start();
} catch (MQClientException e) {
e.printStackTrace();
}
}
}
启动虚拟机上的rocketmq:
(1)启动nameserver
[itcast@lch bin]$ pwd
/usr/local/messageQueue/rocketmq/bin
[itcast@lch bin]$ nohup sh mqnamesrv &
[1] 3403
[itcast@lch bin]$ nohup: ignoring input and appending output to `nohup.out'
^C
[itcast@lch bin]$ cat nohup.out
(2) 启动broker
[itcast@lch bin]$ nohup sh mqbroker -n 127.0.0.1:9876 &
启动rocketmq控制台:找到 rocketmq-console-ng-1.0.1.jar ,使用java -jar 命令启动
D:\CodeFromGit\rocketmq-externals-master\rocketmq-externals-master\rocketmq-console\target>java -jar rocketmq-console-ng-1.0.1.jar
linux防火墙开放9876端口:
[root@lch bin]# /sbin/iptables -I INPUT -p tcp --dport 9876 -j ACCEPT
[root@lch bin]# /etc/init.d/iptables save
iptables: Saving firewall rules to /etc/sysconfig/iptables:[ OK ]
[root@lch bin]#
启动访问http://localhost:8081/api/v1/orders?msg=testrocketmq&tag=pay,报错,原因如下:
https://bbs.csdn.net/topics/392168188 需要同时开放端口9876 10911 10909 10912才可以连接
开放10911 10909 10912 端口后继续访问:
http://localhost:8081/api/v1/orders?msg=testrocketmq&tag=pay
在rocketmq控制台,可以看到有一条消息了:
idea控制台打印:
发送响应:MsgId:C0A8008057A818B4AAC21E8288390000,发送状态:SEND_OK
messageExt:MessageExt [queueId=2, storeSize=173, queueOffset=0, sysFlag=0, bornTimestamp=1599401471034, bornHost=/192.168.0.128:60992, storeTimestamp=1599401471568, storeHost=/192.168.0.126:10911, msgId=C0A8007E00002A9F0000000000000000, commitLogOffset=0, bodyCRC=376694888, reconsumeTimes=0, preparedTransactionOffset=0, toString()=Message [topic=testTopic, flag=0, properties={
MIN_OFFSET=0, MAX_OFFSET=1, CONSUME_START_TIME=1599401476086, UNIQ_KEY=C0A8008057A818B4AAC21E8288390000, WAIT=true, TAGS=pay}, body=12]]
消费响应:C0A8008057A818B4AAC21E8288390000,messageBody:testrocketmq