A具有Web可访问(通过basicHttpBinding)WCF服务,我也希望从同一台机器上的其他.NET服务访问,并尽可能提高性能。我知道netNamedPipeBinding是理想的,但是想知道什么是最好的配置,我甚至只会与其他.NET进程通信。
例如,我不一定使用像SOAP这样的编码,因为它可能太笨重,而且我不需要与.NET客户端以外的任何其他客户端兼容。我也认为我不需要任何安全措施。
为此目的(或任何其他配置)的最佳绑定配置是什么
答案 0 :(得分:9)
正如您所指出的,NetNamedPipeBinding绑定针对同一台机器通信进行了优化:
提供安全可靠的绑定 这是针对机上优化的 通信。
在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个字节,但与普通流不同,你应该继续阅读)。