WCF4.0支持路由機制,通過RoutingService實現請求分發、攔截處理。
一、應用場景
1、暴露一個endpoint在外網,其余服務部署於內網;
2、請求分發,能對服務做負載功能;
二、WCF4.0 路由服務

圖1- WCF路由示意圖
WCF RoutingService使用了消息過濾器的功能,內置定義了6個過濾器滿足不同的需求:
1、ActionMessageFilter:滿足指定的操作集之一,也就操作匹配;
2、EndpointAddressMessageFilter:滿足指定的終結點地址;
3、XPathMessageFilter:使用 XPath指定匹配的條件,用於實現基於內容路由的核心消息過濾器;
4、MatchAllMessageFilter 與所有消息相匹配;
5、MatchNoneMessageFilter 與所有消息都不匹配;
對於以上默認提供的過濾器不能滿足需求,還可以通過創建自己的 MessageFilter 實現消息過濾器。如下我們通過一個demo實現wcf服務分發負載處理。
三、WCF RoutingService負載處理請求
1、創建一個WCF服務,名稱為:Aden.FK.WcfServiceA,基於console hosting實現,創建兩個ServiceHost。
(1)接口定義和實現為:
[ServiceContract]
public interface IWcfServiceA
{
[OperationContract]
int GetNumber();
[OperationContract]
string GetString();
}
(2)服務的實現:
public class WcfServiceA : IWcfServiceA
{
public int GetNumber()
{
string msg = "Service :" + OperationContext.Current.EndpointDispatcher.EndpointAddress.Uri;
Console.WriteLine(string.Format("print: {0}", msg));
return new Random().Next();
}
public string GetString()
{
string msg = "Service :" + OperationContext.Current.EndpointDispatcher.EndpointAddress.Uri;
Console.WriteLine(string.Format("print: {0}", msg));
return msg;
}
}
(3)創建服務host:
int num = 2;
int index = 0;
List<ServiceHost> serviceHost = new List<ServiceHost>();
for (int i = 1; i <= num; i++)
{
serviceHost.Add(new ServiceHost(typeof(WcfServiceA)));
}
serviceHost.ToList().ForEach(u =>
{
var netTcp = new NetTcpBinding();
netTcp.Security.Mode = SecurityMode.None;
u.AddServiceEndpoint(typeof(IWcfServiceA), netTcp, string.Format("net.tcp://127.0.0.1:910{0}/services/WcfServiceA{1}", ++index, index));
u.Open();
Console.WriteLine("{0} Service Start,Address is {1}", u.Description.Name, u.Description.Endpoints[0].Address.Uri);
}
);
2、創建一個路由服務,自定義擴展實現MessageFilter進行請求分發,路由與服務之間以TCP協議傳輸。
var serverEndpoints = new List<ServiceEndpoint>();
var netTcp = new NetTcpBinding();
netTcp.Security.Mode = SecurityMode.None;
serverEndpoints.Add(new ServiceEndpoint(new ContractDescription("IWcfServiceA"), netTcp, new EndpointAddress("net.tcp://127.0.0.1:9101/services/WcfServiceA1")));
serverEndpoints.Add(new ServiceEndpoint(new ContractDescription("IWcfServiceA"), netTcp, new EndpointAddress("net.tcp://127.0.0.1:9102/services/WcfServiceA2")));
using (var router = new ServiceHost(typeof(RoutingService)))
{
int index = 10;
string routerAddress = "net.tcp://127.0.0.1:8101/router/routerendpoint";
router.AddServiceEndpoint(typeof(IRequestReplyRouter), netTcp, routerAddress);
var config = new RoutingConfiguration();
LoadBalancerFilter.EndpointsNumber = 2;
serverEndpoints.ForEach(x => config.FilterTable.Add(new LoadBalancerFilter(), new[] { x }, index--));
router.Description.Behaviors.Add(new RoutingBehavior(config));
var debugBehavior = router.Description.Behaviors.Find<ServiceDebugBehavior>();
debugBehavior.IncludeExceptionDetailInFaults = true;
if (router.State != CommunicationState.Opening)
router.Open();
while (Console.ReadKey().Key == ConsoleKey.Enter)
{
break;
}
router.Close();
}
3、創建一個客戶端,客戶端與路由之間以TCP協議傳輸。
var endpoint = new EndpointAddress("net.tcp://127.0.0.1:8101/router/routerendpoint");
var netTcp = new NetTcpBinding();
netTcp.Security.Mode = SecurityMode.None;
var client = ChannelFactory<IWcfServiceA>.CreateChannel(netTcp, endpoint);
while (Console.ReadKey().Key == ConsoleKey.Enter)
{
Console.WriteLine("--" + client.GetNumber());
}
四、運行結果
1、客戶端調用

2、服務端顯示,每次將請求分發到不同的服務處理。

五、總結
以上是一個簡單的路由服務例子,可以根據實際情況擴展路由功能,實現上述描述是應用場景。考慮到路由的壓力,可以在路由前架上Nginx負載。
出處: http://www.cnblogs.com/Andon_liu
關於作者:專注於微軟平台項目架構、管理。熟悉設計模式、領域驅動、架構設計、敏捷開發和項目管理。現主要從事ASP.NET MVC、WCF/Web API、SOA、MSSQL、redis方面的項目開發、架構、管理工作。 如有問題或建議,請一起學習討論!
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接。
如有問題,可以郵件:568773262@qq.com 聯系我,謝謝。
