连接是否是会话对实例化的过程将产生不同的影响。
一、什么是实例化
我们在这里探讨的实例化就是当客户端调用服务端服务方法时,服务端如何对服务类进行实例化的问题。二、实例化的几种模式
服务端实例化的方式有三种,分别是"每调用实例","每会话实例"和"单一实例"。1、每调用实例
客户端对服务方法的每一次调用,服务端都会new一个实例,方法调用结束即销毁,这种模式可能要频繁的花费创建对象和销毁对象的花销,因此性能比较差,但是每次调用后服务对象被销毁,对象所把持的资源也就被释放(如文件啦、数据库连接啦),因此伸缩性是最好的。服务类上的属性
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
IIS的例子,HelloWCFService.cs的源代码如下:
using System;
using System.ServiceModel;
namespace LearnWCF
{
[ServiceContract(SessionMode = SessionMode.Required)]
public interface IHelloWCF
{
[OperationContract]
string HelloWCF();
}
服务器行为(实例上下文模式=实例化上下文模式.每个电话)
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]public class HelloWCFService : IHelloWCF
{
private int _Counter;
public string HelloWCF()
{
_Counter++;
return "Hello, you called " + _Counter.ToString() + " time(s)";
}
}
}
Web.Config配置文件:
只有IIS宿主才支持 wsHttpBinding
<configuration>
<system.serviceModel>
<services>
<service name="LearnWCF.HelloWCFService" behaviorConfiguration="metadataExchange">
<endpoint address="" binding="wsHttpBinding" contract="LearnWCF.IHelloWCF"/>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="metadataExchange">
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
客户端调用:
Hello, you called 1 time(s)
Hello, you called 1 time(s)
结果:
即使我们把服务协定的会话模式设置为Required(必须使用会话),即这个时候服务端和客户端是在进行会话连接的时候,服务端还是为两次客户端调用分别实例化了对象,所以看到计数没有增长,每次都是1。
2、每会话实例
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]可以看到计数增长了,说明没有实例化新的对象,在整个会话中只有一个。
3、单一实例
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]服务类在受到首次调用的时候实例化,然后一直不销毁,直到服务宿主关闭,在这期间无论是会话连接还是非会话连接,服务端都用这个实例进行调用。这样实际上几乎没有创建和销毁对象的开销,但是如果一旦实例把持资源,则一直都不能释放,毫无伸缩性可言。
关闭客户端程序再运行一次,计数器继续增长了,客户端程序已经重新运行,很显然这是个新的会话,但是服务端的实例一直没有销毁,所以计数器就继续增长了。
在这种模式下,无论我们把协定的SessionMode改成什么值,结果都是一样的,因为服务端已经认准了一个实例,无论客户端连接是不是会话了。