前言
本章旨在教会你怎么在springboot环境下简单使用rocketMQ,所以对于接下来的代码,大部分不用深究,直接CV大法就完事~
GitHub传送门——rocket-demo
1 引入依赖
首先是springboot的依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.6.RELEASE</version>
</parent>
然后引入rocketMQ依赖,注意,这里要和自己服务器上的rocketMQ版本一致
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-client</artifactId>
<version>4.5.1</version>
</dependency>
2 配置类
public class JmsConfig {
public static String NAME_SERVER = "xxx:9876";
public static String TOPIC_EASY = "topic_easy";
}
3 创建生产者
// (单例对象降低开销)
@Component
public class EasyProduce {
private DefaultMQProducer producer;
public EasyProduce() throws Exception {
producer = new DefaultMQProducer("easy-rocket");
producer.setNamesrvAddr(JmsConfig.NAME_SERVER);
//不开启vip通道 开通口端口会减2
producer.setVipChannelEnabled(false);
producer.start();
}
public DefaultMQProducer getProducer() {
return producer;
}
public void setProducer(DefaultMQProducer producer) {
this.producer = producer;
}
}
4 创建消费者
public class EasyConsumer {
private DefaultMQPushConsumer consumer;
public EasyConsumer() throws Exception {
consumer = new DefaultMQPushConsumer("easy-rocket");
consumer.setNamesrvAddr(JmsConfig.NAME_SERVER);
consumer.subscribe(JmsConfig.TOPIC_EASY, "easy-message-1");
consumer.registerMessageListener((MessageListenerConcurrently) (list, consumeConcurrentlyContext) -> {
for (Message msg : list) {
//消费者获取消息 这里只输出 不做后面逻辑处理
System.out.println("---------消费消息:" + LocalTime.now());
String body = new String(msg.getBody(), StandardCharsets.UTF_8);
System.out.println(body);
}
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
});
consumer.start();
}
public static void main(String[] args) throws Exception {
new EasyConsumer();
}
}
5 创建测试代码
@RestController
public class RocketController {
@Autowired
EasyProduce produce;
@GetMapping("/test")
public String test() throws Exception {
DefaultMQProducer mqProducer = produce.getProducer();
//创建生产信息
for (int i = 0; i < 1; i++) {
Message message = new Message(JmsConfig.TOPIC_EASY, "easy-message-1", ("easy message:" + i).getBytes());
SendResult send = mqProducer.send(message);
System.out.println("---------生产消息:" + LocalTime.now().toString());
System.out.println(send.toString());
}
return "ok";
}
}
6 出现bug
本地启动我们的服务器,然后再启动消费者,请求test之后会发现,程序并没有按照我们预期的进行,而是给我们抛出了如下异常,很明显是没有连上RocketMQ
但是我们明明都打开防火墙了,为什么会连不上呢?打开8181控制台,在集群选项下,我们可以看到broker-a是内网地址,难怪连不上
7 解决问题
修改broker的地址就好了,进入docker容器,修改broker的配置文件:
docker exec -it rmqbroker bash
cd /etc/rocketmq
vi broker.conf
加上如下配置,重启容器,解决问题
brokerIP1=你的服务器IP地址
autoCreateTopicEnable=true
有些读者可能会有疑惑:为什么第一行配置的名字叫"brokerIP1"?那我能不能叫"brokerIP2"呢?
事实上还真有brokerIP2这个配置:
1. brokerIP1:当前broker监听的IP
2. brokerIP2:存在broker主从架构时,当broker主节点上配置了brokerIP2的话,broker从节点会连接主节点配置的brokerIP2来同步。
其中,第一行是指定了地址,那第二行又是用来干嘛的呢?
不加第二行配置的话,你会愉快的发现这时候程序给你报第二个异常:
No route info of this topic, xxx
从字面意思上就能看出,没办法路由到你指定的topic,在控制台我们也能看到,的确没有我们代码中指定的这个topic
聪明的读者这时候再去看看第二行配置是不是能理解它的作用了?没错,就是支持在你broker上不存在这个topic时自动创建(为什么默认是不支持自动创建呢?读者可以自己思考一下,后续会讲解)
到这里我们一个简单的demo就搭建好并且能够使用了,下一章,我们稍稍深入一点来理解RocketMQ的概念及其架构设计