RabbitMQ拓展
TTL队列/消息
- TTL是Time To Live的缩写, 也就是生存时间
- RabbitMQ支持消息的过期时间, 在消息发送时可以进行指定
- RabbitMQ支持队列的过期时间, 从消息入队列开始计算, 只要超过了队列的超时时间配置, 那么消息会自动清除
生产者
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.victoria.rabbitmq.util.ConnectionUtils;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
public class send {
private static final String EXCHANGE_NAME = "test_exchange_ttl";
public static void main(String[] args) throws IOException, TimeoutException {
//获取链接
Connection connection = ConnectionUtils.getConnection();
//创建通道
Channel channel = connection.createChannel();
//交换机声明
channel.exchangeDeclare(EXCHANGE_NAME,"topic",true);
//路由键
String rount_key = "user.add";
//发送消息
for(int i = 0 ;i<5;i++){
String msg_str = "Hello TTl msg"+i;
channel.basicPublish(EXCHANGE_NAME,rount_key,null,msg_str.getBytes());
}
//关闭链接
channel.close();
connection.close();
}
}
消费者
import com.rabbitmq.client.*;
import com.victoria.rabbitmq.util.ConnectionUtils;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeoutException;
public class recv {
private static final String EXCHANGE_NAME = "test_exchange_ttl";
private static final String QUEUE_NAME = "test_queue_ttl";
public static void main(String[] args) throws IOException, TimeoutException {
//获取链接
Connection connection = ConnectionUtils.getConnection();
//创建通道
final Channel channel = connection.createChannel();
//限流
channel.basicQos(1);
//配置参数
Map<String,Object> map = new HashMap<String, Object>();
//配置ttl过期时间
map.put("x-message-ttl", 10000);
//声明队列和交换机
channel.queueDeclare(QUEUE_NAME,true,false,false,map);
channel.exchangeDeclare(EXCHANGE_NAME,"topic",true);
//路由键匹配
String rount_key = "user.#";
//队列绑定交换机
channel.queueBind(QUEUE_NAME,EXCHANGE_NAME,rount_key);
//消费者
Consumer consumer = new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println(new String(body));
//ack认证
channel.basicAck(envelope.getDeliveryTag(),false);
}
};
//监听
channel.basicConsume(QUEUE_NAME,false,consumer);
}
}
DLX(死信队列)
- Dead-Letter-Exchange
- 利用DLX, 当消息在一个队列中变成死信(dead message)之后, 它能被重新publish到另一个Exchange, 这个Exchange就是DLX
- DLX也是一个正常的Exchange, 和一般的Exchange没有区别, 它能在任何队列上被指定, 实际上就是设置某个队列的属性为死信队列
- 当这个队列中有死信时, RabbitMQ就会自动将这个消息重新发布到设置的Exchange上去, 进而被路由到另一个队列
- 可以监听这个队列中消息做相应的处理, 这个特性可以弥补RabbitMQ3.0以前支持的immediate参数的功能
消息变成死信队列的几种情况
- 消息被拒绝(basic.reject/basic.nack) 并且requeue重回队列设置成false
- 消息TTL过期
- 队列达到最大长度
死信队列的配置
- 首先要设置死信队列的exchange和queue,然后进行绑定(死信队列的交换机名和队列名只能这样写)
1.Exchange : dlx.exchange
2.Queue : dlx.queue
3.RoutingKey : # - 然后正常声明交换机, 队列, 绑定, 只不过需要在队列加上一个扩展参数即可 : arguments.put(“x-dead-letter-exchange”, “dlx.exchange”);
- 这样消息在过期, reject或nack(requeue要设置成false), 队列在达到最大长度时, 消息就可以直接路由到死信队列
生产者
import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.victoria.rabbitmq.util.ConnectionUtils;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
public class send {
private static final String EXCHANGE_NAME = "test_exchange_dlx";
public static void main(String[] args) throws IOException, TimeoutException {
//获取链接
Connection connection = ConnectionUtils.getConnection();
//创建通道
Channel channel = connection.createChannel();
//路由键
String rount_key = "user.add";
//消息十秒没被消费则过期
AMQP.BasicProperties properties = new AMQP.BasicProperties().builder().expiration("10000").build();
//生产者发送消息
for(int i =0;i<5;i++){
String str_msg = "hello dlx msg"+i;
channel.basicPublish(EXCHANGE_NAME,rount_key,properties,str_msg.getBytes());
}
//关闭链接
channel.close();
connection.close();
}
}
消费者
import com.rabbitmq.client.*;
import com.victoria.rabbitmq.util.ConnectionUtils;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeoutException;
public class recv {
private static final String EXCHANGE_NAME = "test_exchange_dlx";
private static final String QUEUE_NAME = "test_queue_dlx";
//注意:死信队列的交换机名和队列名只能这样取
private static final String EXCHANGE_DLX_NAME = "dlx.exchange";
private static final String QUEUE_DLX_NAME = "dlx.queue";
public static void main(String[] args) throws IOException, TimeoutException {
//获取链接
Connection connection = ConnectionUtils.getConnection();
//创建通道
final Channel channel = connection.createChannel();
//限流
channel.basicQos(1);
//定义死信队列的队列和交换机
channel.exchangeDeclare(EXCHANGE_DLX_NAME,"topic",true);
channel.queueDeclare(QUEUE_DLX_NAME,true,false,false,null);
//绑定
channel.queueBind(QUEUE_DLX_NAME,EXCHANGE_DLX_NAME,"#");
//定义交换机和队列
channel.exchangeDeclare(EXCHANGE_NAME,"topic",true);
//给与死信队列配置
Map<String,Object> map = new HashMap<String, Object>();
map.put("x-dead-letter-exchange",EXCHANGE_DLX_NAME);
channel.queueDeclare(QUEUE_NAME,true,false,false,map);
//路由键
String rount_key = "user.#";
//绑定
channel.queueBind(QUEUE_NAME,EXCHANGE_NAME,rount_key);
//消费者消费消息
Consumer consumer = new DefaultConsumer(channel){
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println(new String(body));
channel.basicAck(envelope.getDeliveryTag(),false);
}
};
//监听
channel.basicConsume(QUEUE_NAME,false,consumer);
}
}
来源:CSDN
作者:頋婗
链接:https://blog.csdn.net/weixin_44048746/article/details/104280164