WCF - 最快的进程间通信

时间:2010-12-19 23:05:52

标签: c# wcf named-pipes

A具有Web可访问(通过basicHttpBinding)WCF服务,我也希望从同一台机器上的其他.NET服务访问,并尽可能提高性能。我知道netNamedPipeBinding是理想的,但是想知道什么是最好的配置,我甚至只会与其他.NET进程通信。

例如,我不一定使用像SOAP这样的编码,因为它可能太笨重,而且我不需要与.NET客户端以外的任何其他客户端兼容。我也认为我不需要任何安全措施。

为此目的(或任何其他配置)的最佳绑定配置是什么

3 个答案:

答案 0 :(得分:9)

正如您所指出的,NetNamedPipeBinding绑定针对同一台机器通信进行了优化:

  

提供安全可靠的绑定   这是针对机上优化的   通信。

参考。 :System-Provided Bindings

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

  

“你应该问的第一个问题   你自己是否需要服务   与非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)。“

答案 1 :(得分:4)

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

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

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

答案 2 :(得分:1)

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

使用类似这样的绑定配置:

                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个字节,但与普通流不同,你应该继续阅读)。