WCF 服务的 PerCall InstanceContextMode 行为
Posted
技术标签:
【中文标题】WCF 服务的 PerCall InstanceContextMode 行为【英文标题】:PerCall InstanceContextMode behaviour of WCF service 【发布时间】:2015-01-12 17:41:14 【问题描述】:我有一个 WCF 服务,使用 basicHttpBinding 公开 ServiceContract,因此据我了解,InstanceContextMode 将设置为 PerCall(因为 basicHttpBinding 不支持会话),ConcurrenyMode 将设置为 Single。
这个WCF的客户端是一个windows服务,它同时在服务上调用4个不同的操作,在服务内部我们使用了一个单例类,静态变量很少。我们一直面临一个问题,即错误的值被传递给某些 DB 存储过程。
使用 PerCall InstanceContextMode 和 Single 并发模式,我了解为每次调用创建的新服务实例,因此我认为即使在服务实现和静态中有一些单例类(我们没有使其线程安全) variables 所有对象都将被销毁,但我们观察到运行 SQL 分析器,旧值正在通过数据库。
我们已经将我们的 WCF 服务代码编写在一种 3 层架构中,即 ServiceClass、BusinessLogicLayer 和 DataAccessLayer,当我们说服务实例在客户端请求完成后被销毁时,PerCall 设置为 instanceContextMode,这是否意味着我们销毁ServiceClass、BusinessLogicLayer和DataAccessLayer中的所有对象?
请帮助我了解可能出了什么问题
【问题讨论】:
你使用单例有什么原因吗?在您的架构中,这似乎是一种极其不适合的模式。没有单例并使用一些适当的调试,你应该没问题。 【参考方案1】:InstanceContextMode PerCall 表示您的服务的一个新类每次调用都会被实例化。 AppDomain 中的静态变量不会被重置。只要您的 AppPool 没有被回收,它们就会在服务调用之间停留。
从您的代码中删除所有静态变量,包括单例。反正它们从来不属于你的架构。
【讨论】:
感谢@nvoigt,它帮助我更好地理解,是否有任何工具我的意思是某种内存分析工具来理解/可视化内存中的对象在服务调用期间和之后哪些对象不存在 @CSharped 你可以试试here提到的一些分析器。【参考方案2】:许多 WCF 请求共享同一个 AppDomain。静态变量是每个 AppDomain 的。 WCF 对这些变量没有任何作用(事实上它甚至无法发现它们存在)。您有责任维护它们。
WCF 不会破坏您的任何对象,因为WCF 既不理解它们的含义,也不知道它们的存在。
您提到的设置仅与服务对象相关。
我对有状态服务器应用程序的通常建议:您在这里的做法很糟糕。您需要确保线程安全。如果工作进程关闭(部署、自动重启、服务器重启、应用程序错误导致进程崩溃、断电、硬件故障……),您的数据就会丢失。
【讨论】:
谢谢@usr,这帮助我更好地理解,有没有什么工具我的意思是某种内存分析工具来理解/可视化内存中的对象在服务调用期间和之后哪些对象不存在 我相信 Jetbrains 内存分析器有一个快照差异工具。但它不会向您显示仍然存在但已失效的对象(已处置、配置错误......)。我认为手动检查是这里的方法。审计所有静态变量。【参考方案3】:虽然它以任何方式受到限制,但作为最佳实践,需要保护静态变量以确保线程安全。在服务停止/应用程序池回收之前,静态变量不会被销毁。
对于分布式网络场,不建议对发生更改的数据使用静态变量,因为这些变量在故障转移时并不安全。
Visual Studio 2012 及更高版本带有内存分析器。但是可以使用对象构造函数中的计数器来完成简单的事情(仅在测试时),它可以判断是否在每个请求上都创建了一个新实例。
[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerCall,ConcurrencyMode=ConcurrencyMode.Single)]
public class TestServiceWithStaticVars : ITestServiceWithStaticVars
static int instanceCount = 0;
public TestServiceWithStaticVars()
Interlocked.Decrement(ref instanceCount);
public string GetInstanceCount()
return string.Format("You have created 0 instance", instanceCount);
让您知道是否可以轻松使用更好的实例计数器。
[编辑] 因为我现在无法评论。
重新分配静态变量将采用您所说的新值。静态变量被加载到 HighFrequencyHeap 以进行频繁访问。欲了解更多信息http://www.codeproject.com/Articles/15269/Static-Keyword-Demystified
【讨论】:
谢谢,在我的情况下,我有一个导致所有麻烦的静态变量,我现在明白,如果我的代码重新初始化该静态变量,它将存储在相应服务的 AppDomain 中取新值?你能帮我理解它是如何工作的吗以上是关于WCF 服务的 PerCall InstanceContextMode 行为的主要内容,如果未能解决你的问题,请参考以下文章