Bra*_*ton 23 c# nhibernate wcf multithreading transactions
我们有一个WCF服务,可以进行大量的事务NHibernate调用.偶尔我们看到SQL超时,即使调用更新了不同的行,并且表被设置为行级锁定.
在深入研究日志之后,看起来不同的线程正在进入代码中的相同点(我们的事务使用块),并且更新挂起在提交上.但是,它没有意义,因为我们认为以下服务类属性强制每个服务调用一个唯一的执行线程:
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, InstanceContextMode = InstanceContextMode.PerCall)]
Run Code Online (Sandbox Code Playgroud)
我们最近将并发模式改为ConcurrencyMode.Single并且还没有遇到任何问题,但是这个错误非常难以重现(如果有人有任何关于刷出这样的错误的想法,请告诉我!).
无论如何,这一切都让我想到了问题:PerCall的InstanceContextMode是否应该在服务中强制执行线程安全,即使ConcurrencyMode设置为多个?如何通过同一个服务实例为两个调用提供服务?
谢谢!
Mat*_*vis 24
使用两个不同的WCF客户端(即代理)引用同一个WCF服务实例的唯一方法InstanceContextMode=InstanceContextMode.Single.如果缩放是一个问题,这是一个糟糕的选择,所以PerCall如果可以,你想要使用.
使用时PerCall,WCF服务的每个CALL都会获得自己的WCF服务实例.没有共享服务实例,但这并不意味着它们不共享相同的后端存储(例如,数据库,内存,文件等).请记住,PerCall允许每个调用同时访问您的WCF服务.
该ConcurrencyMode设置控制服务本身的线程模型.一种设置,Single将所有WCF服务实例限制为在同一线程上运行.因此,如果您同时连接多个客户端,则它们将仅在WCF服务端一次执行一个.在这种情况下,您可以利用WCF提供同步.正如您所见,它会正常工作,但我认为这只是对同步的宏级控制 - 每个WCF服务调用将在下一次调用执行之前完整执行.
但是,设置ConcurrencyMode为Multiple允许所有WCF服务实例同时执行.在这种情况下,您负责提供必要的同步.可以将其视为对同步进行微级控制,因为您只能同步每个需要同步的调用的那些部分.
我希望我已经很好地解释了这一点,但这里是MSDN文档的片段,ConcurrencyMode以防万一:
将ConcurrencyMode设置为Single指示系统一次将服务实例限制为一个执行线程,这使您无需处理线程问题.值Multiple表示服务对象可以在任何时候由多个线程执行.在这种情况下,您必须确保线程安全.
编辑
您询问
那么,在使用ConcurrencyMode.Single时,使用PerCall与Single是否有任何性能提升?或者是反过来的?
这可能取决于服务.
使用InstanceContextMode.PerCall,通过代理为每个调用创建一个新的服务实例,因此您需要处理实例创建的开销.假设您的服务构造函数没有做太多,这不会是一个问题.
使用时InstanceContextMode.Single,应用程序的生命周期中只存在一个服务实例,因此实际上没有与实例创建相关的开销.但是,此模式仅允许一个服务实例处理将要进行的每个调用.因此,如果您同时进行多个呼叫,则每个呼叫都必须等待其他呼叫完成才能执行.
对于它的价值,这就是我如何做到这一点.将PerCall实例上下文与Multiple并发一起使用.在WCF服务类中,创建静态成员以便为您管理后端数据存储,然后根据需要使用lock语句,volatile字段等同步对这些静态成员的访问.这使您的服务可以在保持线程安全的同时很好地扩展.