多线程单例 WCF 服务

9
在他的书《Programming WCF Services》中,Juval Lowry表达了对使用Singleton服务的担忧,因为这可能会影响性能。
在我的一个项目中,我正在使用一个声明为无状态单例WCF服务,如下所示:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single,
   ConcurrencyMode = ConcurrencyMode.Multiple)]
public class FooService : IFoo
{
}

该服务通过httpsTransport从多个Silverlight客户端访问。我选择了单例模式,因为我认为当不真正需要时,没有必要给系统增加GC开销。我是否遗漏了什么,或者这不应该是实现无状态服务的最有效方式,速度至少与PerCall实例化服务一样快吗?


你会担心 gc(垃圾回收)开销的原因是这个服务中有哪些类型的操作。 - Nix
@Nix: InstanceContextMode.Single可以避免为每个调用实例化服务本身。 - Oliver Weichhold
那并没有回答我的问题。 - Nix
@Nix 我想我已经解释清楚了。我的关于GC开销的评论是针对服务本身将不断进行垃圾回收的事实。无论其内部工作如何。 - Oliver Weichhold
所以你只关心服务的垃圾收集,而不关心任何底层代码。你会多频繁地调用这个东西? - Nix
1
好的,我已经给三个答案点赞了,因为每个人都贡献了一些有用的信息。 - Oliver Weichhold
3个回答

7
你的假设可能对于一个未启用SSL的basicHttpBinding WCF服务来说是正确的(有关更多信息,请参见此处),但对于其他绑定来说可能不正确。尽管你的应用程序代码可能真的是无状态和/或线程安全的,但WCF在其他绑定中使用会话来支持功能。这意味着每个请求只能处理一个会话,因为只有一个服务实例。
似乎选择单例模式是一种过早优化的情况。只有在有证明的需要时才应考虑优化GC效率。

我不认为使用一行代码避免不必要的对象实例化和因此产生不必要的GC压力是过早优化 :) 你的情况可能有所不同。 - Oliver Weichhold
2
@Oliver,我认为最佳吞吐量的无状态服务应使用percall模型,而不是违反建议(避免你不知道是否会成为问题的东西)是过早的 :) - Sam Holder
每次调用服务都必须具备状态感知能力;也就是说,它们必须主动管理自己的状态,给客户端一个连续会话的错觉。状态感知型服务并不同于无状态服务。事实上,如果每次调用服务真正无状态,那么根本没有必要首先进行每次调用激活。正是因为该服务具有状态,并且是昂贵的状态,您才需要使用每次调用模式。——《Programming WCF Services, 4th Edition》Michael Montgomery, Juval Lowy。 - Nick Westgate

6
你没有错过什么。如果你的服务类没有实例成员变量,这些变量代表可以通过多线程访问明显被损坏的状态,那么就没有什么可担心的了。
我个人始终使用 Single+Multiple 模式,因为我的所有状态总是来自缓存或 SQL 数据库或其他共享资源,你需要模式来防止并发。我从来没有在我的服务中发现成员变量的需求。静态变量?当然也许会有,但是你知道要保护它们。
现在这都是我个人对 PerCall vs. Single 的看法。另一方面,PerSession 服务可能会/很可能会在实例中维护状态,但我个人不经常写这些,而且在我偶尔需要时,它们也是 ConcurrencyMode.Single。 查看这篇 MSDN 文章 获取更多讨论和实际性能比较的信息。

这正是我喜欢的风格。我的所有服务都没有任何实例成员。 - Oliver Weichhold

2

避免使用单例模式的原因之一是通常你会有一个必须保证线程安全的共享资源。一旦这样做,你就有可能在串行队列中堆叠服务调用,因为在关键部分只允许一个调用。

由于你有一个无状态单例,那可能不是一个问题。然而,这很容易在以后发生。


我完全意识到一旦将其变为有状态的,它会变得混乱不堪,但这个问题明确涉及无状态单例服务。 - Oliver Weichhold
1
@Oliver:我是在说明为什么我认为它不被鼓励。几年前,我们请了IDesign为我们提供关于WCF的大师课程,我清楚地记得那个时候他们就有这样的说法。我同意你的观点,只要是无状态的,这应该不是问题。在紧张的情况下,它可能更具性能。但它比现有方案更具性能的程度可能不值得冒以上风险。 - Dave Ferguson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接