无状态 WCF 服务中的 ConcurrencyMode.Multiple
我们当前有多个使用默认 ServiceBehavior
的 WCF 服务。由于可扩展性问题,我们正在考虑应用 ConcurrencyMode = ConcurrencyMode.Multiple
属性来提高吞吐量。我们所有的服务调用都是完全无状态的,例如:
PersonService.cs:
public class PersonService : IPersonService
{
public GetPersonResponse GetPerson(GetPersonRequest request)
{
GetPersonResponse response = new GetPersonResponse();
try
{
response.Person = Person.GetPerson(request.PersonID);
return response;
}
catch (Exception ex)
{
return (GetPersonResponse) response.SetException(ex);
}
}
}
Person.cs:
public static class Person
{
public static PersonDataContract GetPerson(int personID)
{
PersonDataContract pdc = null;
// load contract from db...
pdc = Database.Load<PersonDataContract>(personID);
// Address is another static class in the same pattern as Person
pdc.Addresses = Address.GetAddressesForPerson(personID);
return pdc;
}
}
Person 类中的所有方法都是静态的,以提高性能,无状态以保证线程安全。 Database 类也是静态的,但它的方法引用静态变量。
在这种情况下,为了使 ConcurrencyMode.Multiple 不会导致多线程问题,需要如何确保线程安全?我只考虑 Database
类,但是 Person
类(以及遵循相同模式的所有其他类)也需要锁定吗?
我知道所有类都应该是防弹的,以实现最大的安全性,但不幸的是时间限制不允许这样做......我们需要尽快交付代码。
We currently have multiple WCF services which are using the default ServiceBehavior
. Due to issues with scalability, we are looking at applying the ConcurrencyMode = ConcurrencyMode.Multiple
attribute to improve throughput. All of our service calls are completely stateless, for example:
PersonService.cs:
public class PersonService : IPersonService
{
public GetPersonResponse GetPerson(GetPersonRequest request)
{
GetPersonResponse response = new GetPersonResponse();
try
{
response.Person = Person.GetPerson(request.PersonID);
return response;
}
catch (Exception ex)
{
return (GetPersonResponse) response.SetException(ex);
}
}
}
Person.cs:
public static class Person
{
public static PersonDataContract GetPerson(int personID)
{
PersonDataContract pdc = null;
// load contract from db...
pdc = Database.Load<PersonDataContract>(personID);
// Address is another static class in the same pattern as Person
pdc.Addresses = Address.GetAddressesForPerson(personID);
return pdc;
}
}
All methods in the Person
class are static to help performance, and stateless for thread safety. The Database
class is also static, but its methods reference static variables.
In this context, what needs to be made thread-safe in order for ConcurrencyMode.Multiple
to not cause multithreading issues? I'm thinking only the Database
class, but does the Person
class (and all other classes that follow the same pattern) need to be locked as well?
I know that all classes should be bulletproofed for maximum safety, but unfortunately time constraints don't allow this... we need to get code delivered ASAP.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
如果您使用默认的“每次调用”激活机制(如果您的服务完全无状态,则该机制非常有效),那么添加 ConcurrencyMode.Multiple 绝对没有意义,因为每个传入请求都会获得自己的实例处理其请求的服务类。这是
InstanceContextMode
的首选和推荐设置。在 MSDN 杂志上阅读有关 WCF 实例管理的更多信息:探索用于开发 WCF 的强大实例管理技术应用
唯一能从使用 ConcurrencyMode.Multiple 中受益的时候是当您拥有单例 WCF 服务时 - 但强烈建议不要这样做,因为它 a) 可扩展性的一大障碍,b) )正确编程非常棘手。
我的建议是:尝试更详细地缩小真正导致性能问题的原因。仅仅跳入 ConcurrencyMode.Multiple 似乎是错误的方法 - 它非常混乱,非常劳动密集型,大量代码,很多出错的机会......
If you use the default "per call" activation mechanism (which works great if your services are completely stateless), there's absolutely no point in adding the
ConcurrencyMode.Multiple
since each incoming request will get its own instance of the service class to handle its request. This is the preferred and recommended setting forInstanceContextMode
.Read more about instance management in WCF at MSDN Magazine: Discover Mighty Instance Management Techniques For Developing WCF Apps
The only time when you benefit from using
ConcurrencyMode.Multiple
is when you have a singleton WCF service - but this is highly discouraged, since it's a) a big hindrance for scalability, and b) extremely tricky to program properly.My recommendation would be: try to narrow down more in detail what really causes the performance problems. Just jumping into
ConcurrencyMode.Multiple
seems like the wrong approach - it's very messy, very labor-intensive, lots of code, lots of chance of getting it wrong......如果您的服务是无状态且线程安全的,则最好将 InstanceContextMode.Single 与 ConcurrencyMode.Multiple 结合使用。
这将避免创建服务实例,减少内存占用,减少GC活动。
几乎我开发的每项服务都是以这种方式完成的......
除非需要为每个调用或会话保留单独的实例,否则我会按照他的方式进行。
其他答案提到“单例 WCF 服务 - 但这是非常不鼓励的,因为它 a) 可扩展性的一大障碍,b) 正确编程极其棘手。”
我们并不强烈劝阻它,对可扩展性没有影响(事实上可能是有益的),而且没有什么棘手的。
更新:对于 InstanceContextMode.Single 的作用似乎存在混淆。
此设置将强制 WCF 引擎仅创建该服务的一个实例。
有些人错误指出它不适用于 basicHttpBinding。
所以我发布一个例子来一劳永逸地解决这个问题。
这是我的服务类:
这是我的服务合同:
这是我的配置文件:
现在是结果的一些屏幕截图:
这是第一个请求,您可以看到计数为 1:
现在我再次点击,你可以看到计数是2:
点击几下后:
如您所见,它是一个SINGLE实例,在多个请求中保存一个变量
If your service is stateless and thread safe it is better to use InstanceContextMode.Single combined with ConcurrencyMode.Multiple.
This will avoid the creation of instances of the service, reduce the memory footprint, reduce GC activity.
Almost every service I develop is done in this way....
Unless there was the need to keep separate instances per call or session I would got his way.
Other answers mention "singleton WCF service - but this is highly discouraged, since it's a) a big hindrance for scalability, and b) extremely tricky to program properly."
It is NOT highly discouraged, has no impact on scalability ( as a matter of fact can be benefitial ), and there is NOTHIN tricky about it.
UPDATE: There seems to be confusion about what InstanceContextMode.Single does.
This setting will force the WCF engine to create only ONE instance of the service.
Some people have WRONGLY stated it does not work with basicHttpBinding.
So I am posting an example to clear this once and for all.
Here is my Service class:
Here is my service contract:
This is my config file:
And now some screen shots of the results:
This is the first request as you can see the count is 1:
Now I click again and you can see the count is 2:
A few clicks later:
As you can see it is a SINGLE instance keeping a variable across many requests.