简体   繁体   English

WCF - 最快的进程间通信

[英]WCF - Fastest interprocess communication

A have a web-accessible (via basicHttpBinding) WCF service which I also want to access from other .NET services on the same machine with as higher performance as possible. A具有Web可访问(通过basicHttpBinding)WCF服务,我也希望从同一台机器上的其他.NET服务访问,并尽可能提高性能。 I understand that the netNamedPipeBinding is ideal for this, but wonder what the best configuration would be given that I'm only even going to be communicating with other .NET processes. 我知道netNamedPipeBinding是理想的,但是想知道什么是最好的配置,我甚至只会与其他.NET进程通信。

For example, I needn't necessarily use an encoding such as SOAP as this is perhaps too bulky and I don't need the compatibility with any other clients other than a .NET client. 例如,我不一定使用像SOAP这样的编码,因为它可能太笨重,而且我不需要与.NET客户端以外的任何其他客户端兼容。 I also don't think I need any security. 我也认为我不需要任何安全保障。

What would be the best binding configuration for this purpose (or any other configurations for that matter) 什么是最好的绑定配置为此目的(或任何其他配置)

As you have noted, the NetNamedPipeBinding binding is optimised for same-machine communication: 如您所知NetNamedPipeBinding绑定针对同一台机器通信进行了优化:

Provides a secure and reliable binding that is optimized for on-machine communication. 提供安全可靠的绑定,针对机上通信进行了优化。

Ref. 参考。 : System-Provided Bindings 系统提供的绑定

In chapter one of Juval Lowy's book, "Programming WCF Services", he provides a useful decision-activity diagram for choosing the right binding: 在Juval Lowy的书“编程WCF服务”的第一章中,他提供了一个有用的决策活动图,用于选择正确的绑定:

"The first question you should ask yourself is whether your service needs to interact with non-WCF clients. If the answer is yes, and if the client is a legacy MSMQ client, choose the MsmqIntegrationBinding that enables your service to interoperate over MSMQ with such a client. If you need to interoperate with a non-WCF client and that client expects basic web service protocol (ASMX web services), choose the BasicHttpBinding, which exposes your WCF service to the outside world as if it were an ASMX web service (that is, a WSI-basic profile). The downside is that you cannot take advantage of most of the modern WS-* protocols. However, if the non-WCF client can understand these standards, choose one of the WS bindings, such as WSHttpBinding, WSFederationHttpBinding, or WSDualHttpBinding. If you can assume that the client is a WCF client, yet it requires offline or disconnected interaction, choose the NetMsmqBinding that uses MSMQ for transporting the messages. If the client requires conn “您应该问自己的第一个问题是您的服务是否需要与非WCF客户端进行交互。如果答案是肯定的,并且客户端是传统的MSMQ客户端,请选择MsmqIntegrationBinding,使您的服务能够通过MSMQ与MSMQ进行互操作。如果您需要与非WCF客户端进行互操作,并且该客户端需要基本的Web服务协议(ASMX Web服务),请选择BasicHttpBinding,它将您的WCF服务公开给外部世界,就好像它是ASMX Web服务一样(也就是WSI基本配置文件。。缺点是您无法利用大多数现代WS- *协议。但是,如果非WCF客户端可以理解这些标准,请选择其中一个WS绑定,例如WSHttpBinding,WSFederationHttpBinding或WSDualHttpBinding。如果您可以假设客户端是WCF客户端,但它需要脱机或断开连接,请选择使用MSMQ传输消息的NetMsmqBinding。如果客户端需要conn ected communication, but could be calling across machine boundaries, choose the NetTcpBinding that communicates over TCP. 通过通信,但可以跨机器边界调用,选择通过TCP进行通信的NetTcpBinding。 If the client is on the same machine as the service, choose the NetNamedPipeBinding that uses named pipes to maximize performance. 如果客户端与服务位于同一台计算机上,请选择使用命名管道的NetNamedPipeBinding以最大限度地提高性能。 You may fine-tune binding selections based on additional criteria such as the need for callbacks (WSDualHttpBinding) or federated security (WSFederationHttpBinding)." 您可以根据其他条件(例如需要回调(WSDualHttpBinding)或联合安全性(WSFederationHttpBinding))来微调绑定选择。“

Certainly the Named Pipe transport is the best choice. 当然,命名管道运输是最好的选择。

Transport security with EncryptAndSign is enabled by default on the standard NetNamedPipeBinding. 默认情况下,在标准NetNamedPipeBinding上启用使用EncryptAndSign的传输安全性。 You certainly want to remove this, as doing so will speed things up without any real impact on security, for the reasons I discuss here . 你当然希望删除它,因为这样做会加快速度而不会对安全性产生任何实际影响,原因我在这里讨论

I also suspect, but have not yet confirmed, that changing the message encoding binding element may help. 我也怀疑,但尚未确认,更改消息编码绑定元素可能会有所帮助。 This is because the default is the WCF proprietary 'binary encoding with in-band dictionary', which is an encoding of an XML infoset which aims to reduce redundant bytes eg in opening and closing element tags: a worthy aim when network IO is involved, but maybe wasted CPU effort when message transfer is entirely in-memory (provided the messages are not too big). 这是因为默认值是WCF专有的“带内字典二进制编码”,它是XML信息集的编码,旨在减少冗余字节,例如打开和关闭元素标签:当涉及网络IO时,这是一个有价值的目标,但是当消息传输完全在内存中时(如果消息不是太大),可能会浪费CPU工作量。 Thus changing to a plain text encoding might also provide a speed improvement. 因此,改变为纯文本编码也可以提高速度。

I Understand this is a pretty old question, but it still worth answering. 我知道这是一个非常古老的问题,但它仍然值得回答。 As already mentioned named pipes are fastest and you need to disable security, but the most dramatic effect you'll get if you get rid of data contract serialization and switch to stream-based transfer mode. 如前所述,命名管道是最快的,您需要禁用安全性,但如果您摆脱数据协定序列化并切换到基于流的传输模式,您将获得最显着的效果。

Use something like this as binding configuration: 使用类似这样的绑定配置:

                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
                        }
                    }
                }

Define your service messages like this: 像这样定义您的服务消息:

[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);
}

The downside of this method is that now you have to serialize your data yourself. 这种方法的缺点是现在你必须自己序列化你的数据。 I prefer using protobuf serialization directly to MemoryStream. 我更喜欢将protobuf序列化直接用于MemoryStream。 Place this stream to your CallRequestMessage.Parameters. 将此流放入CallRequestMessage.Parameters。

Don't forget to transfer ParametersLen/ResultsLen in the message header as Stream is endless (while reading you'll may receive 0 bytes, but unlike normal streams you should continue reading). 不要忘记在消息头中传输ParametersLen / ResultsLen,因为Stream是无限的(读取时你可能会收到0个字节,但与普通流不同,你应该继续阅读)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM