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使用"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)
{
...
}
}