Spring + RabbitMQ — Routing

G-mi
6 min readJun 16, 2019

--

延續上一個 RPC 範例,接著分享的是 Routing 模式,該範例僅實作 Direct Exchange,因為 Fanout、Topic 的作法都跟 Direct 差不多。

rabbit-config.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:rabbit="http://www.springframework.org/schema/rabbit"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/rabbit
http://www.springframework.org/schema/rabbit/spring-rabbit.xsd">

<rabbit:connection-factory id="connectionFactory" host="127.0.0.1" port="5672"
username="guest" password="guest" virtual-host="/" requested-heartbeat="60"/>
<rabbit:template id="amqpTemplate" connection-factory="connectionFactory" reply-timeout="10000"/>
<rabbit:admin connection-factory="connectionFactory"/>
<bean name="serializerMessageConverter" class="org.springframework.amqp.support.converter.SimpleMessageConverter"/>
<bean name="messagePropertiesConverter" class="org.springframework.amqp.rabbit.support.DefaultMessagePropertiesConverter"/>

<!-- RPC -->
...

<!-- Routing -->
<bean name="RoutingListener" class="com.example.mq.RoutingListener"/>

<rabbit:queue id="Routing"/>

<rabbit:direct-exchange name="notice-exchange">
<rabbit:bindings>
<rabbit:binding queue="Routing" key="Notice"/>
</rabbit:bindings>
</rabbit:direct-exchange>

<rabbit:listener-container connection-factory="connectionFactory">
<rabbit:listener ref="RoutingListener" queues="Routing"/>
</rabbit:listener-container>
</beans>

SendMessage.java (Client):

public class SendMessage {

@Autowired
private RabbitTemplate amqpTemplate;

...

public String sendToRouting(String message) {
try {
message = (message == null) ? "default" : message;
amqpTemplate.convertAndSend("notice-exchange", "Notice", message);
return "Send Message: '" + message + "' , Success!";
} catch (Exception e) {
System.out.println(e);
return e.getMessage();
}
}
}

RoutingListener.java (Server):

public class RoutingListener implements MessageListener {

@Override
public void onMessage(Message message) {
String messageBody = new String(message.getBody());
System.out.println("[Notice]: " + messageBody);
}
}

為了測試是不是會同時收到訊息,所以使用 IDEA 啟動三個 tomcat 來連結 RabbitMQ(也可以使用 docker)
可以看到下圖除了上個 RPC 範例的 queue 之外,還有另外三個 queue

RabbitMQ Management

運行結果:

因為當初是拿 RPC 的範例去改成 Direct,但那時候怎麼測試都只有一個 Server 端接收到訊息,在鬼打牆了一段時間後才發現是全部都註冊到同一個 queue 上才導致。
所以需要注意的一點是如果你需要發散訊息到各個 Server 端上時,在 config 中的 queue 千萬不能設定 name,而是讓他自動產生。

// 正確
<rabbit:queue id="Routing"/>
// 錯誤
<rabbit:queue name="Routing"/>

範例下載:https://github.com/zxcvb17295/SpringLab/tree/master/spring-rabbitmq

--

--