简体   繁体   English

使用设置为ConcurrencyMode.Multiple和I​​nstanceContextMode.PerCall的WCF服务行为属性时是否可能出现并发问题?

[英]Are concurrency issues possible when using the WCF Service Behavior attribute set to ConcurrencyMode.Multiple and InstanceContextMode.PerCall?

We have a WCF service that makes a good deal of transactional NHibernate calls. 我们有一个WCF服务,可以进行大量的事务NHibernate调用。 Occasionally we were seeing SQL timeouts, even though the calls were updating different rows and the tables were set to row level locking. 偶尔我们看到SQL超时,即使调用更新了不同的行,并且表被设置为行级锁定。

After digging into the logs, it looks like different threads were entering the same point in the code (our transaction using block), and an update was hanging on commit. 在深入研究日志之后,看起来不同的线程正在进入代码中的相同点(我们的事务使用块),并且更新挂起在提交上。 It didn't make sense, though, because we believed that the following service class attribute was forcing a unique execution thread per service call: 但是,它没有意义,因为我们认为以下服务类属性强制每个服务调用一个唯一的执行线程:

[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, InstanceContextMode = InstanceContextMode.PerCall)]

We recently changed the concurrency mode to ConcurrencyMode.Single and haven't yet run into any issues, but the bug was very difficult to reproduce (if anyone has any thoughts on flushing a bug like that out, let me know!). 我们最近将并发模式更改为ConcurrencyMode.Single并且还没有遇到任何问题,但是这个错误很难重现(如果有人想要刷出这样的错误,请告诉我!)。

Anyway, that all brings me to my question: shouldn't an InstanceContextMode of PerCall enforce thread-safety within the service, even if the ConcurrencyMode is set to multiple? 无论如何,这一切都让我想到了问题:PerCall的InstanceContextMode是否应该在服务中强制执行线程安全,即使ConcurrencyMode设置为多个? How would it be possible for two calls to be serviced by the same service instance? 如何通过同一个服务实例为两个调用提供服务?

Thanks! 谢谢!

The only way to have two different WCF clients, ie, proxies, reference the same instance of your WCF service is to use InstanceContextMode=InstanceContextMode.Single . 拥有两个不同的WCF客户端(即代理)引用WCF服务的同一实例的唯一方法是使用InstanceContextMode=InstanceContextMode.Single This is a poor choice if scaling is an issue, so you want to use PerCall if you can. 如果缩放是一个问题,这是一个糟糕的选择,所以如果可以,你想要使用PerCall

When you use PerCall , each CALL to the WCF service gets its own WCF service instance . 使用PerCallWCF服务的每个CALL都会获得自己的WCF服务实例 There's no sharing of the service instance, but that doesn't mean that they don't share the same back-end storage (eg, database, memory, file, etc.). 没有共享服务实例,但这并不意味着它们不共享相同的后端存储(例如,数据库,内存,文件等)。 Just remember, PerCall allows each call to access your WCF service simultaneously. 请记住, PerCall允许每个调用同时访问您的WCF服务。

The ConcurrencyMode setting controls the threading model of the service itself. ConcurrencyMode设置控制服务本身的线程模型。 A setting of Single restricts all of the WCF service instances to running on the same thread. 设置为Single将所有WCF服务实例限制为在同一线程上运行。 So if you have multiple clients connecting at the same time, they will only be executed one at a time on the WCF service side. 因此,如果您同时连接多个客户端,则它们将仅在WCF服务端一次执行一个。 In this case, you leverage WCF to provide synchronization. 在这种情况下,您可以利用WCF提供同步。 It'll work fine, as you have seen, but think of this as having only macro-level control over synchronization - each WCF service call will execute in its entirety before the next call can execute. 正如您所见,它会正常工作,但我认为这只是对同步的宏级控制 - 每个WCF服务调用将在下一次调用执行之前完整执行。

Setting ConcurrencyMode to Multiple , however, will allow all of the WCF service instances to execute simultaneously. 但是,将ConcurrencyMode设置为Multiple将允许所有WCF服务实例同时执行。 In this case, you are responsible for providing the necessary synchronization . 在这种情况下, 您负责提供必要的同步 Think of this as having micro-level control over synchronization since you can synchronize only those portions of each call that need to be synchronized. 可以将其视为对同步进行微级控制,因为您只能同步每个需要同步的调用的那些部分。

I hope I've explained this well enough, but here's a snippet of the MSDN documentation for ConcurrencyMode just in case: 我希望我已经很好地解释了这一点,但这里是ConcurrencyMode的MSDN文档的片段,以防万一:

Setting ConcurrencyMode to Single instructs the system to restrict instances of the service to one thread of execution at a time, which frees you from dealing with threading issues. 将ConcurrencyMode设置为Single指示系统一次将服务实例限制为一个执行线程,这使您无需处理线程问题。 A value of Multiple means that service objects can be executed by multiple threads at any one time. 值Multiple表示服务对象可以在任何时候由多个线程执行。 In this case, you must ensure thread safety. 在这种情况下,您必须确保线程安全。

EDIT 编辑

You asked 您询问

Is there any performance increase, then, using PerCall vs. Single when using ConcurrencyMode.Single? 那么,在使用ConcurrencyMode.Single时,使用PerCall与Single是否有任何性能提升? Or is the inverse true? 或者是反过来的?

This will likely be service dependent. 这可能取决于服务。

With InstanceContextMode.PerCall , a new service instance is created for each and every call via the proxy, so you have the overhead of instance creation to deal with. 使用InstanceContextMode.PerCall ,将通过代理为每个调用创建一个新的服务实例,因此您需要处理实例创建的开销。 Assuming your service constructor doesn't do much, this won't be a problem. 假设您的服务构造函数没有做太多,这不会是一个问题。

With InstanceContextMode.Single , only one service instance exists for the lifetime of the application, so there is practically no overhead associated with instance creation. 使用InstanceContextMode.Single ,在应用程序的生命周期中只存在一个服务实例,因此实际上没有与实例创建相关的开销。 However, this mode allows only one service instance to process every call that will ever be made. 但是,此模式仅允许一个服务实例处理将要进行的每个调用。 Thus, if you have multiple calls being made simultaneously, each call will have to wait for the other calls to finish before it can be executed. 因此,如果您同时进行多个呼叫,则每个呼叫都必须等待其他呼叫完成才能执行。

For what it's worth, here's how I've done this. 对于它的价值,这就是我如何做到这一点。 Use the PerCall instance context with Multiple concurrency. PerCall实例上下文与Multiple并发一起使用。 Inside your WCF service class, create static members to manage the back-end data store for you, and then synchronize access to these static members as necessary using the lock statement, volatile fields, etc. This allows your service to scale nicely while still maintaining thread safety. 在WCF服务类中,创建静态成员以管理后端数据存储,然后根据需要使用lock语句, volatile字段等同步对这些静态成员的访问。这使您的服务可以在保持良好的同时进行维护线程安全。

I believe the answer is the fact that there are multiple threads (on the client side) utilizing the same proxy instance, thus potentially allowing for multiple calls into the same instance. 我相信答案是有多个线程(在客户端)使用相同的代理实例,因此可能允许多个调用进入同一个实例。 This post has a more detailed explanation. 这篇文章有更详细的解释。

InstanceContextMode.PerCall and ConcurrencyMode.Single should be fine if you are not using two way callbacks on the server. 如果您不在服务器上使用双向回调, InstanceContextMode.PerCallConcurrencyMode.Single应该没问题。 In that case you will need to use ConcurrencyMode.Reentrant or callback will not be able to get access to locked service instance and a deadlock will occur. 在这种情况下,您将需要使用ConcurrencyMode.Reentrant或回调将无法访问锁定的服务实例,并且将发生死锁。

Since its a per call service instance creation it is impossible for other threads or calls to get access to it. 由于每次调用服务实例创建,因此其他线程或调用无法访问它。 As stated in article mentioned in other answers article such combination can still be a problem if session is creatd on a binding level AND you are using the same service proxy object. 正如在其他的答案中提到的文章指出文章这样的组合仍然是一个问题,如果会话在结合水平creatd并且正在使用相同的服务代理对象。

So if you don't use same proxy object or don't have a sessionful binding and dont use two way callbacks to client ( most likely they should be OneWay anyway) InstanceContextMode.PerCall and ConcurrencyMode.Single should be good. 因此,如果您不使用相同的代理对象或没有会话绑定,并且不使用双向回调到客户端(最有可能它们应该是OneWay) InstanceContextMode.PerCallConcurrencyMode.Single应该是好的。

I think its all depends on the requirement. 我认为这完全取决于要求。 If we are going to call the same service so many times then better we can use InstanceContextMode is Single and concurrencymode is multiple. 如果我们要多次调用相同的服务,那么我们可以使用InstanceContextMode是Single,并且concurrencymode是多个。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 具有ConcurrencyMode.Multiple和I​​nstanceContextMode.Single行为和多线程安全性的WCF服务 - WCF service with ConcurrencyMode.Multiple and InstanceContextMode.Single behavior and multithreading safety 将WCF Windows服务作为InstanceContextMode.PerCall运行 - Running WCF Windows Service as InstanceContextMode.PerCall WCF ConcurrencyMode Single和InstanceContextMode PerCall - WCF ConcurrencyMode Single and InstanceContextMode PerCall WCF ConcurrencyMode.Multiple - WCF ConcurrencyMode.Multiple 在WCF中使用ConcurrencyMode.Multiple的优缺点 - Pros and Cons of using ConcurrencyMode.Multiple in WCF InstanceContextMode.PerCall在wcf中充当InstanceContextMode.Single - InstanceContextMode.PerCall acts as a InstanceContextMode.Single in wcf 当服务为ConcurencyMode.Single时,如何制作单个WCF方法ConcurrencyMode.Multiple - How can I make a single WCF method ConcurrencyMode.Multiple when service is ConcurencyMode.Single WCF中的InstanceContextMode.PerCall是否会实例化所有静态变量/方法? - Will InstanceContextMode.PerCall in WCF instantiate all static variables/methods? 自托管WCF服务:ConcurrencyMode.Multiple但只使用一个线程? - Self-hosted WCF service: ConcurrencyMode.Multiple but only using one thread? 将InstanceContextMode.Single转换为InstanceContextMode.PerCall - convert InstanceContextMode.Single to InstanceContextMode.PerCall
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM