我们有一个web服务,它将请求发送到一个承载WCF服务以进行处理的windows服务。
接口很简单:
namespace MyApp
{
[ServiceContract]
public interface IMyApp
{
[OperationContract]
string DoSomething(string xml);
}
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
class MyAppWcf : IMyApp
{
public string DoSomething(string xml)
{
Customer customer = GlobalObject.GetCustomer(xml); //millisecs
return customer.DoSomething(xml); //Takes 5-10 seconds
}
}
}GlobalObject在WindowsService.OnStart()上实例化,并包含客户对象需要的所有静态数据。接口DoSomething()将被调用到大约30个不同的客户端。
问题:
实问题:
有多达1000个客户对象,两个不同的客户对象可以并行调用,但同一个客户对象不能。例如:
DoSomething("Customer 1");=>继续前进。10秒后回答
DoSomething("Customer 2");=>与上述调用并行进行。
DoSomething("Customer 2");=>将等待DoSomething("Customer 2")的最后调用完成
我的服务行为设置应该是什么?我是否必须实现一个锁机制来防止同一个对象被并行处理不止一次?
谢谢。
编辑2: GlobalObject.GetCustomer()只是从字典中检索XML中提到的客户。
发布于 2010-11-18 16:51:33
好的。我不知道在使用ConcurrencyMode实例时是否忽略了PerCall,但在我自己的项目中,我使用PerCall实例,没有为ConcurrencyMode指定任何值。很明显,我曾经知道这一点,只是没有把它记录在我的代码中。这一点现在已得到纠正。
我的项目非常像您描述的那样工作,正如我已经提到的那样,我使用了InstanceContextMode.PerCall。这是什么意思。
MyAppWcfInst.DoSomething( "<customer id=A/>" );
MyAppWcfInst.DoSomething( "<customer id=B/>" );
MyAppWcfInst.DoSomething( "<customer id=B/>" );
所有三个客户端都将同时与您的WCF服务交互,但每个客户端都有自己的实例,并在一个单独的线程中操作。因此,虽然每个客户端的每个调用都是单线程的,但它们可以同时处于活动状态。这意味着多个客户端可以同时访问客户对象列表。
Client1和Client2可以并行操作,因为它们处理不同的客户对象,但是Client3需要等到Client2完成后才能使用CustomerB“做一些事情”。这意味着您需要同步每个Customer对象内的访问。换句话说,Customer.DoSomething()方法中的逻辑需要有一个同步锁,以防止多个客户机同时对客户进行操作。
class Customer
{
private object _sync = new object();
public string DoSomething( string xml )
{
lock (_sync)
{
// put your logic here...
}
}
}这就是我的WCF服务的工作方式。希望这能有所帮助。
发布于 2010-11-18 16:30:38
使用PerCall,您将并行处理对服务的请求,每个请求都位于MyAppWcf类的不同实例上。如果没有可用的空闲.NET线程来调度请求,则只需要等待较早的请求完成。如果将其更改为单个,则除非将ConcurrencyMode设置为Multiple,否则请求将被序列化。
您真正关心的应该是并发访问GobalObject方法的安全性:如果这不安全,那么上面的代码也不安全。
同样,对于Customer.DoSomething方法,如果它触及任何共享数据(例如调用GlobalObject本身)。
我不明白您所说的“一次只能处理一个客户对象”是什么意思。如果这是真的,那么无论如何您都需要避免并行执行。
https://stackoverflow.com/questions/4216379
复制相似问题