看来我可以在同一个WCF合同接口API的以下三个不同版本之间自由切换,而不会破坏客户端:
[ServiceContract]
interface IService
{
// Either synchronous
// [OperationContract]
// int SomeMethod(int arg);
// Or TAP
[OperationContract]
Task<int> SomeMethodAsync(int arg);
// Or APM
// [OperationContract(AsyncPattern = true)]
// IAsyncResult BeginSomeMethod(int arg, AsyncCallback callback, object state);
// int EndSomeMethod(IAsyncResult ar);
}
现有的测试客户端应用程序在没有任何重新编译或触摸的情况下继续工作。如果我重新编译服务并将其引用重新导入客户端应用程序,则 WSDL定义保持不变,1:1。
我的问题:
我们的想法是将一组同步SomeMethod
- 样式方法转换为TAP SomeMethodAsync
- 样式方法,在其实现中使用async/await
,从而提高WCF服务的可伸缩性,破坏现有客户。
此外,已知在.NET 3.5和.NET 4.0下WCF服务扩展的问题。它们记录在MSKB文章"WCF service may scale up slowly under load"和CodeProject文章"Tweaking WCF to build highly scalable async REST API"中。基本上,实现服务契约API并不是自然异步,WCF运行时仍然阻塞了请求线程。
答案 0 :(得分:12)
可以使用同步,EAP或(从.NET 4.5开始)TAP定义WCF操作。来自MSDN:
客户可以为开发人员提供他们选择的任何编程模型,只要遵守基础消息交换模式即可。因此,只要遵守指定的消息模式,服务就可以以任何方式实现操作。
您实际上可以在一个合约界面中拥有所有3种模式,并且它们都与同一条消息相关。
在线上,执行操作的方式没有区别。 WSDL(WCF从每个端点构建的ABC - 地址,绑定和合同)不会#39 ; t包含此信息。它是从操作描述生成的。
如果查看OperationDescription
中使用的ContractDescription
类,您会看到每个操作都包含以下属性:SyncMethod
,BeginMethod
, EndMethod
和TaskMethod
。在创建描述时,WCF将根据操作名称将所有方法组合到一个操作中。如果在不同模式(例如,不同参数)中具有相同名称的操作之间存在某些不匹配,则WCF将抛出异常详细说明错误的内容。 WCF自动假定(可选)&#34; Async&#34;基于任务的方法的后缀,以及APM的开始/结束前缀。
在这个意义上,客户端和服务器端完全不相关。从WSDL(svcutil
)生成代理类的实用程序可以为任何执行模式构建代理。它甚至不必是WCF服务。
在服务器端,如果实现了多个模式,WCF将按以下优先顺序仅使用一个:Task,Sync和APM。这是在MSDN的某处记录的,我现在无法找到它。但您可以查看参考源here。
总之,只要您不修改操作所代表的消息,您就可以安全地更改服务器实施。
关于缩放(应该是IMO的另一个问题)
ThreadPool.SetMinThreads
按某种因素增加金额(请参阅this post)。此设置在客户端也可能是有益的。如果在服务器端使用异步(调用其他服务,数据库等)时,线程情况可能会大大改善,因为您不会浪费等待IO完成的线程池线程
在这些情况下最好的事情是做很多基准测试。