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 聯系我,謝謝。