我有一个WCF服务,可以为多个客户端提供服务。 他们将进行“接受建议匹配”或“拒绝建议匹配”等操作。 我希望所有操作都能按顺序运行,但我担心这会对性能产生影响。
从我看到的 - 默认(和最常用的)实例是'Per Call',默认的并发模式是单一的。
所以我需要在并发中使用'Single'模式吗? 它有多么糟糕?
(我估计最多有几十个客户使用该系统。)
有没有办法享受这两个世界?
使用并行计算(服务与数据库通信)并仍然连续执行操作?
在此post中,我读到了“实例模式=每次调用和并发=单个”:
似乎这并不能保证我会连续执行操作调用!
例如,如果发生这种情况:
从我读到的内容 - 它说'单个线程将用于服务从单个客户端实例'生成的所有WCF实例。这听起来像是意味着CALL 1和CALL 2将以串行方式执行,但CALL 3可能会在它们之间执行,因为它来自不同的客户端线程。
这是真的吗?有没有办法确保按照他们到达的顺序处理呼叫?
有人可以告诉我这是不是一种不好的做法,或者是否有真实世界的场景,在WCF中接受并建议使用这种通信方式。
非常感谢
答案 0 :(得分:2)
我认为有3种方法可以回答这个问题
我想首先给出答案2和3(因为我觉得它们更好)但我会在最后给出一个直接答案......我保证!
我认为您的问题并不是您需要按照服务接收的顺序处理邮件,而是因为您拥有独立的客户,您无法保证服务同时收到它们订购它们是从客户发送的。
考虑一下客户ALPHA和BETA的例子。即使客户端ALPHA可能在客户端BETA调用操作C之前将请求发送到呼叫操作2,您也无法知道服务将接收它们的顺序。这意味着即使您按照收到的顺序在服务器上处理它们,这可能仍然是错误的"顺序。
如果您同意,请继续阅读。如果没有,请直接回到本文底部的直接答案; o)
方法1:使用WS-Transactions
如果您同时控制服务和客户端,并且客户端能够实现WS- * SOAP协议(例如.Net WCF客户端)。然后,您可以使用WS-Transaction协议来确保单个客户端中要在单个长时间运行的事务中处理的操作肯定是以这种方式完成的。
有关如何使用WCF进行WS-Transcation的详细信息,请查看
http://msdn.microsoft.com/en-us/library/ms752261.aspx
按照客户端ALPHA和BETA的示例,这将启用客户端ALPHA
ALPHA在客户端上启动事务的效果是将该事务传递到服务器,以便它可以创建一个DB事务,以保证操作1和操作2一起完成或根本不完成。
如果客户端BETA在此过程中调用操作3,则会强制它等待事务提交或中止。请注意,这可能会导致操作3超时,在这种情况下,BETA需要处理该错误。
此行为适用于任何InstanceContextMode
或ConcurrencyMode
。
然而,缺点是这种长时间运行的分布式事务通常不利于可伸缩性。今天你有10个客户,但未来会增长吗?客户是否总能实现WS-Transaction?如果是这样,那么这可能是一个很好的方法。
方法2:使用"乐观"类型方法
如果您需要支持许多不同的客户端类型(例如电话,浏览器等),那么您可以允许操作以任何顺序发生,并确保服务和客户端逻辑可以处理故障。
这可能听起来很糟糕,但
这里的缺点是你需要仔细考虑你需要什么样的故障逻辑,并确保客户端和服务代码是健壮的并且行为恰当。
在您的示例中,我提到ALPHA可以同步自己的调用,但是如果在ALPHA调用操作1之后但在调用操作2之前BETA调用操作3,则可能是
有关MS Entity Framework上下文中的讨论,请参阅
http://msdn.microsoft.com/en-us/library/bb738618.aspx
有关它的一般性讨论,请参阅
http://en.wikipedia.org/wiki/Optimistic_concurrency_control
同样,在WCF术语中,这适用于任何ConcurrencyMode
和InstanceContextMode
这种方法是可扩展性很重要的最常用方法。它的缺点是用户体验可能很差(例如,他们可能会在不知情的情况下覆盖他们的更改)。
直接回答原始问题
如果你肯定需要确保邮件是连续处理的,我认为你正在寻找InstanceContextMode.Single
http://msdn.microsoft.com/en-us/library/system.servicemodel.instancecontextmode.aspx
这意味着在服务应用程序的生命周期中创建了一个服务类实例。如果您还使用ConcurrencyMode = Single
或ConcurrencyMode = Reentrant
这意味着您的服务一次只会处理一条消息(因为您有一个实例并且它是单线程的)并且消息将在命令他们收到。
如果您使用ConcurrencyMode = multiple
,那么您的单个服务实例将在不同的线程上同时处理多条消息,因此无法保证处理顺序。
这对性能产生的影响有多大将取决于每个服务调用执行的时间。如果你得到每秒10,每个需要0.1秒,那就没问题了。如果你每秒得到20,而每个通常需要0.1秒,你会看到平均时间增加100%。