为啥 MSMQ 比 WCF QueueService 快?

Posted

技术标签:

【中文标题】为啥 MSMQ 比 WCF QueueService 快?【英文标题】:Why is MSMQ faster than WCF QueueService?为什么 MSMQ 比 WCF QueueService 快? 【发布时间】:2012-07-03 17:35:57 【问题描述】:

我在控制台中使用 netNamedPipeBinding 绑定自托管 WCF 服务。该服务只有一个空方法Send(DataTable bulk)

[ServiceContract]
public interface IWcfQueueService

    [OperationContract]
    void Send(DataTable bulk);       

public class WcfQueueService : IWcfQueueService

    public void Send(DataTable bulk)
               
       // Here would be something like _bulks.Add(bulk);
       // BUT, for now it is empty method and still it's slower than MSMQ
        

我的客户从 DB 获得 200K 输入并使用我们的 BoundedThreadPool 处理它(仅创建,比如说,20 个线程)。每个输入都用不同的线程处理。每个线程执行MyMethod 并在MyMethod 的末尾将结果添加到bulkManager

public void MyMethod(string input)
            
    var res = ProcessInput(input);
    bulkManager.Add(res);

bulkManager 累积 N 项 (=bulk) 时,它将批量传递给另一个线程,它所做的只是使用以下两种方法之一将该批量加入队列:

    如果启用 wcf:wcfQueueService.Send(bulk); 如果启用了 MSMQ,则为:new MessageQueue(@".\private$\q").Send(new Message Body = bulk);

这两种方法都有效,但 MSMQ 的工作速度要快得多。使用 MSMQ 客户端可以在 20 秒内处理大约 80K 块,而使用 wcf 只能处理 20K-30K 块。 我不明白为什么会这样。我的 WCF 像 MSMQ 一样在不同的进程中运行。另外,我的 WCF 不存储任何东西,它有空方法。那么为什么 MSMQ 会赢得 WCF?

更新

正如leppie 建议的那样,我尝试了.NetRemoting。 NetRemoting 确实提高了速度。客户端处理了 60K。但是,

    还是比 MSMQ 慢 当我阅读 .Net Remoting 已被 WCF 弃用时,根据this,WCF 应该比 .Net Remoting 更快,那么为什么我会发现我的 wcf 更慢?也许我的绑定有误?

【问题讨论】:

你可能会发现远程处理比 MSMQ 快很多(给定命名管道,我假设 IPC 在本地机器上)。 @leppie,.Net Remoting 确实提高了速度。客户端处理了 60K。但是,1 - 它仍然比 MSMQ 慢,2 - 当我读到 .Net Remoting 已被 WCF 弃用,根据msdn.microsoft.com/en-us/library/…,WCF 应该比 .Net Remoting 快,那么为什么我知道我的 wcf 更慢? @theateist:你能把服务上的InstanceContextMode改成SingleConcurrencyMode改成Multiple吗?然后再做一次测试。也尝试调整节流设置(在服务行为中)。 @theateist:WCF 仅在非 IPC 方案中“替换”.NET 远程处理。 WCF 本质上是断开连接的,而远程处理“主要是连接的”。 .NET 远程处理永远不会消亡! :) @leppie:来吧,伙计……你在说什么?它已经死了:)。 【参考方案1】:

我认为区别在于 WCF 操作中发生的情况与 MSMQ 在接受请求时所做的情况。

我希望当您使用 MSMQ simple 将消息排入队列时执行的方法会接受该消息,而不接受其他任何内容。一些后端工人负责繁重的工作。

在您的操作中,您需要将请求传递给请求处理程序的单例实例。当服务“启动”时,应该实例化请求处理程序实例。

您还可以通过使用 .NET 4 中的任务并行库来并行化您的请求来提高性能。

【讨论】:

【参考方案2】:

您能否提供示例代码来显示您所看到的行为?

我通过生成 20,000 条要发送的消息进行了自己的测试。我尝试了两种方式,20,000 使用直接 MSMQ,20,000 使用 WCF 为我抽象 MSMQ 端点。

带有直接 MSMQ 的 20,000 使用了 64.75% 的 CPU 时间,而发送 20,000 条消息的 WCF 版本使用了 34.16% 的 CPU 时间(使用 Visual Studio Ultimate 的分析功能进行检测)。

除非我自己犯了错误,否则 WCF 版本的速度几乎是硬编码 MSMQ 版本的两倍。

【讨论】:

【参考方案3】:

你不是在比较喜欢和喜欢。

最明显的区别是,在 WCF 案例中,您的时间包括执行整个服务端通道堆栈和操作调用,而您的直接 MSMQ 案例仅测量在客户端将有效负载排入队列的时间。请记住,WCF 中的服务端处理包括您的 DataTable 对象的反序列化,如果您的体积因子 N 很大,这可能会非常昂贵。

此外,根据您配置服务实例化和节流旋钮的方式,来自客户端的请求可能会比服务配置处理的速度更快,从而导致请求本身在队列中等待执行服务端。

此外,根据您配置绑定的方式,可能存在其他显着差异,例如安全性。顺便说一句,您是否真的使用 NetNamedPipeBinding (如您的问题所述)而不是标题似乎暗示的 NetMsmqBinding?如果是这样,使用默认绑定配置,您将拥有totally unnecessary 加密和签名每条批量消息,这在您的直接 MSMQ 案例中不会发生。这些对大型消息的加密操作也会相对昂贵。

与定义为 OneWay 的 WCF 操作进行更好的比较。

【讨论】:

那个“完全没有必要”的链接已经失效了,你有机会获得该条目的副本吗?真的有兴趣阅读,谢谢

以上是关于为啥 MSMQ 比 WCF QueueService 快?的主要内容,如果未能解决你的问题,请参考以下文章

IIS 中的 WCF,在工作组模式下使用 MSMQ

WCF net.msmq 服务自动激活

如何处理 WCF 的 MSMQ 绑定中的消息失败

如何在使用 WCF 的事务性 MSMQ 中将消息显式标记为中毒

将 MSMQ 端到端跟踪与 WCF 跟踪和应用程序级日志记录相关联

WCF msmq 事务和工作单元