程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> .NET通信框架WCF介紹

.NET通信框架WCF介紹

編輯:關於.NET
再見WCF

轉眼微軟的WCF已走過十個年頭,它是微軟通信框架的集大成者,將之前微軟所有的通信框架進行了整合,提供了統一的應用方式。記得從自己最開始做MFC時,就使用過Named Pipe命名管道,之後做Winform時,使用過Remoting,再之後做B/S架構時,就會經常使用.NET平台下的Web Service,直到使用上WCF。看上去有了一些WCF的使用經驗,實則不然,比如對安全、分布式事務、可靠會話等主題仍然接觸甚少,因而決定重新回顧學習一下相關知識,尤其是對WCF框架的理解(已於2015年開源,可下載源碼,https://github.com/dotnet/wcf/)。很多大公司都構建了自己的SOA框架,不過基本上都是以WCF框架為基礎,對其進行了相應的簡化和微調。因此學習該框架,可以觸類旁通,對應用和搭建自有的SOA架構也有很大的幫助。當然,個人認為WCF已足夠強大,並且其管道模式有極強的擴展性,可以通過自定義綁定滿足絕大部分的需求。整個學習過程將參考蔣金楠大師的《WCF全面解析》一書,本章主要介紹WCF的基本概念和傳說中的"ABC",Let go。

 

在介紹WCF之前,不得不提一個稱為SOA(Service Orientation Architecture)的概念,也就是我們常說的面向服務的架構,這是一個很老的概念了。即使如此,如果要以SOA為題,寫一遍2000字的論文,感覺仍然很難下手,說明對概念理解還不夠深刻(之後打算專門撰文一篇,為軟考做准備)。實際上,其是構建大型軟件應用的一種重要理念,並不是什麼具體的技術或者平台。這個提法的出現其實有一個過程,就是在過去軟件的架構說到底是基於數據庫的(至於什麼基於組件、基於領域等概念,其實是在應用范疇的,而不是架構范疇的概念),比如不同的兩個系統的交互,往往是通過公用同一個數據庫,或者通過Job等方式同步兩個應用各自的數據,最終都是以數據為中心的。這種架構的優點是開發快速,與數據庫緊密相連,事務性很好,適用於中小系統;缺點是因為各個系統都可以直接和數據庫連接,層次不清晰,當系統越來越龐大時,運維成本越來越大,此外,其可控性、安全性、擴展性也相對較差。而SOA是以上缺點的一個很合適的解決方案,比如:基於開放的標准,使得可以跨平台調用(.NET, J2EE…);基於自治的服務,便於安全性的控制和服務限流;基於契約,將各個子系統解耦。

接下來,詳細回顧一下微軟的所有分布式通信技術,包括如下4種具體技術。

COM和DCOM:COM基於組件設計,通過GUID唯一標識、IKnown與其他接口進行互操作,例如ActiveX,DCOM是COM的分布式版本,提供了可靠傳輸、安全等支持。

.NET Remoting:其基於信道棧的"管道式"消息處理和傳輸機制,支持TCP,UDP等傳輸協議。

Web Service:其提供跨平台的互操作性,構建在ASP.NET平台上,基於一系列開放的標准,包括XML、XSD、SOAP和WSDL等。此外,微軟還通過WSE(Web Service Enhancement)組件為Web服務提供WS-*規范的支持。

MSMQ(Message Queuing):MSMQ通過異步通信的方式,解耦了服務的提供者和調用者,為系統提供了可觀的伸縮性和可用性,並支持可靠信息傳輸、錯誤處理和對事務的支持。

Tip:

J2EE架構其實也有相對應的技術,例如官方的Java RPC,WebService,JMS,第三方的Axis,RabbitMQ等。

 

本節最後通過一個非常簡單的自寄宿的WCF示例來熟悉WCF的應用以及引入傳說中的三要素"ABC",Address服務地址、Binding服務綁定、Contract服務契約,之後將分節進行詳細介紹

 Contract:
 [ServiceContract]
 public interface IAddService
 {
 [OperationContract]
 CompositeType Add(CompositeType a, CompositeType b);
 }
 [DataContract]
 public class CompositeType
 {
 [DataMember]
 public int PartA { get; set; }
 [DataMember]
 public string PartB { get; set; }
 }
 
 public class AddService : IAddService
 {
 public CompositeType Add(CompositeType a, CompositeType b)
 {
 return new CompositeType() { PartA = a.PartA + b.PartA, PartB = a.PartB + b.PartB };
 }
 }
 
 Host:
 static void Main(string[] args)
 {
 using (var host = new ServiceHost(typeof(AddService)))
 {
 host.Opened += (target, eventArgs) => Console.WriteLine("AddService已經啟動,請按任意鍵終止服務!");
 host.Open();
 Console.Read();
 }
 }
 
 Config:
 <system.serviceModel>
 <behaviors>
 <serviceBehaviors>
 <behavior name="metadataBehavior">
 <serviceMetadata httpGetEnabled="True" httpGetUrl="http://127.0.0.1:9901/addservice/metadata"/> 
 </behavior>
 </serviceBehaviors>
 </behaviors>
 <services>
 <service name="Sory.Entertainment.WCF.AddService" behaviorConfiguration="metadataBehavior">
 <endpoint address="http://127.0.0.1:9901/addservice" binding="wsHttpBinding" contract="Sory.Entertainment.WCF.IAddService"/>
 </service>
 </services>
 </system.serviceModel>
 
 Client:
 static void Main(string[] args)
 {
 using (var client = new WcfService.AddServiceClient())
 {
 var result = client.Add(new WcfService.CompositeType { PartA = 1, PartB = "Hello, " }, new WcfService.CompositeType { PartA = 2, PartB = "World!" });
 
 Console.WriteLine(string.Format("PartA: {0}, PartB: {1}", result.PartA, result.PartB));
 }
 Console.Read();
 }
View Code

 

本節將介紹URI、端口共享、請求監聽和消息分發等概念。正如之前所說的,WCF服務是通過終結點EndPoint發布,而終結點由地址、綁定和契約三要素組成,其中地址用於定位服務,並提供額外的尋址信息和認證信息。既然是服務定位,首先引入URI的概念,URI的全稱為Uniform Resource Identifier統一資源標識,其形式是,[Schema傳輸協議]://[主機名|域名|IP地址]:[端口號]/[資源路經],其中支持的協議類型如下表所示。

協議類型

解釋

HTTP/HTTP

前者是互聯網時代的核心--超文本傳輸協議,其是建立在TCP/IP協議簇上應用層協議。特點無狀態、無連接、提供簡單請求-回復消息傳輸方式;後者是采用了SSL(TLS)的HTTP,提供數據加密,實際上,大部分主流網站已實現全站HTTPS。

Net.TCP

TCP全稱傳輸控制協議,屬於傳輸層協議,基於網絡層IP協議,是應用層HTTP協議的基礎。其特點是有狀態、支持全雙工、支持可靠通信,其是基於連接的協議,在數據傳輸前通過3次"握手"創建連接,在傳輸結束後,通過4次"握手"終止連接。

Net.Pipe

命名管道是Windows等操作系統實現跨進程通信(Inter Process Communication, IPC)的標准實現方式,雖然命名管道本身可以跨機器通信,不過WCF中的命名管道專注於同一台機器中的跨進程通信,因此其主機名為localhost,此外由於基於同一台機器,端口變得沒有意義。

Net.Msmq

消息隊列提供了支持離線的通信機制,其包括公共消息隊列和私有消息隊列兩種方式,前者需要注冊到AD域中。此外,除了存儲業務數據消息的普通隊列之外,還有存儲消息拷貝的日志隊列、存儲確認消息的管理隊列、存儲回復消息的回復隊列和存儲死信消息的死信隊列等。

其URI格式為: net.msmq://sory.com/private/xxxservice

 

之前提及的核心概念終結點在WCF中,通過System.ServiceModel.Description.ServiceEndpoint類表示,其包括Address、Binding、Contract三個核心屬性。其中的Address是EndpointAddress的實現類,其包含UriHeaders、Identity三個屬性,Uri即是服務的唯一標識,也是服務的目標地址,且這個地址可以使物理的,也可以是邏輯的。這兒的Headers其實就是SOAP消息中的消息頭(類似於Http協議的,也包括消息頭和消息體,前者主要提供一些控制信息,後者存放數據部分),它默認通過DataContractSerializer進行序列化和反序列化,最終轉化為SOAP消息的MessageHeader,相應配置如下所示,添加了服務端消息頭後,在客戶端也需要增加相應消息頭,否則會被地址過濾器給過濾掉(之後的客戶端通過ChannelFactory調用服務的示例中可以看到)。

 <endpoint address="http://127.0.0.1:9901/addservice" binding="wsHttpBinding" contract="Sory.Entertainment.WCF.IAddService">
 <headers>
 <authentication xmlns="http://www.sory.com/">{12345678}</authentication>
 </headers>
 </endpoint>
View Code

補充一點的是,可以通過將服務的ServiceBehavior特性中的AddressFilterModel屬性設置為Any,跳過消息頭的檢驗。

 

在基礎概念一節的代碼示例中,可以看到WCF通過ServiceHost完成服務寄宿,其中通過AddServiceEndpoint實現終結點的添加,當然也可以通過配置文件的方式添加終結點,在配置文件的<system.serviceModel>模塊的<service>子節點中添加<endpoint>,並補全address、binding、contract屬性,注意在IIS寄宿的情況下,無需提供address,因為.svc文件的地址就是服務的地址。同時,可以通過ServiceHost的Description屬性(.NET中習慣使用Description獲取元數據相關信息,無論是哪一種框架)獲取終結點和服務行為的相關信息。

此外,除了使用絕對地址來指定某個服務的終結點地址外,還可以通過"基地址+相對地址"的方式,其配置形式如下,需要注意一種類型的協議只能有一個基地址,並且當一個服務實現類同時實現了多個服務接口時,該終結點地址可以共享。

 <service name="XXX" behaviorConfiguration="XXX">
 <host>
 <baseAddresses>
 <add baseAddress="net.tcp://127.0.0.1/baseservice"/>
 </baseAddresses>
 </host>
 </service>
View Code

客戶端通過服務代理實現對服務的調用,包括兩種方式:通過服務引用或者借助SvcUtil.exe工具來生成服務代理類,該生成類繼承自ClientBase<TChannel>;直接通過ChannelFactory<TChannel>創建服務代理。前者比較簡單,只需要在<system.serviceModel>的子節點<client>中添加對應的<endpoint>節點,然後直接生成的對應的Client類即可,後者如下所示。

 var uri = new Uri("http://127.0.0.1:9901/addservice");
 var header = AddressHeader.CreateAddressHeader("authentication", "http://www.sory.com/", "{12345678}");
 var address = new EndpointAddress(uri, header);
 var binding = new WSHttpBinding();
 var contract = ContractDescription.GetContract(typeof(IAddService));
  
 var endpoint = new ServiceEndpoint(contract, binding, address);
 using (var factory = new ChannelFactory<IAddService>(endpoint))
 {
 var channel = factory.CreateChannel();
 var result = channel.Add(new CompositeType { PartA = 1, PartB = "Hello, " }, new CompositeType { PartA = 2, PartB = "World!" });
 Console.WriteLine(string.Format("PartA: {0}, PartB: {1}", result.PartA, result.PartB));
 }
View Code
  • 端口共享

在Windows系統,為了安全,常常只開發少量端口,當有大量應用需要使用不同端口時,會顯得捉襟見肘,因此多個應用共享同一個端口顯得很有必要。對於Http/Https協議來說,由於其可以通過IIS來管理應用,其自身通過HTTP.SYS已經實現了80|443端口的共享。而對於TCP協議來說,其通過一個Windows服務(名稱為Net.Tcp Port Sharing Service)來管理,可以通過如下方式實現其共享。

 <bindings>
 <netTcpBinding>
 <binding name="portSharingBinding" portSharingEnabled="true"></binding>
 </netTcpBinding>
 </bindings>
View Code
  • 邏輯地址和物理地址

之前在EndpointAddress中提及的Uri屬性表示服務的邏輯地址,而物理地址對於服務端來說是監聽地址,對於客戶端來說是消息真正發送的目標地址。默認情況下,兩個地址是統一的,但在需要中介進行消息轉發的場景下,需要將兩者分離。

對於服務端,可以設置終結點的ListenUri的屬性和ListenUriMode屬性(包括Explicit和Unique,前者嚴格使用ListenUri作為最終的監聽地址,後者將通過不同的策略保證監聽地址的唯一性,如針對端口共享的情況,將在默認Uri後加GUID以作識別),共同完成該需求,示例如下。

示例如下。

<endpoint address="http://127.0.0.1:9901/addservice" listenUri="http://127.0.0.1:9900/addservice" listenUriMode="Unique" …/>

對於客戶端,需要借助ClientViaBehavior這一終結點行為來實現,示例如下。

 <behaviors>
 <endpointBehaviors>
 <behavior name="clientViaBehavior">
 <clientVia viaUri="http://127.0.0.1:9900/addservice"/>
 </behavior>
 </endpointBehaviors>
 </behaviors>
 <client >
 <endpoint behaviorConfiguration="clientViaBehavior"></endpoint>
 </client>
View Code

補充:行為這個概念在WCF中非常的重要,很多的功能都是通過相應的行為實現的,接下來進行簡要介紹。如果說契約是客戶端和服務端達成的某種共識,是雙邊協議,而行為則是客戶端或服務端在本地實現某個功能的一種方式,是一種單邊行為。WCF提供了4種類型的行為,包括服務行為、契約行為、終結點行為和操作行為,它們一般可以通過特性或者配置文件的方式進行設置。

 

  • 請求監聽和消息分發

這部分內容涉及到整個WCF服務端的架構,下圖展示了一個最簡單的請求分發過程。

在整個消息監聽和分發體系中,信道分發器和終結點分發器是兩個核心的對象,前者負責請求監聽、消息接收並通過消息篩選器選擇正確的終結點,後者完成消息的處理。終結點分發器具有兩個消息消息篩選器,分別是AddressFilter和ContractFilter,均是MessageFilter類型,前者對應的AddressFilterMode包含Exact、Prefix、Any三種枚舉類型。WCF提供6種典型的消息篩選器,包括:ActionMessageFilter,判斷請求消息(SOAP)的<Action>報頭是否和終結點契約中任意操作的Action屬性相匹配(Match);EndpointAddressMessageFilter判斷<To>報頭是否和終結點地址相匹配;MatchAllMessageFilter,表示全匹配;以及不常用的XPathMessageFilter、MatchNoneMeesageFilter和PrefixEndpointAddressMessageFilter。

 

從基礎架構的角度上看,WCF可以分為服務模型層和信道層兩個層次,服務模型層建立在信道層的基礎是上,而信道層就是通過本節即將介紹的binding綁定創建,注意這兒的綁定與.NET很多地方的綁定概念不同(例如最常見的數據綁定),注意理解。那麼binding是如何創建信道層的呢?它通過組合不同的信道,將其整合為一個指定的信道棧,這個過程其實就是一個職責鏈模式的實現,每個信道都只處理自己的一部分內容,最基本的有傳輸、編碼,復雜一些的包括事務流轉、安全傳輸和可靠傳輸,使得整個框架足夠靈活,已於擴展,一個支持WS-*的信道棧如下圖所示。

其中傳輸信道實現了基於某種協議的消息傳輸,消息編碼信道實現了消息的編碼(例如XML、Binary、MTOM),而WS-AT(WS-Atomic Transaction)實現了分布式的事務支持,WS-RM(WS-Reliable Messaging)實現了信息的可靠傳輸,WS-Security實現了消息的傳輸安全,他們都可以被稱為協議信道。接下來通過一個簡單的例子來演示通過綁定進行消息通信,在其中將引入信道、信道監聽器、信道工廠等主要對象。

 服務端:
 static void Main(string[] args)
 {
 var listenUri = new Uri("http://127.0.0.1:9902/listener");
 var binding = new BasicHttpBinding();
 //創建和開啟信道監聽器
 var channelListener = binding.BuildChannelListener<IReplyChannel>(listenUri);
 channelListener.Open();
 //創建、開啟回復信道
 var channel = channelListener.AcceptChannel(TimeSpan.MaxValue);
 channel.Open();
 //開始監聽
 while (true)
 {
 //接受輸入請求信息
 var requestContext = channel.ReceiveRequest(TimeSpan.MaxValue);
 Console.WriteLine(requestContext.RequestMessage);
 requestContext.Reply(CreateReplyMessage(binding));
 }
 }
 
 private static Message CreateReplyMessage(Binding binding)
 {
 var action = "http://www.sory.com/addservice/AddResponse";
 XNamespace ns = "http://www.sory.com";
 XElement body = new XElement(new XElement(ns + "AddResponse", new XElement(ns + "AddResult", 3)));
 return Message.CreateMessage(binding.MessageVersion, action, body);
 }
 
 客戶端:
 static void Main(string[] args)
 {
 var listenUri = new Uri("http://127.0.0.1:9902/listener");
 var binding = new BasicHttpBinding();
 //創建和開啟信道工廠
 var channelFactory = binding.BuildChannelFactory<IRequestChannel>();
 channelFactory.Open();
 //創建、開啟請求信道
 var channel = channelFactory.CreateChannel(new EndpointAddress(listenUri));
 channel.Open();
 //發送請求消息,接受回復消息
 var replyMessage = channel.Request(CreateRequestMessage(binding));
 Console.WriteLine(replyMessage);
 Console.Read();
 }
  
 private static Message CreateRequestMessage(Binding binding)
 {
 var action = "http://www.sory.com/addservice/Add";
 XNamespace ns = "http://www.sory.com";
 XElement body = new XElement(new XElement(ns + "Add", new XElement(ns + "x", 1), new XElement(ns + "y", 2)));
 return Message.CreateMessage(binding.MessageVersion, action, body);
 }
View Code

通過這個例子看起來很像以前的Window網絡編程中的Socket編程形式,首先服務端監聽,然後客戶端請求,服務端接收並綁定Socket(這兒是綁定信道),之後就可以在此基礎上進行通訊了。這部分涉及到的類型很多,接下來通過一個表格簡述部分主要類,浏覽即可。

類別

介紹

信道與信道棧

最基礎的ICommunicationObject接口,提供統一管理通信對象的狀態機,可以作為一種設計范例用於實際項目中;DefaultCommunicationTimeouts類負責控制超時時限;IChannel和ChannelBase用於表示信道;ISession和ISessionChannel<TSession>用於表示會話信道。此外,支持3種消息交換模式。

數據報Datagram模式:一般使一部的消息發送方式,支持1或多個接收者,對應IOutputChannel, IInputChannel

請求-回復模式:對應IRequestChannel、IReplyChannel

雙工模式:對應IDuplexChannel

信道監聽器(Server)

IChannelListener, ChannelListenerBase

信道工廠(Client)

IChannelFactory, ChannelFactoryBase

最後,進入綁定元素與綁定的介紹,之前提到過,綁定是用於創建信道棧的,而它其中的綁定元素則是用於創建具體的信道的。常見的系統綁定包括:BasicHttpBinding、WSHttpBinding、WS2007HttpBinding、WSDualHttpBinding、NetTcpBinding、NetNamedPipeBinding和NetMsmqBinding。其中BasicHttpBinding最為基礎,在構建類似web服務形式的應用中使用最多,所有帶Net前綴的綁定將局限於.NET平台,不同的綁定的運行效率有不小差異。一般來說,企業內部的服務推薦使用RPC類型的服務,如NetTcpBinding,而對外服務推薦使用WSHttpBinding,當然實際項目中,對外服務一般不會使用WCF框架,而是使用Restful風格的WebAPI。此外,也可以建立自定義的綁定,將框架提供的綁定元素進行重新組合,更有甚者,可以自定義綁定元素,不過這部分內容使用的場景非常的少。最後,提供一個簡單自定義綁定配置作為參考,其組合了傳輸、編碼和安全3個綁定元素,前兩者是必選項,且必須按照順序構建。

 <bindings >
 <customBinding>
 <binding name="testBinding">
 <security></security>
 <textMessageEncoding></textMessageEncoding>
 <tcpTransport></tcpTransport>
 </binding>
 </customBinding>
 </bindings>
View Code

 

契約其實就是一個生活中的概念,是一種雙邊和多邊的協議,在WCF中,其保證了無論服務的實現有任何的改變,而服務的消費者始終可以通過契約約定方式來調用服務。由於整個WCF都是基於SOAP以及WS-*的,因此其XML是數據格式標准,通過XSD控制XML的數據結構,用WSDL(web服務描述語言)來提供跨平台的描述服務。

服務契約的定義通過ServiceContractAttribute和OperationContractAttribute兩個特性來定義,前者定義整個服務,後者定義服務中具體的方法,接下來具體介紹一下這兩個類。ServiceContractAttribute類,比較重要的屬性包括:Name,可以定義服務的名稱,默認為接口名;Namespace定義服務的命名空間,可以使用自己的公司名和項目名的組合來設定,其和之前的Name在wsdl文件中均是對<portType>元素的修飾;ConfigurationName實際上就對應配置中的Contract名稱;SessionMode表示契約的會話模式,比如Allowed、Required等;ProtectionLevel表示消息的保護級別;CallbackContract在雙工通信時指定回調操作的接口類型。OperationContractAttribute類,其屬性Name、Namespace、ProtectionLevel與之前相似,值得一提的屬性包括:Action/ReplyAction用於控制某個操作請求/回復信息的<Action>頭,其默認通過命名空間、服務契約、操作名稱組成,後者默認添加Response;IsOneWay控制消息交換的模式。提到消息交換的模式,記得之前提到過主要的三種請求-回復、單向和雙工,前兩項之前的例子中已有展示,之後的示例將展示雙工模式。

 服務端:
 public interface IAddCallback
 {
 [OperationContract]
 void DisplayResult(CompositeType result, CompositeType a, CompositeType b);
 }
 [ServiceContract(CallbackContract=typeof(IAddCallback))]
 public interface IAddService
 {
 [OperationContract]
 void Add(CompositeType a, CompositeType b);
 }
  
 [DataContract]
 public class CompositeType
 {
 [DataMember]
 public int PartA { get; set; }
 [DataMember]
 public string PartB { get; set; }
 }
 public class AddCallbackService : IAddCallback
 {
 public void DisplayResult(CompositeType result, CompositeType a, CompositeType b)
 {
 Console.WriteLine("x + y = {2} when x= {0} and y = {1}", a.PartA, b.PartA, result.PartA);
 }
 }
 
 public class AddService : IAddService
 {
 public void Add(CompositeType a, CompositeType b)
 {
 var result = new CompositeType() { PartA = a.PartA + b.PartA, PartB = a.PartB + b.PartB };
 IAddCallback callback = OperationContext.Current.GetCallbackChannel<IAddCallback>();
 callback.DisplayResult(result, a, b);
 }
 }
 
 配置:
 <system.serviceModel>
 <behaviors>
 <serviceBehaviors>
 <behavior name="metadataBehavior">
 <serviceMetadata httpGetEnabled="True" httpGetUrl="http://127.0.0.1:9901/addservice/metadata"/> 
 <serviceDebug includeExceptionDetailInFaults="true"/>
 </behavior>
 </serviceBehaviors>
 </behaviors>
 <services>
 <service name="Sory.Entertainment.WCF.AddService" behaviorConfiguration="metadataBehavior">
 <endpoint address="net.tcp://127.0.0.1:1001/addservice" binding="netTcpBinding" contract="Sory.Entertainment.WCF.IAddService"/>
 </service>
 </services>
 </system.serviceModel>
 
 客戶端:
 
 InstanceContext callback = new InstanceContext(new AddCallbackService());
 using (DuplexChannelFactory<IAddService> channelFactory = new DuplexChannelFactory<IAddService>(callback, "addservice"))
 {
 var addChannel = channelFactory.CreateChannel();
 addChannel.Add(new CompositeType { PartA = 1 }, new CompositeType { PartA = 2 });
 }
 
 配置:
 <system.serviceModel>
 <client>
 <endpoint name="addservice" address="net.tcp://127.0.0.1:1001/addservice" binding="netTcpBinding" contract="Sory.Entertainment.WCF.IAddService"/>
 </client>
 </system.serviceModel>
View Code

當調用以上示例的服務時,會拋出一個關於死鎖的異常,原因是其在並發場景下會造成回調死鎖的情況,可以通過將請求或回調方法設置為單向即可。

此外,服務契約是不支持繼承的,而操作契約支持繼承,不過這部分也不太常用,而與契約相關的元數據描述類也非常簡單,這兒就不展開介紹了。

  • 多線程和異步操作

在《CLR via C#》中,將操作分為計算限制的和I/O限制的,一般來說,WCF中主要涉及到I/O限制的操作,這種類型的操作主要是通過異步模型來提高其並發性。談到異步操作,在SOA這類應用中包含3個不同異步場景,這部分知識比較有意思,曾經困到鄙人多年。這3中場景包括:異步的信道調用,客戶端可以通過代理對象異步的調用信道;單向消息交換,客戶端的信道通過單向的消息交換模式向服務端發送消息,發送立刻返回;異步服務實現,服務端在具體實現服務操作時,采用異步調用的方式。

異步服務代理的創建,可以通過在添加服務引用時通過高級選項添加生成異步操作選項,之後可以通過使用BeginXX/EndXX方法、回調和事件注冊等方式使用異步服務代理類。而異步的服務實現可以在服務接口中將原有方法修改為BeginXXX/EndXXX形式的異步方法名,並將OperationContract契約的AsyncPattern屬性設置為true即可。

  • 操作的選擇與執行

之前提及的契約描述類中的Operations列表只包含了被OperationContractAttribute特性修飾的服務操作,而運行時的操作是通過DispatchOperation和ClientOperation兩個類型表示。DispatchOperation在服務端的終結點分發器初始化時建立一個DispatchRuntime類,其通過一個SynchronizedKeyedCollection<string, DispatchOperation>集合類型來管理所有的運行時分發操作,OperationSelector用於操作選擇,IOperationInvoker用於操作執行。ClientOperation和前者的結構基本一致,只不過它用於客戶端而已。

 

Tip:在實際中,很多公司選用ServiceStack的開源架構來構建的自身的SOA服務,此外,過去也常常以通過WebService搭建企業服務總線ESB的方式構建SOA服務。這部分推薦兩位大神的博文,寒江獨釣的http://www.cnblogs.com/yangecnu/p/Introduce-ServiceStack.html和張善友的http://www.cnblogs.com/shanyou/p/3348347.html。

最後,分享一個好玩的東西,就是在微信中可以搜索微軟的"小冰"(剛截稿前對面的程序媛告訴我的,挺逗的,能挖掘你的內心哦),然後就可以在編碼無聊、寂寞空虛時…你懂得,哈哈!

 

參考資料:

[1]蔣金楠. WCF全面解析[M]. 上海:電子工業出版社, 2012.

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved