Message:信息载体 Queue:数据结构,先进先出
消息队列几个应用机制:
1、异步通信
消息队列通信方式与分布式服务调用类似,但异步通信通过消息队列实现异步效果,生产者方无需等待消息结果,直接将消息放入在消息队列中即可,然后消费者方在合适的时机取出消息,来实现通信业务;
2、应用解耦
得益于消息队列的异步机制,可以将生产者和消费者之间的耦合关系解开,生产者和消费者互相不用关心谁来发送消息或者取出消息;
3、冗余存储
MQ本身具有储存数据的功能,当生产者产出信息大于消费者能取出信息时,可以把冗余的信息持久化保持下来;
4、削峰填谷
当流量输入不稳定,存在流量峰值时,消费者无法及时取出消化流量,因此通过冗余存储机制,讲流量洪峰流量转换为平稳流量输出,从而保护消费者方,避免其出现雪崩或溢出等情况;
Rocket Message Queue:
(阿里巴巴消息队列中间件)
常见MQ:ActiveMQ、RabbitMQ、Kafka、pulsar、RocketMQ
RocketMQ概念模型
- Producer:负责发布消息的角色,支持分布式集群方式部署;
- Consumer:负责消费消息的角色,支持分布式集群方式部署,它提供实时消息订阅机制,同时支持Push、Pull、集群方式及广播等方式获取消息;
- NameService:一个Topic路由注册中心,支持Broker的动态注册和发现,主要包括Broker管理,提供心跳检测机制以及路由信息管理;
- BrokerServer:Broker主要负责消息的存储、投递和查询以及服务高可用保证;
简单收发案例:
1、创建Maven QuickStart项目
2、添加依赖
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-client</artifactId>
<version>4.9.1</version>
</dependency>
3、生产者方
public class Sender {
public static void main(String[] args) throws MQClientException, RemotingException, InterruptedException, MQBrokerException, UnsupportedEncodingException {
//(1)创建生产者
/**
* 生产者分组
*/
DefaultMQProducer producer = new DefaultMQProducer("TestSender");
producer.setNamesrvAddr(AppConstants.ROCKETMQ_NAMESERVER_ADDR);
//(2)启动producer
producer.start();
//(3)构建消息并发送
Scanner scanner = new Scanner(System.in);
while (true) {
System.out.println("请输入要发送的消息");
String smsContent = scanner.next();
if (smsContent.equals("exit")) {
//(4)关闭producer
producer.shutdown();
}
Message msg = new Message(AppConstants.SMS_TOPIC, "user_register", smsContent.getBytes("UTF-8"));
//同步发送到RocketMQ
SendResult sendResult = producer.send(msg);
System.out.println("sendResult:" + sendResult);
}
}
}
4、消费者方
public class Receiver {
public static void main(String[] args) throws MQClientException {
//(1)创建消费者实例
//消费者分组,同一个名字的消费者组成一个集群
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("TestReceive");
consumer.setNamesrvAddr(AppConstants.ROCKETMQ_NAMESERVER_ADDR);
//(2)订阅某个主题,收到特定的消息
consumer.subscribe(AppConstants.SMS_TOPIC,"*");
//(3)向MQ注册一个监听器
/*
msgs 消息列表
context 消息上下文
*/
consumer.registerMessageListener((MessageListenerConcurrently) (msgs, context) -> {
for (MessageExt msgExt:msgs){
try {
System.out.println("消息内容:"+new String(msgExt.getBody(),"utf-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
});
// (4)启动消费者实例
consumer.start();
System.out.printf("Consumer Started.%n");
}
}
发送消息的三种模式:
同步确认发送结果:
同步发送是指消息发送方发出一条消息后,会在收到服务端同步响应之后才发下一条消息;
应用场景:此种方式应用场景非常广泛,例如重要通知邮件、报名短信通知、营销短信系统等。
生产者代码:
public class Sender {
public static void main(String[] args) throws MQClientException, RemotingException, InterruptedException, MQBrokerException, UnsupportedEncodingException {
//(1)创建生产者
/**
* 生产者分组
*/
DefaultMQProducer producer = new DefaultMQProducer("TestSender");
producer.setNamesrvAddr(AppConstants.ROCKETMQ_NAMESERVER_ADDR);
//(2)启动producer
producer.start();
//循环发送,查看回调结果顺序
for (int i = 0; i < 10; i++) {
//(3)构建消息并发送
String smsContent = "嘿嘿";
Message msg = new Message(AppConstants.SMS_TOPIC, "user_register", (smsContent + i).getBytes("UTF-8"));
//同步发送到RocketMQ
SendResult sendResult = producer.send(msg);
System.out.println("sendResult:" + sendResult);
}
//(4)关闭producer
producer.shutdown();
}
}
异步确认发送结果:
异步发送是指发送方发出一条消息后,不等服务端返回响应,接着发送下一条消息的通讯方式。消息队列RocketMQ版的异步发送,需要您实现异步发送回调接口(SendCallback)。消息发送方在发送了一条消息后,不需要等待服务端响应即可发送第二条消息。发送方通过回调接口接收服务端响应,并处理响应结果。
应用场景:异步发送一般用于链路耗时较长,对响应时间较为敏感的业务场景,例如,您视频上传后通知启动转码服务,转码完成后通知推送转码结果等。
生产者代码:
public class AsyncSender {
public static void main(String[] args) throws MQClientException, RemotingException, InterruptedException, MQBrokerException, UnsupportedEncodingException {
//(1)创建生产者
/**
* 生产者分组
*/
DefaultMQProducer producer = new DefaultMQProducer("AsyncTestSender");
producer.setNamesrvAddr(AppConstants.ROCKETMQ_NAMESERVER_ADDR);
//(2)启动producer
producer.start();
producer.setRetryTimesWhenSendAsyncFailed(0); //异步发送失败后的重试次数
//(3)构建消息并发送
String smsContent = "嘿嘿";
for (int i = 0; i < 10; i++) {
Message msg = new Message(AppConstants.SMS_TOPIC, "user_register", (smsContent + i).getBytes("UTF-8"));
//发送到RocketMQ,通过callback异步确认
producer.send(msg, new SendCallback() {
@Override
public void onSuccess(SendResult sendResult) {
System.out.println(sendResult);
System.out.println("send status " + System.currentTimeMillis());
}
@Override
public void onException(Throwable e) {
e.printStackTrace();
}
});
}
System.out.println("send finished " + System.currentTimeMillis());
//(4)关闭producer
producer.shutdown();
}
}
结束 oneway发送:
发送方只负责发送消息,不等待服务端返回响应且没有回调函数触发,即只发送请求不等待应答。此方式发送消息的过程耗时非常短,一般在微秒级别。
应用场景:适用于某些耗时非常短,但对可靠性要求并不高的场景,例如日志收集。
核心代码:
//发送到RocketMQ,不等待结果
producer.sendOneway(msg);