目錄
本篇主要介紹在Mule ESB中控制訊息的流向。控制訊息的流向有很多不同的場景,資料的路由,資料的拆分和組合,資料的排序,資料的分發等。資料路由是ESB平臺上最基本,也是最重要的功能之一,完整的ESB平臺都會有相對應的功能。ESB基本的功能可分成訊息路由,訊息傳輸和訊息轉換等,後續幾篇Mule ESB開發教程我們會陸續講解這些功能。
Mule ESB同樣具有很多的訊息路由元件。作為開源ESB產品中很成熟的平臺,Mule ESB的發展狀態非常好,經過多年的發展,2017年在紐交所成功上市。Mule ESB擁有眾多的企業案例,我們作為MuleSoft的重要合作伙伴,使用Mule ESB企業版開發實施,或者Mule ESB社群版開發實施,幫助國內眾多的行業標杆客戶成功上線企業整合專案。
Mule ESB的原始碼託管在GitHub上,擁有非常詳細的英文文件,Mule ESB的中文文件資料和開發教程卻非常少,我們使用8篇文章來寫基礎Mule ESB中文開發教程,一起為開源軟體做貢獻。
- EnjoyingSoft之Mule ESB開發教程第一篇:初識Mule ESB
- EnjoyingSoft之Mule ESB開發教程第二篇:Mule ESB基本概念
- EnjoyingSoft之Mule ESB開發教程第三篇:Mule message structure - Mule message結構
- EnjoyingSoft之Mule ESB開發教程第四篇:Mule Expression Language - MEL表示式
- EnjoyingSoft之Mule ESB開發教程第五篇:控制訊息的流向-資料路由
- EnjoyingSoft之Mule ESB開發教程第六篇:Data Transform - 資料轉換
- EnjoyingSoft之Mule ESB開發教程第七篇:SOAP Web Service的消費和建立
- EnjoyingSoft之Mule ESB開發教程第八篇:使用API構建Rest Service
1. 使用場景
我們來看一個常見的應用場景。我們的整合應用可以接收客戶端提交訂單的請求,有多種不同型別的客戶端。手機客戶端是一個App,我們在App上使用的訊息格式通常是輕量級的JSON格式。而PC客戶端是一個Windows時代的產物,它仍然使用XML格式。我們的整合應用在接收到訂單請求後,會根據訂單的類別分發到不同的倉庫,訂單類別儲存在訂單內容的OrderType欄位中。
2. 基於訊息頭的路由
我們首先要區分訂單的格式,因為JSON和XML的處理邏輯是完全不同的。在Mule中我們可以使用MEL的JSON Path來解決JSON檔案的解析,XML Path來解決XML檔案的解析。MEL的詳細用法可以參考上一篇文章。訂單的格式通常會放在訊息頭上傳遞,而Mule Message中對應訊息頭的部分就是Message Inboud Properties。
2.1 使用JSON提交訂單的訊息
{
"OrderType": "Book",
"TotalAmount": 1000,
"OrderLines": [{
"ProductName": "Learn English",
"Qty": 3,
"Price": 300
}, {
"ProductName": "Lean Mule ESB",
"Qty": 1,
"Price": 100
}]
}
使用Postman提交JSON,注意Content-Type設定為application/json。
通過Postman的Preview可以看到,實際上Http的Request頭資訊上設定了Content-Type欄位為application/json。
2.2 使用XML提交訂單的訊息
<?xml version="1.0" encoding="UTF-8"?>
<OrderInfo>
<OrderType>Book</OrderType>
<TotalAmount>1000</TotalAmount>
<OrderLines>
<OrderLine>
<ProductName>Learn English</ProductName>
<Qty>3</Qty>
<Price>300</Price>
</OrderLine>
<OrderLine>
<ProductName>Learn Mule ESB</ProductName>
<Qty>1</Qty>
<Price>100</Price>
</OrderLine>
</OrderLines>
</OrderInfo>
使用Postman提交XML,注意Content-Type設定為application/xml。
通過Postman的Preview可以看到,實際上Http的Request頭資訊上設定了Content-Type欄位為application/xml。
2.3 使用Choice元件判斷訂單格式
Mule ESB最基本的路由元件就是Choice元件,元件類似於我們在程式語言中的if/esle if/else。訂單的格式是存放在Message Inbound Properties中的。這裡就使用Choice元件來判斷訂單的格式。
Mule XML Config:
<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns:http="http://www.mulesoft.org/schema/mule/http" xmlns="http://www.mulesoft.org/schema/mule/core" xmlns:doc="http://www.mulesoft.org/schema/mule/documentation"
xmlns:spring="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-current.xsd
http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
http://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd">
<http:listener-config name="HTTP_Listener_Configuration" host="0.0.0.0" port="8081" doc:name="HTTP Listener Configuration"/>
<flow name="flow-control">
<http:listener config-ref="HTTP_Listener_Configuration" path="/" doc:name="HTTP"/>
<choice doc:name="Choice">
<when expression="#[message.inboundProperties['content-type'] == 'application/json']">
<logger message="JSON" level="INFO" doc:name="JSON"/>
</when>
<when expression="#[message.inboundProperties['content-type'] == 'application/xml']">
<logger message="XML" level="INFO" doc:name="XML"/>
</when>
<otherwise>
<logger message="Error" level="INFO" doc:name="Error"/>
</otherwise>
</choice>
</flow>
</mule>
Mule UI Config:
通過Choice元件所支援的MEL語法,我們就能通過判斷mule message inboundProperties來確定訂單格式。需要注意的是,圖上所示的Default是選擇的最後一個路徑,實際是if,else if,else,end if這個路徑中的else路徑。
3. 基於訊息內容的路由
通過訊息頭的判斷,我們已經可以區分JSON格式和XML格式訂單,那麼如果區分訂單型別呢,這裡就需要用到基於訊息內容的路由,我們對前面的程式碼做改進,同時引入訊息佇列。
Mule XML Config:
<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns:jms="http://www.mulesoft.org/schema/mule/jms" xmlns:http="http://www.mulesoft.org/schema/mule/http" xmlns="http://www.mulesoft.org/schema/mule/core" xmlns:doc="http://www.mulesoft.org/schema/mule/documentation"
xmlns:spring="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-current.xsd
http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
http://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd
http://www.mulesoft.org/schema/mule/jms http://www.mulesoft.org/schema/mule/jms/current/mule-jms.xsd">
<http:listener-config name="HTTP_Listener_Configuration" host="0.0.0.0" port="8081" doc:name="HTTP Listener Configuration"/>
<jms:activemq-connector name="Active_MQ" brokerURL="tcp://192.168.63.1:61616" validateConnections="true" doc:name="Active MQ"/>
<flow name="flow-control">
<http:listener config-ref="HTTP_Listener_Configuration" path="/" doc:name="HTTP"/>
<choice doc:name="Choice">
<when expression="#[message.inboundProperties['content-type'] == 'application/json']">
<set-variable doc:name="orderType" value="#[json:/OrderType]" variableName="orderType"/>
<choice doc:name="Choice">
<when expression="#[flowVars.orderType == 'Book']">
<jms:outbound-endpoint queue="bookQ" connector-ref="Active_MQ" doc:name="bookQ"/>
</when>
<when expression="#[flowVars.orderType == 'Tool']">
<jms:outbound-endpoint queue="toolQ" connector-ref="Active_MQ" doc:name="toolQ"/>
</when>
<otherwise>
<jms:outbound-endpoint queue="DLQ" connector-ref="Active_MQ" doc:name="DLQ"/>
</otherwise>
</choice>
</when>
<when expression="#[message.inboundProperties['content-type'] == 'application/xml']">
<set-variable doc:name="orderType" value="#[xpath://OrderInfo/OrderType]" variableName="orderType"/>
<choice doc:name="Choice">
<when expression="#[flowVars.orderType == 'Book']">
<jms:outbound-endpoint queue="bookQ" connector-ref="Active_MQ" doc:name="bookQ"/>
</when>
<when expression="#[flowVars.orderType == 'Tool']">
<jms:outbound-endpoint queue="toolQ" connector-ref="Active_MQ" doc:name="toolQ"/>
</when>
<otherwise>
<jms:outbound-endpoint queue="DLQ" connector-ref="Active_MQ" doc:name="DLQ"/>
</otherwise>
</choice>
</when>
<otherwise>
<jms:outbound-endpoint queue="DLQ" connector-ref="Active_MQ" doc:name="DQL"/>
</otherwise>
</choice>
</flow>
</mule>
Mule UI Config:
4. 其他控制流向的元件
除了使用Choice元件改變Flow執行路徑以外,還要很多控制流向的元件。比如Round-Robin,Resequencer,Scatter-Gather,Splitter,Aggregator等元件。這些元件的用法各不相同,這裡主要講一下Round-Robin的用法。Round-Robin是一種輪詢排程演算法,在負載均衡的策略裡面經常見到Round-Robin,輪詢排程演算法的原理是每一次把來自使用者的請求輪流分配給內部中的伺服器,從1開始,直到N(內部伺服器個數),然後重新開始迴圈。
Mule的Round-Robin元件也是類似的思路,輪詢執行Flow中的分支路徑。舉例如下,我們接收到使用者的檢索請求,每次請求我們使用不同的執行路徑,第一次使用Bing搜尋,第二次使用Google,第三次使用Baidu。
Mule XML Config:
<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns:http="http://www.mulesoft.org/schema/mule/http" xmlns="http://www.mulesoft.org/schema/mule/core" xmlns:doc="http://www.mulesoft.org/schema/mule/documentation"
xmlns:spring="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-current.xsd
http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
http://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd">
<http:listener-config name="HTTP_Listener_Configuration" host="0.0.0.0" port="8081" doc:name="HTTP Listener Configuration"/>
<flow name="round-robin-flow">
<http:listener config-ref="HTTP_Listener_Configuration" path="/" doc:name="HTTP"/>
<round-robin doc:name="Round Robin">
<set-payload value="Baidu" doc:name="Baidu"/>
<set-payload value="Google" doc:name="Google"/>
<set-payload value="Bing" doc:name="Bing"/>
</round-robin>
</flow>
</mule>
Mule UI Config:
本文同步發文於EnjoyingSoft Blogs ,CSDN,簡書
訪問EnjoyingSoft 網站,獲取更多Mule ESB 社群版 實施幫助。
歡迎轉載,但必須保留原文和此段宣告,且在文章頁面明顯位置給出原文連結,否則保留追究法律責任的權利。