不同形式的WCF服务合同接口

nos*_*tio 22 .net c# wcf asynchronous async-await

看来我可以在同一个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);
}
Run Code Online (Sandbox Code Playgroud)

现有的测试客户端应用程序无需重新编译或触摸即可继续工作.如果我重新编译服务并将其引用重新导入客户端应用程序,则WSDL定义保持不变,1:1.

我的问题:

  • 这是我可以依赖的合法行为吗?是否记录在任何地方?

我们的想法是将一组同步SomeMethod方法转换为TAP SomeMethodAsync风格的方法,以便async/await在其实现中使用,从而提高WCF服务的可扩展性,而不会破坏现有客户端.

此外,已知在.NET 3.5和.NET 4.0下WCF服务扩展的问题.它们记录在MSKB文章"WCF服务可能在负载下缓慢扩展"和CodeProject文章"调整WCF以构建高度可伸缩的异步REST API"中.基本上,将服务契约API实现为自然异步是不够的,WCF运行时仍然阻塞了请求线程.

  • 有没有人知道这个问题是否已经为.NET 4.5.x修复,开箱即用?或者还需要额外的调整?

Eli*_*bel 13

可以使用同步,EAP或(从.NET 4.5开始)TAP定义WCF操作.来自MSDN:

只要观察到基础消息交换模式,客户端就可以为开发人员提供他们选择的任何编程模型.因此,只要遵守指定的消息模式,服务也可以以任何方式实现操作.

实际上,您可以在单个合约界面中拥有所有3种模式,并且它们都与同一消息相关.

在线上,执行操作的方式没有区别.WSDL(WCF从每个端点的ABC构建 - 地址,绑定和合同)不包含此信息.它是根据操作说明生成的.

如果你看一下OperationDescription类,它是在使用ContractDescription,你会看到每个操作具有以下属性:SyncMethod,BeginMethod,EndMethodTaskMethod.在创建描述时,WCF将根据操作名称将所有方法组合到一个操作中.如果在不同模式中具有相同名称的操作之间存在一些不匹配(例如,不同的参数),WCF将抛出一个例外,详细说明错误.WCF自动假设(可选)基于任务的方法的"异步"后缀,以及APM的开始/结束前缀.

在这个意义上,客户端和服务器端完全不相关.从WSDL(svcutil)生成代理类的实用程序可以为任何执行模式构建代理.它甚至不必是WCF服务.

在服务器端,如果实现了多个模式,WCF将按以下优先顺序使用一个:任务,同步和APM.这是在MSDN的某处记录的,我现在无法找到它.但是你可以在这里查看参考源.

总之,只要不修改操作所代表的消息,就可以安全地更改服务器实现.

关于缩放(应该是IMO的另一个问题)

  • WCF的限制默认值已在.NET 4.5中更新为更合理的值,现在依赖于处理器(请参阅此处).
  • 线程池问题没有变化.问题源于完成端口线程池的初始大小,最初设置为逻辑处理器数量的4倍.你可以用ThreadPool.SetMinThreads一些因素来增加金额(见这篇文章).此设置在客户端也可能是有益的.

如果在服务器端使用异步(在调用其他服务,数据库等时),则线程情况可能会大大改善,因为您不会浪费等待IO完成的线程池线程.

在这些情况下最好的事情是做很多基准测试.