一丶认识RocketMQ
1.MQ是什么
MQ全称为Message Queue,即消息队列 ,是一种提供消息队列服务的中间件,也称为消息中间件,是一套提供了消息生 产、存储、消费全过程的软件系统,遵循FIFO原则
2.MQ的使用场景
2.1限流削峰
MQ可以将系统的超量请求暂存其中,以便系统后期可以慢慢进行处理,从而避免了请求的丢失或系统 被压垮。
2.2异步&解耦
上游系统对下游系统的调用若为同步调用,则会大大降低系统的吞吐量与并发度,且系统耦合度太高。 而异步调用则会解决这些问题。所以两层之间若要实现由同步到异步的转化,一般性做法就是,在这两层间添加一个MQ层。 即使消费者挂掉也不影响生产者工作,只要把消息放入队列即可,消费者重启后自己消费即可。
2.3数据收集
分布式系统会产生海量级数据流,如:业务日志、监控数据、用户行为等。针对这些数据流进行实时或 批量采集汇总,然后对这些数据流进行大数据分析,这是当前互联网平台的必备技术。通过MQ完成此 类数据收集是最好的选择。
2.4大数据处理
比如我们的平台向“三方平台”获取数据,一次请求了大量数据回来要进行处理,由于数据较多处理不过来,那么就可以放入MQ,再创建一些消费者进行数据处理即可
3.RocketMQ是什么
3.1RocketMQ介绍
RocketMQ是一个统一消息引擎、轻量级数据处理平台。
3.2RocketMQ特征
①.支持集群模型、负载均衡、水平扩展能力
②.亿级别消息堆积能力
③.采用零拷贝的原理,顺序写盘,随机读
④.底层通信框架采用Netty NIO
⑤.NameServer代替Zookeeper,实现服务寻址和服务协调
⑥.消息失败重试机制、消息可查询
⑦.强调集群无单点,可扩展,任意一点高可用,水平可扩展
⑧.经过多次双十一的考验
二丶RocketMQ的原理
RocketMQ主要由 Producer、Broker、Consumer、NameServer 三部分组成,其中Producer 负责生产消息,Consumer 负责消费消息,Broker 负责存储消息。Broker 在实际部署过程中对应一台服务器。
为了实现高可用,Broker本身是主备架构,Master负责写请求和读请求,Slave负责数据备份和分担读请求。这样的好处是提高了吞吐量同时防止数据丢失
三丶RocketMQ的使用
1.环境搭建
1.1导入依赖
<parent>
<groupId> org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.5.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-spring-boot-starter</artifactId>
<!-- <version>2.0.4</version> -->
<version>2.2.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
1.2配置文件(yml/yaml)
rocketmq:
name-server: 127.0.0.1:9876
#生产者配置
producer:
#生产者组名字
group: "service-producer"
# 消息最大长度 默认 1024 * 1024 * 4 (4M)
max-message-size: 4194304
# 发送消息超时时间,默认 3000
send-message-timeout: 3000
# 发送消息失败重试次数,默认2
retry-times-when-send-failed: 2
# 异步消息发送失败重试次数
retry-times-when-send-async-failed: 2
#达到 4096 ,进行消息压缩
compress-message-body-threshold: 4096
consumer:
#消费者名字
group: "service-consumer"
#批量拉取消息数量
pull-batch-size: 10
message-model: CLUSTERING
selector-expression: "*"
1.3启动类
@SpringBootApplication
public class ApplicationStart {
public static void main(String[] args) {
SpringApplication.run(ApplicationStart.class);
}
}
2.消息发送
2.1同步发送(两种)
第二种可以指定超时时间
@Autowired
private RocketMQTemplate rocketMQTemplate;
@GetMapping("/send/{message}")
public void sendMsg(@PathVariable("message") String data) {
Message<String> message = MessageBuilder.withPayload(data).build();
rocketMQTemplate.send("topic-order:tags-order-flow", message);
}
@GetMapping("/synSend/{message}")
public void synSendendMsg(@PathVariable("message") String data) {
Message<String> message = MessageBuilder.withPayload(data).build();
SendResult result = rocketMQTemplate.syncSend("topic-order:tags-order-flow", message, 2000, 3);//延迟消息
System.out.println(result);
if (result.getSendStatus() != SendStatus.SEND_OK) {
System.out.println("发送失败");
} else {
System.out.println("发送成功");
}
}
2.2异步发送
@GetMapping("/asyncSend/{message}")
public void asyncSendMessage(@PathVariable("message") String data){
Message<String> message = MessageBuilder.withPayload(data).build();
rocketMQTemplate.asyncSend("topic-order:tags-order-flow", message, new SendCallback() {
@Override
public void onSuccess(SendResult sendResult) {
System.out.println(sendResult);
System.out.println("发送成功");
}
@Override
public void onException(Throwable e) {
System.out.println("发送失败");
e.printStackTrace();
}
});
}
2.3单向发送
@GetMapping("/sendOneWay/{message}")
public void sendOneWayMessage(@PathVariable("message") String data) {
Message<String> message = MessageBuilder.withPayload(data).build();
rocketMQTemplate.sendOneWay("topic-order:tags-order-flow", message);
}
2.4消费者获取消息
import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.spring.annotation.MessageModel;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.springframework.stereotype.Component;
import java.nio.charset.StandardCharsets;
@Component
@RocketMQMessageListener(
//消费者的名字
consumerGroup = "consumer-group-xxx",
//主题
topic = "topic-order",
//tags
selectorExpression = "tags-order-flow",
//消息消费模式:默认是CLUSTERING集群,还支持BROADCASTING广播
messageModel = MessageModel.CLUSTERING)
//MessageExt:Message对象的子类
public class TestConsumer implements RocketMQListener<MessageExt> {
@Override
public void onMessage(MessageExt message) {
//这里拿到的消息 message.getBody 是byte[]格式。
if(message.getBody() == null ||message.getBody().length == 0)return;
//拿到消息:如果发送的消息是字符串,那么需要把byte[]转为字符串
String msg = new String(message.getBody(), StandardCharsets.UTF_8);
}
}