1. 程式人生 > >[SOA] Mule ESB 3.x 入門(三)—— 訊息路由

[SOA] Mule ESB 3.x 入門(三)—— 訊息路由

在前面兩篇博文基礎上,繼續來看看如何利用 Mule 來實現簡單的訊息路由。訊息路由是ESB平臺上最基本最重要的功能,它是指通過一定的規則將訊息從一個端點發送到另一端點。通常ESB平臺上會統一管理很多服務,為了便於使用和管理通常會對外暴露一個唯一入口,通過請求攜帶的路由資訊來進行分發。

如下圖所示:

ESB平臺將維護一套路由表,根據請求中的路由資訊來做處理。這個路由資訊就是指在路由表中能唯一識別真實服務資訊(資料)的相關資料(key),利用Mule Message我們可以在以下幾個地方做功課。

1. 利用Http Header 來傳送路由資訊
在 Http Header 中新增自定義資訊,ESB平臺根據Header的資料進行處理。
這種方式實施比較簡單,接入方需要修改一點程式碼即再呼叫HttpRequest之前需要按照約定封裝Header。
OAuth 認證也是通過Header攜帶Auth資訊來做的。

2. 利用URL來傳送路由資訊
通過 QueryString(或者是rest風格的URL) 傳遞資訊,這種方式實施更簡單,接入方甚至無須直接修改程式碼改改配置檔案的URL即可。
但通過QueryString傳遞資料比較暴露而且有長度限制。

3. 利用Http Body 來傳送路由資訊
將路由資訊存放在 Http Body裡,這種方式實施比較麻煩,接入方需要修改不少程式碼而且極不靈活。
需要整體規劃,將報文格式全部統一下來。

接下來舉個栗子,看看 Mule 3.x 如何實現訊息路由的(方式2)。
實現方式2——根據URL路由資訊處理,核心很簡單,通過一個groovy 指令碼來處理(Mule 自帶Choose元件,但還是自己寫指令碼靈活)

import org.apache.log4j.*;
Logger logger = LogManager.getLogger("router");

class Router implements Serializable {
	def serviceId, address, contentType
} 
List routers = [
	new Router(serviceId:"svc001", address:"localhost:11788/Service1.svc"),
	new Router(serviceId:"svc002", address:"localhost:11789/Service1.svc"),
	new Router(serviceId:"svc003", address:"localhost:11790/Service1.svc"),
	new Router(serviceId:"svc004", address:"localhost:11791/Service1.svc"),
];

def requestSvcId = message.getInboundProperty("http.relative.path");
logger.info "======== request serviceId: ${requestSvcId}"

def requestContentType = message.getInboundProperty("Content-Type");
logger.info "======== request contentType: ${requestContentType}"

message.setOutboundProperty("SOAPAction", message.getInboundProperty("SOAPAction"));
message.setOutboundProperty("Content-Type", requestContentType);

def currentRouter = routers.find {
	r -> r.serviceId == requestSvcId;
}

logger.info "======== service address: ${currentRouter.address}"
if (currentRouter != null) {
	if (requestContentType != '') {
		currentRouter.contentType = requestContentType
	}
	message.setSessionProperty("router-info", currentRouter)	
}

message

Mule Flow:

<?xml version="1.0" encoding="UTF-8"?>

<mule xmlns:scripting="http://www.mulesoft.org/schema/mule/scripting" 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" version="CE-3.3.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="
http://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd 
http://www.mulesoft.org/schema/mule/scripting http://www.mulesoft.org/schema/mule/scripting/current/mule-scripting.xsd 
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 ">
    <flow name="mule-esb-route-sampleFlow1" doc:name="mule-esb-route-sampleFlow1">
        <http:inbound-endpoint exchange-pattern="request-response" address="http://localhost:9999/esb" doc:name="HTTP" />
        
        <logger message="---------- #[groovy:message.toString()]" level="INFO" doc:name="log request"/>
        
        <scripting:component doc:name="Groovy">
            <scripting:script engine="Groovy" file="router.groovy"/>
        </scripting:component>
        <http:outbound-endpoint exchange-pattern="request-response" 
              address="http://#[groovy:message.getSessionProperty('router-info').address]"
              doc:name="HTTP"/>
         
    </flow>
</mule>

接入方通過向 http://localhost:9999/esb/{serviceId} 來發送請求使用服務。groovy 中定義的 List routers 即可看成是ESB平臺內部管理的路由表
(實際使用時會儲存在資料庫中或者快取容器中便於即時修改維護),Mule 通過 relative path 獲取的 {serviceId} 來做對映。
最後將變數交給 Mule 的 <http.outbound-endpoint> 將請求轉發到真實服務上去。

順便做個廣告,下面是我在 InfoQ 做的分享的PPT和視訊,有興趣的童鞋請移步觀看。