基础
RoutingKey、BindingKey
RoutingKey是生产者发消息给消费者的时候指定的,BindingKey是交换器和队列绑定时设置的,两者匹配,就会进行消息传递
队列声明
queueDeclare (String queue , boolean durable , boolean exclusive ,
boolean autoDelete , Map<Str ng Object> arguments) throws IOException;
autoDelete:自动删除是指至少有一个消费者连接过这个队列,再之后与它连接的消费者都断开了才自动删除,不是说当连接到这个队列的所有消费者都断开时候才删除
交换机声明
Exchange . DeclareOk exchangeDeclare(String exchange ,
String type , boolean durable ,
boolean autoDelete , boolean internal,
Map<String, Object> arguments) throws IOException ;
type:交换机类型,包括fanout、direct、topic、header
durable:持久化
arguments:备份交换器,生产者没有设置mandatory参数,又要不丢失没有匹配的消息的话,就声明这个参数把消息备份到这里
消息
- 返回
第二个参数设置为true则如果消息没有被路由到任何消费者,则返回消息给生产者
channel.basicPublish(EXCHANGE NAME , "", true,
MessageProperties . PERSISTENT TEXT PLAIN ,
"mandatory test" . getBytes());
而生产者可以通过监听器获得没有成功路由的消息
channel.addReturnListener(new ReturnListener() (
public void handleReturn(int replyCode , String replyText ,
String exchange , String routingKey,
AMQP.BasicProperties basicProperties,
byte[] body) throws IOExcept 工。 {
String message = new String(body);
System.out.println( "Basic.Return 返回的结果是: "+message ); }
});
- 备份
Map<String, Object> args = new HashMap<String , Object>();
args.put("a1ternate-exchange" , "myAe");
channe1.exchangeDeclare( "norma1Exchange" , "direct" , true , fa1se , args);
channe1 . exchangeDeclare( "myAe " , "fanout" , true , fa1se , nu11) ;
channe1 .queueDec1are( "norma1Queue " , true , fa1se , fa1se , nu11);
channe1 .queueBind( "norma1Queue", "norma1Exchange" , " norma1Key");
channe1 .queueDec1are( "unroutedQueue " , true , fa1se , fa1se , nu11);
channel .queueBind( "unroutedQueue " , "myAe " , "");
上述代码,声明了两个交换机,norma1Exchange和myAe。norma1Exchang绑定了norma1Queue队列,myAe绑定了unroutedQueue队列,同时交换机norma1Exchange设置了一个备份交换机,其实就是myAe,只要norma1Exchange没路由成功的消息都会路由给备份交换机最后到unroutedQueue存储。
注意,建议备份交换机的类型用fanout,因为重新备份发送的消息路由键是和生产者发出的时候一样的。
过期时间
两种方法设置
- 通过队列设置,这时候队列内所有消息都拥有一样的过期时间
- 通过消息单独设置
tip:如果两个都设置了,谁的ttl小就遵循谁的
队列实例:
Map<String, Object> argss = new HashMap<String , Object>();
argss.put("x-message-ttl " , 6000);
channel . queueDeclare(queueName , durable , exclusive , autoDelete , argss) ;
死信
DLX(Dead-Letter-Exchange),死信交换器(死信邮箱),当消息在队列中变成死信之后就会路由到这。绑定DLX的队列就叫做死信队列。
死信场景:
- 消息被拒绝(Basic.Reject/Basic.Nack),并且设置requeue参数为false
- 消息过期
- 队列达到最大长度
实例:
channel . exchangeDeclare("dlx_exchange " , "dir ect "); // 创建 DLX: dlx_exchange
Map<String, Object> args = new HashMap<String, Object>();
args . put("x-dead-letter-exchange" , " dlx exchange ");
//为队列 myqueue 添加 DLX
channel . queueDeclare("myqueue" , false , false , false , args);
下面例子,normal指定了死信交换机和过期时间,过期时间是10秒,10秒后没有被消费就将消息路由到死信队列中
channel .exchangeDeclare("exchange.dlx" , "direct " , true);
channel . exchangeDeclare( "exchange.normal " , " fanout " , true);
Map<String , Object> args = new HashMap<String, Object>( );
args . put("x-message - ttl " , 10000);
args . put( "x-dead-letter-exchange " , " exchange . dlx");
args . put( "x-dead-letter-routing-key" , " routingkey");
channe1 .queueDec1are( " queue.norma1 " , true , fa1se , fa1se , args);
channe1 . queueBind( "queue.normal " , "exchange .normal" , "");
channe1 . queueDec1are( " queue.d1x " , true , false , false , null) ;
channel .queueBind( " queue.dlx" , "exchange.dlx " , Wr outingkey");
channel . basicPublish( " exchange.normal" , " rk" ,
MessageProperties.PERSISTENT_TEXT_PLAIN, "dlx " .getBytes()) ;
延迟队列
使用场景:
- 用户在支付一些商品时候,只是下单了还没支付,订单会存在一段时间,可以将订单放在延迟队列中,时间到了再处理未支付的订单
- 人们发送指令给一些设备,让他们定时处理某些任务,使用延时队列等待时间到再推送指令
使用:
配合TTL和DLX来使用,可以声明normal交换器和死信交换器,消费者订阅的是死信交换器,我们先将消息推送到normal中,并设置一定的过期时间,等待时间到因为无人消费(特地如此,以达到延时的目的)就路由给死信队列,这个时候消费者才会去消费。
同时生产者可以在发送消息的时候设置不同的路由键,以便处理不同类型的延时任务,比如10秒、1分钟等等。