WCF服务方法内部单例模式的问题

本文关键字:问题 单例模式 内部 服务 方法 WCF | 更新日期: 2023-09-27 18:04:22

我先说一句:我对WCF有点陌生。

我正在做一个服务器端例程,它负责做大量的业务逻辑。它可以通过WCF从客户端访问。

我的主WCF方法调用了其他几个私有方法。我没有将业务逻辑所需的所有"查找数据"传递给每个私有方法,而是决定使用一个名为DataProvider的类的单例实例,该实例包含所有这些"查找数据"。

在例程结束时,我"释放"DataProvider的查找数据,以便下次执行例程时,将使用最新的查找数据。

那么,这里有一个简化的例子:

 public void Generate()
 {
      try
      {
           //populate singleton DataProvider with it's lookup data...
           DataProvider.Instance.LoadLookupData();
           //do business logic...
      }
      finally
      {
           //release provider's lookup data...
           DataProvider.Release();
      }
 }

在我有两个不同的客户端同时(或接近)执行该方法之前,这工作得很好。出现问题是因为它们共享同一个单例实例,并且先完成的任务将在其他任务完成之前释放DataProvider。

所以…

我在这里有什么选择?

我希望避免传递所有查找数据,因此单例模式(或一些派生模式)似乎是一个不错的选择。我还需要能够支持多个客户端同时调用该方法。

我相信WCF服务配置为"Per-Call"。我不确定是否有一种方法来配置WCF服务,以便在服务调用之间不共享静态内存。

WCF服务方法内部单例模式的问题

默认情况下,WCF使用"Per-Call",这意味着为每个客户端的调用创建新的WCF服务实例。现在既然你实现了单例,即使创建了WCF的新实例,它仍然调用你的单例。

如果你想为每个调用创建查找(就像你现在所做的),你不应该作为单例来做。这样,每个客户端调用你的方法将有一个新的查找实例,我认为这是你的意图。

但是,如果您的查找变化不是那么快,我建议在所有调用之间共享它,这将提高您的WCF服务的性能。您需要将WCF服务声明为

InstanceContextMode = InstanceContextMode.Single
ConcurrencyMode = ConcurrencyMode.Multiple  

这是做什么是自动创建Singleton的WCF ,所以你不需要自己做,其次它将支持> 1并发用户(ConcurrencyMode.Multiple)。

现在,如果你的查找正在改变,并且需要在一段时间后重新加载,我仍然建议使用

InstanceContextMode = InstanceContextMode.Single 
ConcurrencyMode = ConcurrencyMode.Multiple

但是在你的代码中缓存它,然后在特定的时间或相对时间(1小时)过期你的缓存。

这里有一些链接可能会对你有所帮助:3种WCF实例管理方法(每个调用,每个会话和单个)

无论WCF InstanceContextMode设置如何,WCF服务中的静态变量总是在实例之间共享。似乎您最好使用缓存模式来查找数据。对于这个缓存问题的答案提供了一些替代方案,尽管它们有点过时。

另外,如果你决定让整个服务实例成为单例(InstanceContextMode=Single)是最简单的解决方案,请注意,除非你也让你的代码多线程(ConcurrencyMode=Multiple),否则你通常会扼杀服务的可伸缩性。如果你能在睡眠中敲出线程安全的代码,那么单例服务可能适合你。

最简单的是使用同步机制-你看过lock(…)吗-它将充当一个看门人,很像一个临界区(如果你在Windows编程中遇到过这些)

在类中定义一个静态对象

static object lockObject = new object();

并在生成方法

中使用

void Generate()
{
    lock(lockObject)
    {
    ...
    }
}