Rabbitmq
什么是中间件
中间件的概念听起来高大上,但其实我们平时都在使用,例如MySQL就可以看作是具备中间件特性的一种技术,中间件技术必须遵循一定的规范和协议,例如 TCP/IP、UDP协议等等,无规矩不成方圆,只有遵守一定的协议才能去处理事情。MySQL 就遵循了 TCP/IP 协议,在我们平常的开发中使用不同的编程语言比如 Java、Go、Python 等来操作 MySQL 的前提也是要遵循 TCP/IP协议,根据此协议实现了不通语言的连接模块来达到通信的目的。由此说使用中间件需要解决的第一个问题就是互通性,也就是相互间可以通信。我们后续学习到其他中间件可能会看到更多其他的协议,比如 AMQP、HTTP 协议等等,为什么呢?因为 TCP/IP 协议是底层的操作系统协议,它并不能满足我们业务场景中的所有需求,所以在其基础上构建一个自己请求信息来实现一个新的协议,比如 AMQP 协议就在信息头中增加消息内容tag标签、队列名、交换机名、连接定制信息等等。
消息中间件
1、应用场景
- 跨系统数据传递
- 高并发的流量削峰
- 数据的分发和异步处理
- 大数据分析与传递
- 分布式事务
2、消息分发策略的机制和对比
ActiveMQ | RabbitMQ | Kafka | RocketMQ | |
---|---|---|---|---|
发布订阅 | 支持 | 支持 | 支持 | 支持 |
轮询分发 | 支持 | 支持 | 支持 | / |
公平分发 | / | 支持 | 支持 | / |
重发 | 支持 | 支持 | / | 支持 |
消息拉取 | / | 支持 | 支持 | 支持 |
3、串行执行和并行执行
阻塞和非阻塞
Rabbitmq的下载和安装
1.安装
2.1、下载RabbitMQ
下载地址:https://www.rabbitmq.com/download.html
选择对应的系统版本点击下载,下载后会得到.rpm
文件
2.2、下载Erlang
RabbitMQ是采用 Erlang语言开发的,所以系统环境必须提供 Erlang环境,需要是安装 Erlang
Erlang
和RabbitMQ
版本对照:https://www.rabbitmq.com/which-erlang.html
这里安装最新版本3.8.14的RabbitMQ
,对应的Erlang
版本推荐23.x
,我们下载erlang-23.2.7-2.el7.x86_64.rpm
下载地址:https://packagecloud.io/rabbitmq/erlang/packages/el/7/erlang-23.2.7-2.el7.x86_64.rpm
其中的el7
表示Red Hat 7.x,即CentOS 7.x
点击右上角下载即可得到.rpm
文件
2.3、安装Erlang
首先将下载好的文件上传到服务器,创建一个文件夹用来存放文件
[root@zsr ~]# mkdir -p /usr/rabbitmq
12
再利用xftp
工具将上述下载的两个.rpm
文件上传到服务器的刚创建的文件夹中
然后切换到/usr/rabbitmq
目录,解压安装erlang
# 解压
rpm -Uvh erlang-23.2.7-2.el7.x86_64.rpm
# 安装
yum install -y erlang
123456
安装完成后输入如下指令查看版本号
erl -v
12
2.4、安装RabbitMQ
在RabiitMQ
安装过程中需要依赖socat
插件,首先安装该插件
yum install -y socat
12
然后解压安装RabbitMQ
的安装包
# 解压
rpm -Uvh rabbitmq-server-3.8.14-1.el7.noarch.rpm
# 安装
yum install -y rabbitmq-server
123456
2.5、启动RabbitMQ服务
# 启动rabbitmq
systemctl start rabbitmq-server
# 查看rabbitmq状态
systemctl status rabbitmq-server
123456
显示active
则表示服务安装并启动成功
其他命令:
# 设置rabbitmq服务开机自启动
systemctl enable rabbitmq-server
# 关闭rabbitmq服务
systemctl stop rabbitmq-server
# 重启rabbitmq服务
systemctl restart rabbitmq-server
123456789
3、RabbitMQWeb管理界面及授权操作
3.1、安装启动RabbitMQWeb管理界面
默认情况下,rabbitmq没有安装web端的客户端软件,需要安装才可以生效
# 打开RabbitMQWeb管理界面插件
rabbitmq-plugins enable rabbitmq_management
123
然后我们打开浏览器,访问服务器公网ip:15672
(注意打开阿里云安全组以及防火墙的15672端口),就可以看到管理界面
rabbitmq
有一个默认的账号密码guest
,但该情况仅限于本机localhost进行访问,所以需要添加一个远程登录的用户
3.2、添加远程用户
# 添加用户
rabbitmqctl add_user 用户名 密码
# 设置用户角色,分配操作权限
rabbitmqctl set_user_tags 用户名 角色
# 为用户添加资源权限(授予访问虚拟机根节点的所有权限)
rabbitmqctl set_permissions -p / 用户名 ".*" ".*" ".*"
123456789
角色有四种:
administrator
:可以登录控制台、查看所有信息、并对rabbitmq进行管理monToring
:监控者;登录控制台,查看所有信息policymaker
:策略制定者;登录控制台指定策略managment
:普通管理员;登录控制
这里创建用户zsr
,密码123456
,设置administrator
角色,赋予所有权限
创建完成后,访问服务器公网ip:15672
进行登录,然后便可进入到后台
使用rabbitmq
五种工作模式
代码实现
package com.zyl.rabbitmq.simple;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
//生产者
public class Producer {
public static void main(String[] args) throws IOException, TimeoutException {
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("8.130.94.244");
connectionFactory.setPort(5672);
connectionFactory.setUsername("admin");
connectionFactory.setPassword("admin");
connectionFactory.setVirtualHost("/");
Connection connection=null;
Channel channel=null;
try {
//创建连接
connection=connectionFactory.newConnection("生产者");
//获取连接通道
channel=connection.createChannel();
//队列名称
String QueueName="queue2";
//设置参数
channel.queueDeclare(QueueName,true,false,false,null);
//准备消息内容
String msg="hello rabbitmq";
//发送消息
channel.basicPublish("",QueueName,null,msg.getBytes());
System.out.println("发送消息成功");
} catch (Exception e) {
e.printStackTrace();
} finally {
//关闭通道
if (channel!=null&&channel.isOpen()){
channel.close();
}
//关闭连接
if (connection!=null&&connection.isOpen()){
connection.close();
}
}
}
}
package com.zyl.rabbitmq.simple;
import com.rabbitmq.client.*;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
//消费者
public class Comsumer {
public static void main(String[] args) throws IOException, TimeoutException {
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("8.130.94.244");
connectionFactory.setPort(5672);
connectionFactory.setUsername("admin");
connectionFactory.setPassword("admin");
connectionFactory.setVirtualHost("/");
Connection connection=null;
Channel channel=null;
try {
//创建连接
connection=connectionFactory.newConnection("生产者");
//获取连接通道
channel=connection.createChannel();
//发送消息
channel.basicConsume("queue2", true, new DeliverCallback() {
@Override
public void handle(String s, Delivery delivery) throws IOException {
System.out.println("接收到的消息是" + new String(delivery.getBody(), "UTF-8"));
}
}, new CancelCallback() {
@Override
public void handle(String s) throws IOException {
System.out.println("接受失败");
}
});
System.out.println("开始接受消息");
System.in.read();
} catch (Exception e) {
e.printStackTrace();
} finally {
//关闭通道
if (channel!=null&&channel.isOpen()){
channel.close();
}
//关闭连接
if (connection!=null&&connection.isOpen()){
connection.close();
}
}
}
}
批量应答
如果开启批量应答对进入消息信道的消息:容易消息丢失
消息的手动应答
package org.example.three;
import com.rabbitmq.client.CancelCallback;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.DeliverCallback;
import com.rabbitmq.client.Delivery;
import org.example.utils.RabbitMqUtil;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
public class worker01 {
public static final String QUEUE_NAME="ack_queue";
public static void main(String[] args) throws IOException, TimeoutException, InterruptedException {
Channel channel = RabbitMqUtil.getChannel();
//声明
DeliverCallback deliverCallback=new DeliverCallback() {
@Override
public void handle(String s, Delivery delivery) throws IOException {
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("接收到的信息是:"+new String(delivery.getBody()));
//手动应答 false表示不会批量应答
channel.basicAck(delivery.getEnvelope().getDeliveryTag(),false);
}
};
//取消消息时的回调
CancelCallback cancelCallback= s->System.out.println("消息终断");;
/**
* 消费信息
*/
//是否自动应答
boolean autoAck=false;
channel.basicConsume(QUEUE_NAME, autoAck,deliverCallback,cancelCallback);
}
}
RabbitMQ 为什么需要信道?为什么不是TCP直接通信?
-
TCP的创建和销毁,开销大,创建需要三次握手,销毁需要四次分手
-
如果不使用信道,那么引用程序就会使用TCP的方式连接到rabbitmq,高峰时每秒成千上万条连接会造成资源的巨大浪费(一条tcp消耗资源,成千上万的tcp会非常消耗资源),而且操作系统每秒处理TCP连接数量也是有限的,必定会造成性能瓶颈
3.信道的原理是一条线程一条信道,多条线程多条信道共同使用一条TCP连接。一条TCP连接可以容纳无限的信道,及时每秒造成成千上万的请求也不会造成性能瓶颈
消息持久化和消息持久化
1.设置队列持久化
2.设置消息持久化
3.发布确认
做到上面三步才能保证消息不丢失
//发布确认
channel.confirmSelect();
确认发布的策略
public static void main(String[] args) throws IOException, InterruptedException, TimeoutException {
// 单个确认 168ms
ConFirmMsg.ByOne();
// 批量确认 28ms
//ConFirmMsg.ByBatch();
// 异步批量确认 22ms
//ConFirmMsg.ByAsync();
}
//来一个信息确认一次
public static void ByOne() throws IOException, TimeoutException, InterruptedException {
Channel channel = RabbitMqUtil.getChannel();
String queueName = UUID.randomUUID().toString();
channel.confirmSelect();
channel.queueDeclare(queueName, false, false, false, null);
long begin = System.currentTimeMillis();
for (int i = 0; i < 1000; i++) {
String s = i + "";
channel.basicPublish("", queueName, null, s.getBytes());
boolean result = channel.waitForConfirms();
if (result) {
System.out.println("发送成功");
}
}
long end = System.currentTimeMillis();
System.out.println(end - begin + "ms");
}
public static void ByBatch() throws IOException, TimeoutException, InterruptedException {
Channel channel = RabbitMqUtil.getChannel();
String queueName = UUID.randomUUID().toString();
channel.confirmSelect();
channel.queueDeclare(queueName, false, false, false, null);
long begin = System.currentTimeMillis();
int test = 100;
for (int i = 0; i < 1000; i++) {
String s = i + "";
channel.basicPublish("", queueName, null, s.getBytes());
if (i % test == 0) {
boolean result = channel.waitForConfirms();
if (result) {
System.out.println("发送成功");
}
}
}
long end = System.currentTimeMillis();
System.out.println(end - begin + "ms");
}
public static void ByAsync() throws IOException, TimeoutException, InterruptedException {
Channel channel = RabbitMqUtil.getChannel();
String queueName = UUID.randomUUID().toString();
channel.confirmSelect();
channel.queueDeclare(queueName, false, false, false, null);
//添加监听器
channel.addConfirmListener(new ConfirmCallback() {
@Override
public void handle(long l, boolean b) throws IOException {
System.out.println("消息发送成功");
}
}, new ConfirmCallback() {
@Override
public void handle(long l, boolean b) throws IOException {
System.out.println("消息发送失败" + l);
}
});
long begin = System.currentTimeMillis();
for (int i = 0; i < 1000; i++) {
String s = i + "";
channel.basicPublish("", queueName, null, s.getBytes());
}
long end = System.currentTimeMillis();
System.out.println(end - begin + "ms");
}
不公平分发
public static final String QUEUE_NAME="ack_queue";
public static void main(String[] args) throws IOException, TimeoutException, InterruptedException {
Channel channel = RabbitMqUtil.getChannel();
//声明
DeliverCallback deliverCallback=new DeliverCallback() {
@Override
public void handle(String s, Delivery delivery) throws IOException {
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("接收到的信息是:"+new String(delivery.getBody()));
//手动应答 false表示不会批量应答
channel.basicAck(delivery.getEnvelope().getDeliveryTag(),false);
}
};
//取消消息时的回调
CancelCallback cancelCallback= s->System.out.println("消息终断");;
/**
* 消费信息
*/
//设置不公平分发
int perfetCount=1;
channel.basicQos(1);
//是否自动应答
boolean autoAck=false;
channel.basicConsume(QUEUE_NAME, autoAck,deliverCallback,cancelCallback);
}
消息的分发都是通过交换机
- 不设置会有默认交换机
- 然后通过队列存储
Fanout交换机
配置类
package com.zyl.config;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.FanoutExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class rabbitmq {
@Bean
public FanoutExchange fanoutExchange(){
return new FanoutExchange("fanout_order_exchange",true,false);
}
@Bean
public Queue smsQueue(){
return new Queue("sms_fanout_queue",true);
}
@Bean
public Queue msgQueue(){
return new Queue("msg_fanout_queue",true);
}
@Bean
public Queue emailQueue(){
return new Queue("email_fanout_queue",true);
}
@Bean
public Binding smsQueuebinding(){
return BindingBuilder.bind(smsQueue()).to(fanoutExchange());
}
@Bean
public Binding msgQueuebinding(){
return BindingBuilder.bind(msgQueue()).to(fanoutExchange());
}
@Bean
public Binding emailQueuebinding(){
return BindingBuilder.bind(emailQueue()).to(fanoutExchange());
}
}
具体实现
package com.zyl.service;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.UUID;
@Service
public class orderService {
@Autowired
private RabbitTemplate rabbitTemplate;
public void makeOrder(String userid,String goodid,int num){
String orderid = UUID.randomUUID().toString();
System.out.println("订单生成成功"+orderid);
String ExchangeName="fanout_order_exchange";
String routerKey="";
rabbitTemplate.convertAndSend(ExchangeName,routerKey,orderid);
}
}
Fanout消费者代码
package com.zyl.service.fanout;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
@Component
@RabbitListener(queues = {"email_fanout_queue"})
public class emailConsumer {
@RabbitHandler
public void reciveMessage(String msg){
System.out.println("email接受到消息----"+msg);
}
}
Direct交换机
生产者代码
package com.zyl.config;
import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class directConfig {
@Bean
public DirectExchange directExchange(){
return new DirectExchange("direct_order_exchange",true,false);
}
@Bean
public Queue DirectsmsQueue(){
return new Queue("sms_direct_queue",true);
}
@Bean
public Queue DirectmsgQueue(){
return new Queue("msg_direct_queue",true);
}
@Bean
public Queue DirectemailQueue(){
return new Queue("email_direct_queue",true);
}
@Bean
public Binding DirectsmsQueuebinding(){
return BindingBuilder.bind(DirectsmsQueue()).to(directExchange()).with("sms");
}
@Bean
public Binding DirectmsgQueuebinding(){
return BindingBuilder.bind(DirectmsgQueue()).to(directExchange()).with("msg");
}
@Bean
public Binding DirectemailQueuebinding(){
return BindingBuilder.bind(DirectemailQueue()).to(directExchange()).with("email");
}
}
消费者代码
package com.zyl.service.direct;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
@Component
@RabbitListener(queues = {"email_direct_queue"})
public class DirectemailConsumer {
@RabbitHandler
public void DirectreciveMessage(String msg){
System.out.println("email接受到消息----"+msg);
}
}
Topic交换机模式(使用注解开发)
消费者代码
package com.zyl.service.topic;
import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.rabbit.annotation.*;
import org.springframework.stereotype.Component;
@Component
@RabbitListener(bindings = @QueueBinding(
value = @Queue(value = "email.topic.queue",durable = "true",autoDelete = "false"),
exchange = @Exchange(value = "topic_order_exchange",type = ExchangeTypes.TOPIC),
key = "com.#"
))
public class TopicemailConsumer {
@RabbitHandler
public void reciveMessage(String msg){
System.out.println("email接受到消息----"+msg);
}
}
设置过期时间
package com.zyl.config;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.HashMap;
@Configuration
public class ttl {
@Bean
public DirectExchange ttlExchange(){
return new DirectExchange("ttl_exchange",true,false);
}
@Bean
public Queue ttlQueue(){
//设置过期时间
HashMap<String, Object> map = new HashMap<>();
map.put("x-message-ttl",5000);
return new Queue("ttl_direct_queue",true,false,false,map);
}
@Bean
public Binding TtlQueuebinding(){
return BindingBuilder.bind(ttlQueue()).to(ttlExchange()).with("as");
}
}
死信队列
1.就是处理设置了过期的队列信息
2.队列的长度达到了最大值
3.没有被消费的消息
代码演示
1.设置过期时间
//生产者
public static final String NORMAL_EXCHANGE="normal_exchange";
public static void main(String[] args) throws IOException, TimeoutException {
Channel channel = RabbitMqUtil.getChannel();
AMQP.BasicProperties properties=new AMQP.BasicProperties()
.builder()
.expiration("10000")
.build();
for (int i = 1; i < 11; i++) {
String msg=i+"";
channel.basicPublish(NORMAL_EXCHANGE,"zhangsan",properties,msg.getBytes());
}
}
//普通消费者
public static final String NORMAL_EXCHANGE="normal_exchange";
public static final String DEAD_EXCHANGE="dead_exchange";
public static final String NORMAL_QUEUE="normal_queue";
public static final String DEAD_QUEUE="dead_queue";
public static void main(String[] args) throws IOException, TimeoutException {
Channel channel = RabbitMqUtil.getChannel();
channel.exchangeDeclare(NORMAL_EXCHANGE, BuiltinExchangeType.DIRECT);
channel.exchangeDeclare(DEAD_EXCHANGE, BuiltinExchangeType.DIRECT);
HashMap<String, Object> map = new HashMap<>();
// 设置过期时间
//设置发送到死信交换机
map.put("x-dead-letter-exchange",DEAD_EXCHANGE);
//设置路由key
map.put("x-dead-letter-routing-key","lisi");
//普通队列的声明
channel.queueDeclare(NORMAL_QUEUE,false,false,false,map);
channel.queueDeclare(DEAD_QUEUE,false,false,false,null);
//绑定交换机
channel.queueBind(NORMAL_QUEUE,NORMAL_EXCHANGE,"zhangsan");
channel.queueBind(DEAD_QUEUE,DEAD_EXCHANGE,"lisi");
System.out.println("C1等待消费.....");
DeliverCallback deliverCallback = new DeliverCallback() {
@Override
public void handle(String s, Delivery delivery) throws IOException {
System.out.println("c1----->"+new String(delivery.getBody()));
}
};
channel.basicConsume(NORMAL_QUEUE, true, deliverCallback, s->{});
}
2.队列达到最大长度
public static final String NORMAL_EXCHANGE="normal_exchange";
public static final String DEAD_EXCHANGE="dead_exchange";
public static final String NORMAL_QUEUE="normal_queue";
public static final String DEAD_QUEUE="dead_queue";
public static void main(String[] args) throws IOException, TimeoutException {
Channel channel = RabbitMqUtil.getChannel();
channel.exchangeDeclare(NORMAL_EXCHANGE, BuiltinExchangeType.DIRECT);
channel.exchangeDeclare(DEAD_EXCHANGE, BuiltinExchangeType.DIRECT);
HashMap<String, Object> map = new HashMap<>();
// 设置过期时间
//设置发送到死信交换机
map.put("x-dead-letter-exchange",DEAD_EXCHANGE);
//设置路由key
map.put("x-dead-letter-routing-key","lisi");
//设置队列的长度
map.put("x-max-length",6);
//普通队列的声明
channel.queueDeclare(NORMAL_QUEUE,false,false,false,map);
channel.queueDeclare(DEAD_QUEUE,false,false,false,null);
//绑定交换机
channel.queueBind(NORMAL_QUEUE,NORMAL_EXCHANGE,"zhangsan");
channel.queueBind(DEAD_QUEUE,DEAD_EXCHANGE,"lisi");
System.out.println("C1等待消费.....");
DeliverCallback deliverCallback = new DeliverCallback() {
@Override
public void handle(String s, Delivery delivery) throws IOException {
System.out.println("c1----->"+new String(delivery.getBody()));
}
};
channel.basicConsume(NORMAL_QUEUE, true, deliverCallback, s->{});
}
3.消息被拒绝
public static final String NORMAL_EXCHANGE="normal_exchange";
public static final String DEAD_EXCHANGE="dead_exchange";
public static final String NORMAL_QUEUE="normal_queue";
public static final String DEAD_QUEUE="dead_queue";
public static void main(String[] args) throws IOException, TimeoutException {
Channel channel = RabbitMqUtil.getChannel();
channel.exchangeDeclare(NORMAL_EXCHANGE, BuiltinExchangeType.DIRECT);
channel.exchangeDeclare(DEAD_EXCHANGE, BuiltinExchangeType.DIRECT);
HashMap<String, Object> map = new HashMap<>();
// 设置过期时间
//设置发送到死信交换机
map.put("x-dead-letter-exchange",DEAD_EXCHANGE);
//设置路由key
map.put("x-dead-letter-routing-key","lisi");
//普通队列的声明
channel.queueDeclare(NORMAL_QUEUE,false,false,false,map);
channel.queueDeclare(DEAD_QUEUE,false,false,false,null);
//绑定交换机
channel.queueBind(NORMAL_QUEUE,NORMAL_EXCHANGE,"zhangsan");
channel.queueBind(DEAD_QUEUE,DEAD_EXCHANGE,"lisi");
System.out.println("C1等待消费.....");
DeliverCallback deliverCallback = new DeliverCallback() {
@Override
public void handle(String s, Delivery delivery) throws IOException {
String msg = new String(delivery.getBody());
if (msg.equals("5")){
System.out.println(msg+"----被拒收");
channel.basicReject(delivery.getEnvelope().getDeliveryTag(),false);
}else {
System.out.println("c1----->"+msg);
channel.basicAck(delivery.getEnvelope().getDeliveryTag(),false);
}
}
};
//关闭自动应答
channel.basicConsume(NORMAL_QUEUE, false, deliverCallback, s->{});
}
SpringBoot整合rabbitmq
1.导入坐标
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
2.写配置文件
spring.rabbitmq.host=localhost
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
3.代码实现(定义)
public static final String X_EXCHANGE="X";
public static final String DEAD_EXCHANGE="Y";
public static final String QUEUE_A="A";
public static final String QUEUE_B="B";
public static final String DEAD_QUEUE="C";
//普通交换机
@Bean
public DirectExchange X(){
return new DirectExchange(X_EXCHANGE);
}
//死信交换机
@Bean
public DirectExchange Y(){
return new DirectExchange(DEAD_EXCHANGE);
}
//延迟队列1
@Bean
public Queue queueA(){
HashMap<String, Object> map = new HashMap<>();
//设置死信交换机
map.put("x-dead-letter-exchange",DEAD_EXCHANGE);
//设置死信路由key
map.put("x-dead-letter-routing-key","YD");
//设置TTL
map.put("x-message-ttl",10000);
return QueueBuilder.durable(QUEUE_A).withArguments(map).build();
}
//延迟队列2
@Bean
public Queue queueB(){
HashMap<String, Object> map = new HashMap<>();
//设置死信交换机
map.put("x-dead-letter-exchange",DEAD_EXCHANGE);
//设置死信路由key
map.put("x-dead-letter-routing-key","YD");
//设置TTL
map.put("x-message-ttl",40000);
return QueueBuilder.durable(QUEUE_B).withArguments(map).build();
}
//死信队列
@Bean
public Queue queueC(){
return QueueBuilder.durable(DEAD_QUEUE).build();
}
//队列绑定
@Bean
public Binding xBindA(){
return BindingBuilder.bind(queueA()).to(X()).with("XA");
}
@Bean
public Binding xBindB(){
return BindingBuilder.bind(queueB()).to(X()).with("XB");
}
@Bean
public Binding yBindC(){
return BindingBuilder.bind(queueC()).to(Y()).with("YD");
}
3.消费者
@Component
public class DeadConsumer {
@RabbitListener(queues = "C")
public void receive(Message message, Channel channel){
System.out.println(new String(message.getBody()));
}
}
4.生产者
@RestController
public class send {
@Autowired
private RabbitTemplate rabbitTemplate;
@GetMapping("/ttl")
public void sendMsg(){
System.out.println(LocalDateTime.now().toString());
rabbitTemplate.convertAndSend("X","XA", LocalDateTime.now().toString());
rabbitTemplate.convertAndSend("X","XB", LocalDateTime.now().toString());
}
}
延迟队列(定义)
public static final String X_EXCHANGE="X";
public static final String DEAD_EXCHANGE="Y";
public static final String QUEUE_A="A";
public static final String QUEUE_B="B";
public static final String DEAD_QUEUE="C";
//普通交换机
@Bean
public DirectExchange X(){
return new DirectExchange(X_EXCHANGE);
}
//死信交换机
@Bean
public DirectExchange Y(){
return new DirectExchange(DEAD_EXCHANGE);
}
//延迟队列1
@Bean
public Queue queueA(){
HashMap<String, Object> map = new HashMap<>();
//设置死信交换机
map.put("x-dead-letter-exchange",DEAD_EXCHANGE);
//设置死信路由key
map.put("x-dead-letter-routing-key","YD");
//设置TTL
map.put("x-message-ttl",10000);
return QueueBuilder.durable(QUEUE_A).withArguments(map).build();
}
//延迟队列2
@Bean
public Queue queueB(){
HashMap<String, Object> map = new HashMap<>();
//设置死信交换机
map.put("x-dead-letter-exchange",DEAD_EXCHANGE);
//设置死信路由key
map.put("x-dead-letter-routing-key","YD");
//设置TTL
map.put("x-message-ttl",40000);
return QueueBuilder.durable(QUEUE_B).withArguments(map).build();
}
//死信队列
@Bean
public Queue queueC(){
return QueueBuilder.durable(DEAD_QUEUE).build();
}
//队列绑定
@Bean
public Binding xBindA(){
return BindingBuilder.bind(queueA()).to(X()).with("XA");
}
@Bean
public Binding xBindB(){
return BindingBuilder.bind(queueB()).to(X()).with("XB");
}
@Bean
public Binding yBindC(){
return BindingBuilder.bind(queueC()).to(Y()).with("YD");
}
1.消费者
@RabbitListener(queues = "C")
public void receive(Message message, Channel channel){
System.out.println(new String(message.getBody()));
}
2.生产者
@Autowired
private RabbitTemplate rabbitTemplate;
@GetMapping("/ttl")
public void sendMsg(){
System.out.println(LocalDateTime.now().toString());
rabbitTemplate.convertAndSend("X","XA", "第一条消息");
rabbitTemplate.convertAndSend("X","XB", "第二条消息");
}
map.put("x-message-ttl",40000);
return QueueBuilder.durable(QUEUE_B).withArguments(map).build();
}
//死信队列
@Bean
public Queue queueC(){
return QueueBuilder.durable(DEAD_QUEUE).build();
}
//队列绑定
@Bean
public Binding xBindA(){
return BindingBuilder.bind(queueA()).to(X()).with("XA");
}
@Bean
public Binding xBindB(){
return BindingBuilder.bind(queueB()).to(X()).with("XB");
}
@Bean
public Binding yBindC(){
return BindingBuilder.bind(queueC()).to(Y()).with("YD");
}
## 1.消费者
@RabbitListener(queues = "C")
public void receive(Message message, Channel channel){
System.out.println(new String(message.getBody()));
}
## 2.生产者
@Autowired
private RabbitTemplate rabbitTemplate;
@GetMapping("/ttl")
public void sendMsg(){
System.out.println(LocalDateTime.now().toString());
rabbitTemplate.convertAndSend("X","XA", "第一条消息");
rabbitTemplate.convertAndSend("X","XB", "第二条消息");
}