开始
解决的问题就是消息真的被路由了吗?消息发给exchange路由到各个队列里面。如果exchange没有相应的路由规则,那么这条消息就被丢弃了。我们可以做一个特殊的设置,让exchange在路由消息的时候,如果没有找到对应的队列。可以不丢弃这条消息。将这条消息给返回回来。
如果exchange丢弃了这条消息的话。就会造成我们的订单业务异常,消息丢弃。
所以我们要使用消息返回机制。
大概讲解消息返回机制的原理。如果没有找到消息的队列会回调Return Listener方法,我们提前声明好这个方法就会被调用,里面我们可以写一些对消息没有被路由的异常的业务处理。
代码实战
利用商家微服务来实现消息的返回机制。
ctrl+鼠标左键。
ctrl+鼠标左键
IDEA的左下方
第三个basicPublish 有个mandatory的参数。
用第二个就可以了
我们在原来的返回的方法里面加上mandatory参数 设置为true就可以了。开启了这个选项之后,我们的rabbitMQ在收到消息但是无法路由的时候,就会调用发送方的returnListener方法,
实现发送方的returnListener
加载channel上。
我们两个returnListener这两个方法都尝试一下,括号内要new一个returnListener
当我们发送的消息无法路由的时候,handleReturn会被调用,
调用的时候后面的这些参数会自动传递给我们。returnCode有点像Http的Code,是用一个数字 字码表示一个消息。路由的结果。 replyText是返回的信息,properties是消息的源数据,body就是消息的内容了。
如果这个log被打印出来就说明消息被返回回来了
大括号在log4j里面是占位符。
拼接参数,输出出来
body是字节数组,我们想看字符串。用String的构造方法就可以把字符串数组转成字符串了。
启动orderService和商家的微服务。用postman发送一个新订单的请求。试一下。
订单微服务在收到了订单 马上发消息给商家微服务
发送完消息后,他也收到了消息的发送端确认
切换到商家微服务。处理了消息了也把消息往回发了。我们要演示路由不了这个消息。
这是因为我们的消息路由成功了。我们在启动的时候就绑定了。
我故意让它路由不了
解绑,我们把这个队列的路由给他去掉。
解绑后。这样商家微服务再往回发的时候就找不到路由了。
再来发一个消息 试试
orderService没有收到商家回复的消息
我们再来看下商家的微服务。发完之后没有log
发送消息失败没有被路由,按说会调用handleReturn这个方法。
我们的事件是绑定在channel上的。如果这个channel被关了。 我们绑定这些属性、回调方法等都没有用。
我们的channel是在try里面声明的,
当他走出这个try快的时候就会自动的被关掉。这就叫做autoClosable
所以我们发送完消息,它就会被自动的关掉了。因为它走出了try块。那我们之前注册的returnListener就不管用了。
发送完消息 不让这个channel被关闭呢?一种是不要在try里面去声明channel
还有一种方法是。线程休眠1秒,这样try块就没走出来,那么这个channel就关不掉。我们的returnListener就可以被调用。
把这个异常声明一下
重启下 商家服务 测试
消息发送后没有被路由
返回的消息NoRoute
exchange和routingKey
最后是消息体的内容
另外一种returnListener
注释原来的代码
就一个handle方法。
看一下returnMessage类里面的属性。
通过对象可以get到各个属性
入参太多就可以换成对象的形式
重启服务测试
return了一个对象。这里输出的是对象的地址。
发送消息和回调不是一个线程。是异步的