【问题标题】:WCF - Fastest interprocess communicationWCF - 最快的进程间通信
【发布时间】:2011-05-28 00:07:03
【问题描述】:

A 有一个 Web 可访问的(通过 basicHttpBinding)WCF 服务,我还想从同一台机器上的其他 .NET 服务访问它,并尽可能提高性能。我知道 netNamedPipeBinding 非常适合这个,但想知道最好的配置是什么,我什至只会与其他 .NET 进程进行通信。

例如,我不一定需要使用 SOAP 之类的编码,因为这可能过于庞大,而且我不需要与 .NET 客户端以外的任何其他客户端兼容。我也不认为我需要任何安全措施。

为此目的最好的绑定配置(或任何其他配置)

【问题讨论】:

    标签: c# wcf named-pipes


    【解决方案1】:

    如您所述,NetNamedPipeBinding 绑定针对同机通信进行了优化:

    提供安全可靠的绑定 针对机上优化 交流。

    参考。 :System-Provided Bindings

    在 Juval Lowy 的书“Programming WCF Services”的第一章中,他提供了一个有用的决策活动图来选择正确的绑定:

    "你应该问的第一个问题 你自己是不是你的服务需要 与非 WCF 客户端交互。如果 答案是肯定的,如果客户 是旧版 MSMQ 客户端,请选择 MsmqIntegrationBinding 启用 您的服务通过 MSMQ 进行互操作 有这样的客户。如果你需要 与非 WCF 客户端互操作,并且 该客户需要基本的 Web 服务 协议(ASMX Web 服务),选择 BasicHttpBinding,它公开 您对外界的 WCF 服务 就好像它是一个 ASMX Web 服务 (即 WSI 基本配置文件)。这 缺点是你不能接受 大多数现代 WS-* 的优势 协议。但是,如果非 WCF 客户可以理解这些标准, 选择一种 WS 绑定,例如 WSHttpBinding, WSFederationHttpBinding,或 WSDualHttpBinding。如果你可以假设 客户端是 WCF 客户端,但 它需要离线或断开连接 交互,选择 NetMsmqBinding 使用 MSMQ 传输 消息。如果客户需要 连接的通信,但可能是 跨机器边界调用, 选择 NetTcpBinding 通过 TCP 进行通信。如果客户端 与服务在同一台机器上, 选择 NetNamedPipeBinding 使用命名管道最大化 表现。您可以微调绑定 基于额外的选择 标准,例如需要 回调(WSDualHttpBinding)或 联合安全 (WSFederationHttpBinding)。”

    【讨论】:

    • 感谢您的回复,但如果可以进行任何改进,我希望对绑定进行“微调”。例如,我认为默认情况下启用了安全性 - 我可以禁用它并节省一些开销。我假设使用了 SOAP 编码,但也许二进制会加快速度。也许甚至可以使用更快的自定义编码?任何有关优化绑定的建议将不胜感激。
    • 您似乎在说您想要“微调”绑定,然后再确定您需要这样做。您能否解释一下为什么需要这种性能以及您为确定此要求所做的工作?
    • 我测试了性能,发现使用 HTTP、命名管道并在同一个应用程序上执行的操作的 1,000 次迭代耗时:服务 (HTTP):5192 毫秒,服务(命名管道):4646 毫秒,应用:2971ms。我可以接受它会更慢,但我希望 NamedPipe 绑定比 HTTP 速度更接近应用程序速度(在本地运行相同的操作)。
    • 啊——为什么?它仍然需要序列化。想要调整它 - 使用 PROTOBUF 作为序列化协议。比 MS 的 XML / Binary 快得多。可通过谷歌下载的资源。
    【解决方案2】:

    当然,命名管道传输是最佳选择。

    在标准 NetNamedPipeBinding 上默认启用 EncryptAndSign 传输安全性。您当然想删除它,因为这样做会加快速度而不会对安全性产生任何实际影响,原因是I discuss here

    我还怀疑,但尚未确认,更改消息编码绑定元素可能会有所帮助。这是因为默认值是 WCF 专有的“带内字典的二进制编码”,它是 XML 信息集的编码,旨在减少冗余字节,例如在打开和关闭元素标签中:当涉及网络 IO 时,这是一个有价值的目标,但当消息传输完全在内存中时可能会浪费 CPU 工作(假设消息不是太大)。因此,更改为纯文本编码也可能会提高速度。

    【讨论】:

    • 链接已失效。您是否能够更新或发布相关信息?您的回答非常有帮助,我很乐意看到其余的内容。
    【解决方案3】:

    我知道这是一个很老的问题,但仍然值得回答。如前所述,命名管道速度最快,您需要禁用安全性,但如果您摆脱数据合约序列化并切换到基于流的传输模式,您将获得最显着的效果。

    使用类似这样的东西作为绑定配置:

                    new NetNamedPipeBinding
                    {
                        MaxReceivedMessageSize     = 524288000,
                        ReceiveTimeout             = TimeSpan.MaxValue, // never timeout
                        SendTimeout                = TimeSpan.MaxValue, // never timeout
                        ReaderQuotas               =
                        {
                            MaxStringContentLength = 655360000
                        },
                        TransferMode               = TransferMode.Streamed,
                        Security = new NetNamedPipeSecurity
                        {
                            Mode = NetNamedPipeSecurityMode.None,
                            Transport = new NamedPipeTransportSecurity
                            {
                                ProtectionLevel = ProtectionLevel.None
                            }
                        }
                    }
    

    像这样定义您的服务消息:

    [MessageContract]
    public class CallRequestMessage
    {
        [MessageHeader]
        public string Arg1;
        [MessageHeader]
        public int ParametersLen;
        [MessageBodyMember]
        public Stream Parameters;
    }
    
    [MessageContract]
    public class CallResponceMessage
    {
        [MessageHeader]
        public int ResultCode;
        [MessageHeader]
        public int ResultsLen;
        [MessageBodyMember]
        public Stream Results;
    }
    
    [ServiceContract]
    public interface ILocalServiceAPI
    {
        [OperationContract]
        CallResponceMessage Call(CallRequestMessage message);
    }
    

    这种方法的缺点是现在您必须自己序列化数据。我更喜欢将 protobuf 序列化直接用于 MemoryStream。将此流放入您的 CallRequestMessage.Parameters。

    不要忘记在消息头中传输 ParametersLen/ResultsLen,因为 Stream 是无限的(读取时您可能会收到 0 个字节,但与普通流不同,您应该继续读取)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-06-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-14
      • 1970-01-01
      相关资源
      最近更新 更多