三种 WCF 实例管理方式






4.92/5 (153投票s)
三种 WCF 实例管理方式(每个调用、每个会话、单个)。
目录
- 引言
- WCF 服务对象实例化基础
- 每个调用实例模式
- 如何实现 WCF 每个调用实例化
- 每个会话实例模式
- 如何实现每个会话实例化
- 单个实例模式
- 如何实现单个实例模式
- 何时应使用每个调用、每个会话和单个模式?
- 参考文献
- 源代码
引言
我们经常希望控制 WCF 服务对象在 WCF 服务器上的实例化方式。您需要控制 WCF 实例在服务器上保留多长时间。
WCF 框架提供了三种控制 WCF 实例创建的方式。在本文中,我们将首先尝试通过简单的代码示例来理解这三种 WCF 服务实例控制方式,以及如何实现它们。最后,我们将比较何时以及在何种情况下使用它们。
为我所有的 .NET 朋友准备了一本小型电子书,涵盖了 WCF、WPF、WWF、AJAX、Core .NET、SQL 等主题,您可以在此下载:此处。
WCF 服务对象实例化基础
在正常的 WCF 请求和响应通信中,会发生以下一系列操作:
- WCF 客户端向 WCF 服务对象发出请求。
- 实例化 WCF 服务对象。
- WCF 服务实例处理请求并将响应发送给 WCF 客户端。
以下是 WCF 请求和响应工作方式的图示。
以下是创建 WCF 实例的不同方式:
- 在每次 WCF 客户端方法调用时创建一个新的 WCF 服务实例。
- 为每个 WCF 客户端会话只创建一个 WCF 服务实例。
- 只创建一个全局 WCF 服务实例供所有 WCF 客户端使用。
为了满足上述场景,WCF 提供了三种控制 WCF 服务实例的方式:
- 每个调用
- 每个会话
- 单个实例
每个调用实例模式
当我们将 WCF 服务配置为每个调用时,每次通过 WCF 代理客户端调用方法时都会创建新的服务实例。下图以图示形式展示了这一点:
- WCF 客户端发出第一个方法调用(方法调用 1)。
- 在服务器上为该方法调用创建一个新的 WCF 服务实例。
- WCF 服务处理请求并发送响应,然后 WCF 实例被销毁并交给垃圾回收器进行清理。
- 现在,假设 WCF 客户端发出第二次方法调用,会创建一个新实例,处理请求,然后销毁 WCF 实例。
换句话说,每次调用 WCF 客户端方法时,都会创建一个 WCF 服务实例,并在请求处理完毕后销毁。
如何实现 WCF 每个调用实例化
为了指定实例化模式,我们需要在 ServiceBehavior
属性中提供 InstanceContextMode
值,如下所示。此属性需要应用于 Service
类。在下面的代码片段中,我们将 intCounter
声明为类级别的变量,并在调用 Increment
方法时将类计数器加一。
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Percall)]
public class Service : IService
{
private int intCounter;
public int Increment()
{
intCounter++
return intCounter;
}
}
在客户端,我们使用 WCF 客户端并调用两次 Increment
方法。
ServiceReference1.ServiceClient obj = new ServiceReference1.ServiceClient();
MessageBox.Show(obj.Increment().ToString());
MessageBox.Show(obj.Increment().ToString());
即使我们调用了两次 Increment
方法,得到的值仍然是 '1'。换句话说,每次调用 WCF 服务实例的方法时都会创建一个 WCF 服务实例,因此值将始终为一。
每个会话实例模式
我们经常需要在方法调用之间或在特定会话中维护状态。对于这些场景,我们需要将服务配置为每个会话。在每个会话模式下,只会为一次会话交互创建一个 WCF 服务对象的实例。下图以图示形式解释了这一点:
- 客户端创建 WCF 服务的代理并进行方法调用。
- 创建一个 WCF 服务实例来处理方法响应。
- 客户端在同一会话中发出另一个方法调用。
- 同一个 WCF 服务实例处理该方法调用。
- 当客户端完成其活动时,WCF 实例会被销毁并交给垃圾回收器进行清理。
如何实现每个会话实例化
要将服务配置为每个会话,我们需要使用 InstanceContextMode
对象中的 PerSession
值来配置 ServiceBehavior
属性。
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
public class Service : IService
{
private int intCounter;
public int Increment()
{
intCounter++
return intCounter;
}
}
在客户端,当我们运行下面的客户端代码时,在客户端代码执行完毕后,您应该会看到值 '2'。我们调用了两次方法,所以看到的值是二。
ServiceReference1.ServiceClient obj = new ServiceReference1.ServiceClient();
MessageBox.Show(obj.Increment().ToString());
MessageBox.Show(obj.Increment().ToString());
单个实例模式
我们经常希望为所有 WCF 客户端创建一个全局 WCF 实例。要创建 WCF 服务的单个实例,我们需要将 WCF 服务配置为 Single
实例模式。下面是单个实例模式如何工作的简单图示:
- WCF 客户端 1 向 WCF 服务发出方法调用请求。
- 创建一个 WCF 服务实例并处理该请求。WCF 服务实例不会被销毁,而是被保留以服务其他请求。
- 现在,假设另一个 WCF 客户端,例如客户端 2,发出方法调用请求。
- 由 WCF 客户端 1 创建的同一个 WCF 实例用于处理 WCF 客户端 2 的请求。换句话说,只有一个全局 WCF 服务器服务实例用于处理所有客户端请求。
如何实现单个实例模式
为了创建 WCF 服务的单个实例,我们需要将 InstanceContextMode
指定为 Single
。
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class Service : IService
{
}
如果从不同的客户端调用 WCF 服务,您会看到计数器在递增。计数器成为一个全局变量。
何时应使用每个调用、每个会话和单个模式?
每个调用
- 您需要无状态服务。
- 您的服务包含大量资源,例如连接对象和大量内存对象。
- 可伸缩性是首要要求。您希望拥有一个横向扩展的体系结构。
- 您的 WCF 函数以单线程模型调用。
每个会话
- 您希望在 WCF 调用之间维护状态。
- 您有一个纵向扩展的体系结构。
- 轻量级资源引用。
单个
- 您希望通过 WCF 服务共享全局数据。
- 可伸缩性不是问题。
参考文献
- WCF 实例 MSDN 链接:http://msdn.microsoft.com/en-us/library/ms733040.aspx。
- 不要错过这篇关于 WCF 会话端到端内容的帖子:http://codeidol.com/csharp/wcf/Instance-Management/。
- Rick Rain 关于 WCF 实例化的精彩博客:http://blogs.msdn.com/b/rickrain/archive/2009/06/15/wcf-instancing-concurrency-and-throttling-part-1.aspx。
源代码
您可以从 此处 下载本教程的源代码。
进一步阅读,请观看下面的面试准备视频和分步视频系列。