从安装到测试成功,花了好几天的时间。在网上也查了很多的资料。但是很多时候都是徒劳的。第一次学习MQ,想把这些天学到的东西总结一下。也很欢迎各位大神、大牛来评论。
首先,我们花点时间介绍一下RocketMQ的性能及一些角色。个人觉得这是很有必要的。其实,不管是什么MQ,他们都是MQ,只要是MQ,他都具有一下特点:
如上图所示,整体可以分成4个角色,分别是:Producer,Consumer,Broker以及NameServer;
可以理解为是消息队列的协调者,Broker向它注册路由信息,同时Client向其获取路由信息,如果使用过Zookeeper,就比较容易理解了,但是功能比Zookeeper弱;
NameServer本身是没有状态的,并且多个NameServer直接并没有通信,可以横向扩展多台,Broker会和每一台NameServer建立长连接;
Broker是RocketMQ的核心,提供了消息的接收,存储,拉取等功能,一般都需要保证Broker的高可用,所以会配置Broker Slave,当Master挂掉之后,Consumer然后可以消费Slave;
Broker分为Master和Slave,一个Master可以对应多个Slave,Master与Slave的对应关系通过指定相同的BrokerName,不同的BrokerId来定义,BrokerId为0表示Master,非0表示Slave;
息队列的生产者,需要与NameServer建立连接,从NameServer获取Topic路由信息,并向提供Topic服务的Broker Master建立连接;Producer无状态.
消息队列的消费者,同样与NameServer建立连接,从NameServer获取Topic路由信息,并向提供Topic服务的Broker Master,Slave建立连接;
在介绍完以上4个角色以后,还需要重点介绍一下上面提到的Topic和Message Queue;字面意思就是主题,用来区分不同类型的消息,发送和接收消息前都需要先创建Topic,针对Topic来发送和接收消息,为了提高性能和吞吐量,引入了Message Queue,一个Topic可以设置一个或多个Message Queue,有点类似kafka的分区(Partition),这样消息就可以并行往各个Message Queue发送消息,消费者也可以并行的从多个Message Queue读取消息;
跟其他的MQ相比,可能角色多了点,但是没有关系。这里我说明一点。前面两种角色不需要我们自己创建,开发者只需要自己创建后三者角色。
在申明一点:我们一定要提前搭建好RocketMQ的基本环境,如果你还不会搭建的,请点击这里;如果你搭建好了,先启动NameServer服务器,在启动Broker服务器,在运行相应的jar包。详细步骤上一篇文章都有。
我们先看怎么整合的问题,至于问题,后面再说
Pom文件
4.0.0
com.tff
springboot_rocketmq
pom
1.0-SNAPSHOT
org.springframework.boot
spring-boot-starter-parent
2.2.2.RELEASE
org.apache.rocketmq
rocketmq-spring-boot-starter
2.0.3
org.springframework.boot
spring-boot-starter-web
生产者角:
package com.tff.springbootrocketmq;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class Producer{
@Autowired
private RocketMQTemplate rocketMQTemplate;
public void sendMessage(){
//参数1:topic 参数2:要发送的消息
rocketMQTemplate.convertAndSend("hoppy","i love code");
System.out.println("消息发送完成");
}
}
消费者角色:
package com.tff.springbootrocketmq;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.springframework.stereotype.Component;
#这个注解相当重要 参数1 topic 参数2 消息的组
@RocketMQMessageListener(topic = "hoppy",consumerGroup = "${rocketmq.producer.group}")
@Component
public class Consumer implements RocketMQListener {
@Override
public void onMessage(String s) {
System.out.println("接收的消息:"+s);
}
}
controller层
package com.tff.web;
import com.tff.springbootrocketmq.Producer;
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
public class RocketMQController {
@Autowired
private Producer producer; //采用springboot模板集成方式来整合
@RequestMapping("/push")
public String pushMsg() throws UnsupportedEncodingException {
producer.sendMessage();
return "ERROR";
}
}
大家可以不写这一层,直接利用springboot的测试单元也可以
配置文件
# 安装RocketMQ的主机IP地址和端口
rocketmq.name-server=127.0.0.1:9876
#发送消息的组
rocketmq.producer.group=group1
测试:
浏览器地址栏输入:http://localhost:8080/push
我们可以看到,消息消费端已经接受到消息了。
打开RocketMQ的图形用户界面
我们看到,已经可以看到我们的生产者了。
我们在来看一下“消息”菜单
这些都是我们刚才发送的消息
这种方式有一定的局限性,Springboot在这方面做的不是很好。所以,我们在开发过程中经常使用第二种方式,开发者自己进行封装。
Pom文件
4.0.0
com.tff
rocketmq_test_demo
1.0-SNAPSHOT
org.apache.rocketmq
rocketmq-client
4.3.1
生产者:
import org.apache.rocketmq.client.exception.MQBrokerException;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
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 java.io.UnsupportedEncodingException;
public class Producer1 {
public static void main(String[] args) throws MQClientException, RemotingException, InterruptedException, MQBrokerException, UnsupportedEncodingException {
//创建默认 DefaultMQProducer
DefaultMQProducer producer = new DefaultMQProducer("demo1");
//设置nameServer地址
producer.setNamesrvAddr("127.0.0.1:9876");
//开启 DefaultMQProducer
producer.start();
//创建消息
Message message = new Message("Hello_World","jsj","二叉树、平衡二叉树、图、有向图、无向图、线性结构等".getBytes(RemotingHelper.DEFAULT_CHARSET));
//发送消息
SendResult result = producer.send(message);
System.out.println(result);
//关闭
producer.shutdown();
}
}
消息消费者
import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext;
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.message.MessageExt;
import org.apache.rocketmq.remoting.common.RemotingHelper;
import java.io.UnsupportedEncodingException;
import java.util.List;
public class Consumer1 {
public static void main(String[] args) throws MQClientException {
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("demo1");
consumer.setNamesrvAddr("127.0.0.1:9876");
//从那个主题中获取 第二个参数是怎么过滤,*代表所有,也可以是tag
consumer.subscribe("Hello_World","*");
//创建消息监听器
consumer.registerMessageListener(new MessageListenerConcurrently() {
public ConsumeConcurrentlyStatus consumeMessage(List list, ConsumeConcurrentlyContext consumeConcurrentlyContext) {
//迭代消息
for(MessageExt msg : list){
try {
//获取主题
String topic = msg.getTopic();
//获取tag
String tag = msg.getTags();
//获取消息
byte[] mes = msg.getBody();
String message = new String(mes,RemotingHelper.DEFAULT_CHARSET);
System.out.println("接收到消息==: 消息主题:"+topic+", tag: "+tag+", 内容:"+message);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
//消息接收失败,重试机制
return ConsumeConcurrentlyStatus.RECONSUME_LATER;
}
}
//消息接收成功,返回状态
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
}
});
//开启consumer
consumer.start();
}
}
这里就不具体解释代码的含义了,都有注释
这里只需要补充一点;也是特别重要的一点。
就是我们下载的RocketMQ的版本要是我们导入的依赖版本一致,否则,会出现bug
例如,我这个是4.3.1版本
那么,我的maven依赖也因该是这个版本
再启动消费者:
基本上就是这两种方式了,一般开发过程中,选用后者的比较多。大家在开发过程中,可以自己封住,这里只是为了测试,我没有进行封装。
另外,附一下RocketMQ的官网地址;很有用的,因为是阿里开发的,所以中国人看起来还是挺可以的。
官网地址:http://rocketmq.apache.org/docs/simple-example/
欢迎大家批评指正!如果你喜欢的话,请留下您宝贵的建议……