WCF 服務啟動後,訊息如何從網路抵達具體服務實例方法?本文揭示 ServiceHost、ChannelDispatcher、ChannelListener、EndpointDispatcher 協作流程,及雙重 MessageFilter(AddressFilter + ContractFilter) 篩選機制。
配置範例:同一服務 3 個端點,前 2 個共用 listenUri=6666,第 3 個預設 listenUri=7777。
<service name="CalculateService">
<endpoint address="https://127.0.0.1:9999/calculateservice" listenUri="https://127.0.0.1:6666/calculateservice" />
<endpoint address="https://127.0.0.1:8888/calculateservice" listenUri="https://127.0.0.1:6666/calculateservice" />
<endpoint address="https://127.0.0.1:7777/calculateservice" />
</service>
ServiceHost.Open() 執行時:
驗證代碼輸出:
ChannelDispatcher 1: ListenUri: https://127.0.0.1:6666/calculateservice EndpointDispatcher 1: EndpointAddress: https://127.0.0.1:9999/calculateservice EndpointDispatcher 2: EndpointDispatcher 2: EndpointAddress: https://127.0.0.1:8888/calculateservice ChannelDispatcher 2: ListenUri: https://127.0.0.1:7777/calculateservice EndpointDispatcher 1: EndpointAddress: https://127.0.0.1:7777/calculateservice
網路請求
→ ChannelListener.AcceptChannel() 建立輸入通道堆疊接收訊息
→ ChannelDispatcher 接收訊息
→ 遍歷其 EndpointDispatcher 集合
→ 呼叫 AddressFilter.Match(msg) AND ContractFilter.Match(msg)
→ 雙雙 true → 該 EndpointDispatcher 處理後續(實例化、調度、調用)
| Filter | 匹配邏輯 | 預設用途 |
|---|---|---|
| EndpointAddressMessageFilter | SOAP To 標頭 == 端點 Address | AddressFilter (預設) |
| PrefixEndpointAddressMessageFilter | SOAP To 標頭以端點 Address 為前綴 | AddressFilter (Prefix 模式) |
| ActionMessageFilter | SOAP Action 標頭在端點合約操作清單中 | ContractFilter (預設) |
| XPathMessageFilter | 自訂 XPath 匹配 SOAP 內容 | 擴展 |
| MatchAllMessageFilter | 永遠 true | AddressFilter (Any 模式) |
| MatchNoneMessageFilter | 永遠 false | 測試/攔截 |
透過 [ServiceBehavior(AddressFilterMode = AddressFilterMode.Any)] 覆蓋預設精確匹配:
Exact(預設):EndpointAddressMessageFilterPrefix:PrefixEndpointAddressMessageFilterAny:MatchAllMessageFilter(忽略 To 標頭,攔截所有訊息)應用場景:路由器、訊息攔截器、負載平衡器需設 Any 接收任意目標訊息。
實作 IEndpointBehavior,在 ApplyDispatchBehavior 中替換 EndpointDispatcher.AddressFilter/ContractFilter:
public class CustomFilterBehavior : IEndpointBehavior {
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher dispatcher) {
dispatcher.AddressFilter = new MyCustomFilter();
dispatcher.ContractFilter = new ActionMessageFilter(new[] { "CustomAction" });
}
}
Any。理解分發管線,是實作 WCF 路由、攔截、多租戶隔離的基石。