WCF - 最快的进程间通信

发布于 2024-10-08 08:53:09 字数 280 浏览 4 评论 0原文

A 有一个可通过 Web 访问(通过 basicHttpBinding)的 WCF 服务,我还希望从同一台计算机上的其他 .NET 服务进行访问,并具有尽可能更高的性能。我知道 netNamedPipeBinding 非常适合此目的,但想知道如果我只与其他 .NET 进程进行通信,最好的配置是什么。

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

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

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

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. 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)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

淡淡绿茶香 2024-10-15 08:53:09

正如您所注意到的, NetNamedPipeBinding 绑定针对同机通信:

提供安全可靠的绑定
针对机器上进行了优化
沟通。

参考号: 系统提供的绑定

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

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

As you have noted, the NetNamedPipeBinding binding is optimised for same-machine communication:

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:

"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
connected communication, but could be
calling across machine boundaries,
choose the NetTcpBinding that
communicates over TCP. If the client
is on the same machine as the service,
choose the NetNamedPipeBinding that
uses named pipes to maximize
performance. You may fine-tune binding
selections based on additional
criteria such as the need for
callbacks (WSDualHttpBinding) or
federated security
(WSFederationHttpBinding)."

泛滥成性 2024-10-15 08:53:09

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

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

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

Certainly the Named Pipe transport is the best choice.

Transport security with EncryptAndSign is enabled by default on the standard NetNamedPipeBinding. 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 e.g. 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). Thus changing to a plain text encoding might also provide a speed improvement.

梦幻的心爱 2024-10-15 08:53:09

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

使用类似这样的内容作为绑定配置:

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

此方法的缺点是现在您必须自己序列化数据。与 MemoryStream 相比,我更喜欢直接使用 protobuf 序列化。将此流放置到您的 CallRequestMessage.Parameters 中。

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

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. Place this stream to your 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).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文