WCF - 服务实例管理模式
WCF 提供了三种实例上下文模式:PreCall、PreSession 以及 Single。开发人员通过 ServiceBehavior.InstanceContextMode 就可以很容易地控制服务对象的实例管理模式。而当 WCF 释放服务对象时,会检查该对象是否实现了 IDisposable 接口,并调用其 Dispose 方法,以便及时释放相关资源,同时也便于我们观察对象释放行为。
1. PreCall
在 PreCall 模式下,即便使用同一个代理对象,也会为每次调用创建一个服务实例。调用结束后,服务实例被立即释放(非垃圾回收)。对于不支持 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 对象。在客户端代理触发终止操作前,WCF 为每个客户端维持同一个服务对象,因此 PreSession 模式可用来保持调用状态。也正因为如此,PreSession 在大并发服务上使用时要非常小心,避免造成服务器过度负担。虽然支持 Session 的 Binding 对象缺省就会启用 PreSession 模式,但依然建议你强制指定 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
一如其名,服务器会在启动时,创建一个唯一(Singleton)的服务对象。这个对象为所有的客户端服务,并不会随客户端终止而释放。
[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;
还有另外一种方式来启动 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();
});
此方式最大的好处是允许我们使用非默认构造,除此之外,和上面的例子并没有什么区别。
需要特别注意的是,缺省情况下,Single 会对服务方法进行并发控制。也就是说,多个客户端需要排队等待,直到排在前面的其他客户端调用完成后才能继续。看下面的例子。
[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
...
我们可以通过修改并发模式(ConcurrencyMode)来改变这种行为,但需要自己维护多线程安全。
[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
WCF - 服务实例管理模式的更多相关文章
- WCF分布式开发步步为赢(9):WCF服务实例激活类型编程与开发
.Net Remoting的激活方式也有三种:SingleTon模式.SingleCall模式.客户端激活方式,WCF服务实例激活类型包括三种方式:单调服务(Call Service),会话服务(Se ...
- UI层调用WCF服务实例(源码)
WCF原理性的东西,暂时还没有深入研究,只是在公司的项目中使用到了,会调用,然后再多做了一些了解,现在将它抽出来了一个小实例,写了一个WCF的demo. 我写的这个WCF.Demo主要包括数据契约和服 ...
- WCF 项目应用连载[3] - 双向通信 实例管理与服务端监控
WCF 项目应用连载[1] - 索引 - 轻量级的Log系统 - Lig Sample -序 第二节我们已经创建了Lig项目,并且能稳定工作了.现在我们来改进ILigAgent接口,实现WCF的双向通 ...
- [WCF编程]7.实例上下文模式
一.实例上下文模式概述 实例上下文(IntanceContext Mode)表示服务端的服务实例与客户端的服务代理的绑定方式. 在实例化服务器对象时,WCF采用了3种不同的模式:单调(Per-Call ...
- 跟我一起学WCF(8)——WCF中Session、实例管理详解
一.引言 由前面几篇博文我们知道,WCF是微软基于SOA建立的一套在分布式环境中各个相对独立的应用进行交流(Communication)的框架,它实现了最新的基于WS-*规范.按照SOA的原则,相对独 ...
- WCF入门(九)--WCF实例管理
这组由Windows通讯基础(WCF)结合一组消息(客户端请求)服务实例所采用的技术被称为实例管理.一个完全由三种类型实例激活支持WCF,它们如下所述. 1.每个调用服务 每次调用服务是Windows ...
- WCF 服务的集合管理器的设计
今天是2019年2月1日,时间过得针对,马上就年底了,当前新年也离我们越来越近了.在此,我也祝福经常浏览我博客的朋友们“新年快乐.阖家欢乐”,来年有一个好彩头.在即将结束这一年之计,写今年的最后一片文 ...
- WCF实例管理的三种方式
很多情况下,我们都需要控制wcf服务端对象的初始化方式,用来控制wcf实例在服务端的存活时间. Wcf框架提供了三种创建wcf实例的方式. WCF服务对象实例化基础 在普通的WCF请求和相应过程中,将 ...
- WCF技术剖析之二十三:服务实例(Service Instance)生命周期如何控制[下篇]
原文:WCF技术剖析之二十三:服务实例(Service Instance)生命周期如何控制[下篇] 在[第2篇]中,我们深入剖析了单调(PerCall)模式下WCF对服务实例生命周期的控制,现在我们来 ...
随机推荐
- 使用springMVC和Jquery实现JSONP
JSONP这个东东是啥我就不写了,直接贴实现的代码 JAVA代码: /** * * 查询用户是否已经提交认证获取已经是认证会员 * * 使用spring mvc的直接返回string会遇到分号转义后字 ...
- python之模块ftplib(FTP协议的客户端)
# -*- coding: utf-8 -*- #python 27 #xiaodeng #python之模块ftplib(FTP协议的客户端) #需求:快速进行ftp上传 ,下载,查询文件 from ...
- java动态代理技术
主要用来做方法的增强.让你能够在不改动源代码的情况下,增强一些方法,在方法运行前后做不论什么你想做的事情(甚至根本不去运行这种方法).由于在InvocationHandler的invoke方法中,你能 ...
- Retrofit三步理解之中的一个 ------------------ Retrofit的简单使用总结
概念: Retrofit一開始看起来使用比較麻烦是由于它和其它网络请求框架不同的是它是通过注解和interface来进行网络请求,而且须要对返回数据进行特殊处理才干使用. 1. 简单使用,请求返回St ...
- Linux中 /boot 目录介绍 【转载】
Linux中 /boot 目录介绍 转自:点击打开链接 一./boot/目录中的文件和目录 Linux系统在本地启动时,目录/boot/非常重要,其中的文件和目录有: (1)系统Kernel的配置文件 ...
- Octave及其工具包的安装
Octave的安装: http://blog.sina.com.cn/s/blog_1358485f70102wmpa.html http://www.gnu.org/software/octave/ ...
- 新系统基础优化--Centos6.6
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 3 ...
- java小程序,用java在指定目录或以及子目录中找出同名文件,java File过滤文件名后找同名文件
主要是使用java API“java.io.File”实现 一个简单的类,copy出来,因main方法可直接运行. package com.paic.icore.pams.auto.util; imp ...
- 浅谈bitmap算法
一.bitmap算法思想 32位机器上,一个整形,比如int a; 在内存中占32bit位,可以用对应的32bit位对应十进制的0-31个数,bitmap算法利用这种思想处理大量数据的排序与查询. ...
- Vue.js 添加组件
<!DOCTYPE HTML> <html> <head> <title>vue.js hello world</title> <sc ...