WCF - 服务实例管理模式
生活随笔
收集整理的這篇文章主要介紹了
WCF - 服务实例管理模式
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
WCF 提供了三種實(shí)例上下文模式:PreCall、PreSession 以及 Single。開(kāi)發(fā)人員通過(guò) ServiceBehavior.InstanceContextMode 就可以很容易地控制服務(wù)對(duì)象的實(shí)例管理模式。而當(dāng) WCF 釋放服務(wù)對(duì)象時(shí),會(huì)檢查該對(duì)象是否實(shí)現(xiàn)了 IDisposable 接口,并調(diào)用其 Dispose 方法,以便及時(shí)釋放相關(guān)資源,同時(shí)也便于我們觀察對(duì)象釋放行為。
1. PreCall
在 PreCall 模式下,即便使用同一個(gè)代理對(duì)象,也會(huì)為每次調(diào)用創(chuàng)建一個(gè)服務(wù)實(shí)例。調(diào)用結(jié)束后,服務(wù)實(shí)例被立即釋放(非垃圾回收)。對(duì)于不支持 Session 的 Binding,如 BasicHttpBinding,其缺省行為就是 PreCall。
[ServiceContract] public interface IMyService {[OperationContract]void Test(); }[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)] public class MyServie : IMyService, IDisposable {public MyServie(){Console.WriteLine("Constructor:{0}", this.GetHashCode());}[OperationBehavior]public void Test(){Console.WriteLine("Test:{0}", OperationContext.Current.SessionId);}public void Dispose(){Console.WriteLine("Dispose");} }public class WcfTest {public static void Test(){AppDomain.CreateDomain("Server").DoCallBack(delegate{ServiceHost host = new ServiceHost(typeof(MyServie), new Uri("http://localhost:8080/MyService"));host.AddServiceEndpoint(typeof(IMyService), new WSHttpBinding(), "");host.Open();});//-----------------------IMyService channel = ChannelFactory<IMyService>.CreateChannel(new WSHttpBinding(),new EndpointAddress("http://localhost:8080/MyService"));using (channel as IDisposable){channel.Test();channel.Test();}} }
輸出:
Constructor:30136159
Test:urn:uuid:df549447-52ba-4c54-9432-31a7a533d9b4
Dispose
Constructor:41153804
Test:urn:uuid:df549447-52ba-4c54-9432-31a7a533d9b4
Dispose
2. PreSession
PreSession 模式需要綁定到支持 Session 的 Binding 對(duì)象。在客戶端代理觸發(fā)終止操作前,WCF 為每個(gè)客戶端維持同一個(gè)服務(wù)對(duì)象,因此 PreSession 模式可用來(lái)保持調(diào)用狀態(tài)。也正因?yàn)槿绱?#xff0c;PreSession 在大并發(fā)服務(wù)上使用時(shí)要非常小心,避免造成服務(wù)器過(guò)度負(fù)擔(dān)。雖然支持 Session 的 Binding 對(duì)象缺省就會(huì)啟用 PreSession 模式,但依然建議你強(qiáng)制指定 SessionMode.Required 和 InstanceContextMode.PerSession。
[ServiceContract(SessionMode = SessionMode.Required)] public interface IMyService {[OperationContract]void Test(); }[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)] public class MyServie : IMyService, IDisposable {public MyServie(){Console.WriteLine("Constructor:{0}", this.GetHashCode());}[OperationBehavior]public void Test(){Console.WriteLine("Test:{0}", OperationContext.Current.SessionId);}public void Dispose(){Console.WriteLine("Dispose");} }public class WcfTest {public static void Test(){AppDomain.CreateDomain("Server").DoCallBack(delegate{ServiceHost host = new ServiceHost(typeof(MyServie), new Uri("http://localhost:8080/MyService"));host.AddServiceEndpoint(typeof(IMyService), new WSHttpBinding(), "");host.Open();});//-----------------------IMyService channel = ChannelFactory<IMyService>.CreateChannel(new WSHttpBinding(), new EndpointAddress("http://localhost:8080/MyService"));using (channel as IDisposable){channel.Test();channel.Test();}} }
輸出:
Constructor:30136159
Test:urn:uuid:2f01b61d-40c6-4f1b-a4d6-4f4bc3e8847a
Test:urn:uuid:2f01b61d-40c6-4f1b-a4d6-4f4bc3e8847a
Dispose
3. Single
一如其名,服務(wù)器會(huì)在啟動(dòng)時(shí),創(chuàng)建一個(gè)唯一(Singleton)的服務(wù)對(duì)象。這個(gè)對(duì)象為所有的客戶端服務(wù),并不會(huì)隨客戶端終止而釋放。
[ServiceContract] public interface IMyService {[OperationContract]void Test(); }[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)] public class MyServie : IMyService, IDisposable {public MyServie(){Console.WriteLine("Constructor:{0}; {1}", DateTime.Now, this.GetHashCode());}[OperationBehavior]public void Test(){Console.WriteLine("Test:{0}; {1}", DateTime.Now, OperationContext.Current.SessionId);}public void Dispose(){Console.WriteLine("Dispose:{0}", DateTime.Now);} }public class WcfTest {public static void Test(){AppDomain.CreateDomain("Server").DoCallBack(delegate{ServiceHost host = new ServiceHost(typeof(MyServie), new Uri("http://localhost:8080/MyService"));host.AddServiceEndpoint(typeof(IMyService), new BasicHttpBinding(), "");host.Open();});//-----------------------for (int i = 0; i < 2; i++){IMyService channel = ChannelFactory<IMyService>.CreateChannel(new BasicHttpBinding(), new EndpointAddress("http://localhost:8080/MyService"));using (channel as IDisposable){channel.Test();channel.Test();}}} }
輸出:
Constructor:2007-4-17 17:31:01; 63238509
Test:2007-4-17 17:31:03;
Test:2007-4-17 17:31:03;
Test:2007-4-17 17:31:03;
Test:2007-4-17 17:31:03;
還有另外一種方式來(lái)啟動(dòng) Single ServiceHost。
AppDomain.CreateDomain("Server").DoCallBack(delegate {MyServie service = new MyServie();ServiceHost host = new ServiceHost(service, new Uri("http://localhost:8080/MyService"));host.AddServiceEndpoint(typeof(IMyService), new BasicHttpBinding(), "");host.Open(); });
此方式最大的好處是允許我們使用非默認(rèn)構(gòu)造,除此之外,和上面的例子并沒(méi)有什么區(qū)別。
需要特別注意的是,缺省情況下,Single 會(huì)對(duì)服務(wù)方法進(jìn)行并發(fā)控制。也就是說(shuō),多個(gè)客戶端需要排隊(duì)等待,直到排在前面的其他客戶端調(diào)用完成后才能繼續(xù)??聪旅娴睦?。
[ServiceContract] public interface IMyService {[OperationContract]void Test(); }[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)] public class MyServie : IMyService, IDisposable {public MyServie(){Console.WriteLine("Constructor:{0}", this.GetHashCode());}[OperationBehavior]public void Test(){Console.WriteLine("Test:{0}", OperationContext.Current.SessionId);Thread.Sleep(2000);Console.WriteLine("Test End:{0}", OperationContext.Current.SessionId);}public void Dispose(){Console.WriteLine("Dispose");} }public class WcfTest {public static void Test(){AppDomain.CreateDomain("Server").DoCallBack(delegate{ServiceHost host = new ServiceHost(typeof(MyServie), new Uri("http://localhost:8080/MyService"));host.AddServiceEndpoint(typeof(IMyService), new WSHttpBinding(), "");host.Open();});//-----------------------for (int i = 0; i < 2; i++){new Thread(delegate(){IMyService channel = ChannelFactory<IMyService>.CreateChannel(new WSHttpBinding(), new EndpointAddress("http://localhost:8080/MyService"));using (channel as IDisposable){while (true){channel.Test();}}}).Start();}} }
輸出:
Constructor:63238509
Test:urn:uuid:d613cfce-d454-40c9-9f4d-62b30a93ff27
Test End:urn:uuid:d613cfce-d454-40c9-9f4d-62b30a93ff27
Test:urn:uuid:313de31e-96b8-47c2-8cf3-7ae743236dfc
Test End:urn:uuid:313de31e-96b8-47c2-8cf3-7ae743236dfc
Test:urn:uuid:d613cfce-d454-40c9-9f4d-62b30a93ff27
Test End:urn:uuid:d613cfce-d454-40c9-9f4d-62b30a93ff27
Test:urn:uuid:313de31e-96b8-47c2-8cf3-7ae743236dfc
Test End:urn:uuid:313de31e-96b8-47c2-8cf3-7ae743236dfc
Test:urn:uuid:d613cfce-d454-40c9-9f4d-62b30a93ff27
Test End:urn:uuid:d613cfce-d454-40c9-9f4d-62b30a93ff27
Test:urn:uuid:313de31e-96b8-47c2-8cf3-7ae743236dfc
Test End:urn:uuid:313de31e-96b8-47c2-8cf3-7ae743236dfc
...
我們可以通過(guò)修改并發(fā)模式(ConcurrencyMode)來(lái)改變這種行為,但需要自己維護(hù)多線程安全。
[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single, ConcurrencyMode=ConcurrencyMode.Multiple)] public class MyServie : IMyService, IDisposable {//... }
輸出:
Constructor:10261382
Test:urn:uuid:2bdac798-f774-40f2-b8f9-58de8d599d3c
Test:urn:uuid:9a328d0e-8df7-4885-94ed-e04ceedc5a09
Test End:urn:uuid:2bdac798-f774-40f2-b8f9-58de8d599d3c
Test:urn:uuid:2bdac798-f774-40f2-b8f9-58de8d599d3c
Test End:urn:uuid:9a328d0e-8df7-4885-94ed-e04ceedc5a09
Test:urn:uuid:9a328d0e-8df7-4885-94ed-e04ceedc5a09
Test End:urn:uuid:2bdac798-f774-40f2-b8f9-58de8d599d3c
Test:urn:uuid:2bdac798-f774-40f2-b8f9-58de8d599d3c
Test End:urn:uuid:9a328d0e-8df7-4885-94ed-e04ceedc5a09
Test:urn:uuid:9a328d0e-8df7-4885-94ed-e04ceedc5a09
Test End:urn:uuid:2bdac798-f774-40f2-b8f9-58de8d599d3c
Test:urn:uuid:2bdac798-f774-40f2-b8f9-58de8d599d3c
Test End:urn:uuid:9a328d0e-8df7-4885-94ed-e04ceedc5a09
Test:urn:uuid:9a328d0e-8df7-4885-94ed-e04ceedc5a09
1. PreCall
在 PreCall 模式下,即便使用同一個(gè)代理對(duì)象,也會(huì)為每次調(diào)用創(chuàng)建一個(gè)服務(wù)實(shí)例。調(diào)用結(jié)束后,服務(wù)實(shí)例被立即釋放(非垃圾回收)。對(duì)于不支持 Session 的 Binding,如 BasicHttpBinding,其缺省行為就是 PreCall。
[ServiceContract] public interface IMyService {[OperationContract]void Test(); }[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)] public class MyServie : IMyService, IDisposable {public MyServie(){Console.WriteLine("Constructor:{0}", this.GetHashCode());}[OperationBehavior]public void Test(){Console.WriteLine("Test:{0}", OperationContext.Current.SessionId);}public void Dispose(){Console.WriteLine("Dispose");} }public class WcfTest {public static void Test(){AppDomain.CreateDomain("Server").DoCallBack(delegate{ServiceHost host = new ServiceHost(typeof(MyServie), new Uri("http://localhost:8080/MyService"));host.AddServiceEndpoint(typeof(IMyService), new WSHttpBinding(), "");host.Open();});//-----------------------IMyService channel = ChannelFactory<IMyService>.CreateChannel(new WSHttpBinding(),new EndpointAddress("http://localhost:8080/MyService"));using (channel as IDisposable){channel.Test();channel.Test();}} }
輸出:
Constructor:30136159
Test:urn:uuid:df549447-52ba-4c54-9432-31a7a533d9b4
Dispose
Constructor:41153804
Test:urn:uuid:df549447-52ba-4c54-9432-31a7a533d9b4
Dispose
2. PreSession
PreSession 模式需要綁定到支持 Session 的 Binding 對(duì)象。在客戶端代理觸發(fā)終止操作前,WCF 為每個(gè)客戶端維持同一個(gè)服務(wù)對(duì)象,因此 PreSession 模式可用來(lái)保持調(diào)用狀態(tài)。也正因?yàn)槿绱?#xff0c;PreSession 在大并發(fā)服務(wù)上使用時(shí)要非常小心,避免造成服務(wù)器過(guò)度負(fù)擔(dān)。雖然支持 Session 的 Binding 對(duì)象缺省就會(huì)啟用 PreSession 模式,但依然建議你強(qiáng)制指定 SessionMode.Required 和 InstanceContextMode.PerSession。
[ServiceContract(SessionMode = SessionMode.Required)] public interface IMyService {[OperationContract]void Test(); }[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)] public class MyServie : IMyService, IDisposable {public MyServie(){Console.WriteLine("Constructor:{0}", this.GetHashCode());}[OperationBehavior]public void Test(){Console.WriteLine("Test:{0}", OperationContext.Current.SessionId);}public void Dispose(){Console.WriteLine("Dispose");} }public class WcfTest {public static void Test(){AppDomain.CreateDomain("Server").DoCallBack(delegate{ServiceHost host = new ServiceHost(typeof(MyServie), new Uri("http://localhost:8080/MyService"));host.AddServiceEndpoint(typeof(IMyService), new WSHttpBinding(), "");host.Open();});//-----------------------IMyService channel = ChannelFactory<IMyService>.CreateChannel(new WSHttpBinding(), new EndpointAddress("http://localhost:8080/MyService"));using (channel as IDisposable){channel.Test();channel.Test();}} }
輸出:
Constructor:30136159
Test:urn:uuid:2f01b61d-40c6-4f1b-a4d6-4f4bc3e8847a
Test:urn:uuid:2f01b61d-40c6-4f1b-a4d6-4f4bc3e8847a
Dispose
3. Single
一如其名,服務(wù)器會(huì)在啟動(dòng)時(shí),創(chuàng)建一個(gè)唯一(Singleton)的服務(wù)對(duì)象。這個(gè)對(duì)象為所有的客戶端服務(wù),并不會(huì)隨客戶端終止而釋放。
[ServiceContract] public interface IMyService {[OperationContract]void Test(); }[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)] public class MyServie : IMyService, IDisposable {public MyServie(){Console.WriteLine("Constructor:{0}; {1}", DateTime.Now, this.GetHashCode());}[OperationBehavior]public void Test(){Console.WriteLine("Test:{0}; {1}", DateTime.Now, OperationContext.Current.SessionId);}public void Dispose(){Console.WriteLine("Dispose:{0}", DateTime.Now);} }public class WcfTest {public static void Test(){AppDomain.CreateDomain("Server").DoCallBack(delegate{ServiceHost host = new ServiceHost(typeof(MyServie), new Uri("http://localhost:8080/MyService"));host.AddServiceEndpoint(typeof(IMyService), new BasicHttpBinding(), "");host.Open();});//-----------------------for (int i = 0; i < 2; i++){IMyService channel = ChannelFactory<IMyService>.CreateChannel(new BasicHttpBinding(), new EndpointAddress("http://localhost:8080/MyService"));using (channel as IDisposable){channel.Test();channel.Test();}}} }
輸出:
Constructor:2007-4-17 17:31:01; 63238509
Test:2007-4-17 17:31:03;
Test:2007-4-17 17:31:03;
Test:2007-4-17 17:31:03;
Test:2007-4-17 17:31:03;
還有另外一種方式來(lái)啟動(dòng) Single ServiceHost。
AppDomain.CreateDomain("Server").DoCallBack(delegate {MyServie service = new MyServie();ServiceHost host = new ServiceHost(service, new Uri("http://localhost:8080/MyService"));host.AddServiceEndpoint(typeof(IMyService), new BasicHttpBinding(), "");host.Open(); });
此方式最大的好處是允許我們使用非默認(rèn)構(gòu)造,除此之外,和上面的例子并沒(méi)有什么區(qū)別。
需要特別注意的是,缺省情況下,Single 會(huì)對(duì)服務(wù)方法進(jìn)行并發(fā)控制。也就是說(shuō),多個(gè)客戶端需要排隊(duì)等待,直到排在前面的其他客戶端調(diào)用完成后才能繼續(xù)??聪旅娴睦?。
[ServiceContract] public interface IMyService {[OperationContract]void Test(); }[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)] public class MyServie : IMyService, IDisposable {public MyServie(){Console.WriteLine("Constructor:{0}", this.GetHashCode());}[OperationBehavior]public void Test(){Console.WriteLine("Test:{0}", OperationContext.Current.SessionId);Thread.Sleep(2000);Console.WriteLine("Test End:{0}", OperationContext.Current.SessionId);}public void Dispose(){Console.WriteLine("Dispose");} }public class WcfTest {public static void Test(){AppDomain.CreateDomain("Server").DoCallBack(delegate{ServiceHost host = new ServiceHost(typeof(MyServie), new Uri("http://localhost:8080/MyService"));host.AddServiceEndpoint(typeof(IMyService), new WSHttpBinding(), "");host.Open();});//-----------------------for (int i = 0; i < 2; i++){new Thread(delegate(){IMyService channel = ChannelFactory<IMyService>.CreateChannel(new WSHttpBinding(), new EndpointAddress("http://localhost:8080/MyService"));using (channel as IDisposable){while (true){channel.Test();}}}).Start();}} }
輸出:
Constructor:63238509
Test:urn:uuid:d613cfce-d454-40c9-9f4d-62b30a93ff27
Test End:urn:uuid:d613cfce-d454-40c9-9f4d-62b30a93ff27
Test:urn:uuid:313de31e-96b8-47c2-8cf3-7ae743236dfc
Test End:urn:uuid:313de31e-96b8-47c2-8cf3-7ae743236dfc
Test:urn:uuid:d613cfce-d454-40c9-9f4d-62b30a93ff27
Test End:urn:uuid:d613cfce-d454-40c9-9f4d-62b30a93ff27
Test:urn:uuid:313de31e-96b8-47c2-8cf3-7ae743236dfc
Test End:urn:uuid:313de31e-96b8-47c2-8cf3-7ae743236dfc
Test:urn:uuid:d613cfce-d454-40c9-9f4d-62b30a93ff27
Test End:urn:uuid:d613cfce-d454-40c9-9f4d-62b30a93ff27
Test:urn:uuid:313de31e-96b8-47c2-8cf3-7ae743236dfc
Test End:urn:uuid:313de31e-96b8-47c2-8cf3-7ae743236dfc
...
我們可以通過(guò)修改并發(fā)模式(ConcurrencyMode)來(lái)改變這種行為,但需要自己維護(hù)多線程安全。
[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single, ConcurrencyMode=ConcurrencyMode.Multiple)] public class MyServie : IMyService, IDisposable {//... }
輸出:
Constructor:10261382
Test:urn:uuid:2bdac798-f774-40f2-b8f9-58de8d599d3c
Test:urn:uuid:9a328d0e-8df7-4885-94ed-e04ceedc5a09
Test End:urn:uuid:2bdac798-f774-40f2-b8f9-58de8d599d3c
Test:urn:uuid:2bdac798-f774-40f2-b8f9-58de8d599d3c
Test End:urn:uuid:9a328d0e-8df7-4885-94ed-e04ceedc5a09
Test:urn:uuid:9a328d0e-8df7-4885-94ed-e04ceedc5a09
Test End:urn:uuid:2bdac798-f774-40f2-b8f9-58de8d599d3c
Test:urn:uuid:2bdac798-f774-40f2-b8f9-58de8d599d3c
Test End:urn:uuid:9a328d0e-8df7-4885-94ed-e04ceedc5a09
Test:urn:uuid:9a328d0e-8df7-4885-94ed-e04ceedc5a09
Test End:urn:uuid:2bdac798-f774-40f2-b8f9-58de8d599d3c
Test:urn:uuid:2bdac798-f774-40f2-b8f9-58de8d599d3c
Test End:urn:uuid:9a328d0e-8df7-4885-94ed-e04ceedc5a09
Test:urn:uuid:9a328d0e-8df7-4885-94ed-e04ceedc5a09
轉(zhuǎn)載于:https://www.cnblogs.com/lzjsky/archive/2011/04/01/2002285.html
總結(jié)
以上是生活随笔為你收集整理的WCF - 服务实例管理模式的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Windows下安装GitHub客户端
- 下一篇: 收集一些正则表达式