为什么MSMQ比WCF QueueService更快?

时间:2012-07-03 09:47:17

标签: .net wcf performance msmq

我在带有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个项目(=批量)时,它将批量传递给另一个线程,它所做的就是使用以下两种方法之一将该批量排入队列:

  1. 如果启用了wcf:wcfQueueService.Send(bulk);
  2. 如果启用了MSMQ,则为其他:new MessageQueue(@".\private$\q").Send(new Message {Body = bulk});
  3. 所有两种方法都有效,但MSMQ的工作速度要快得多。使用MSMQ客户端设置在20秒内处理大约80K批量,而wcf只有20K-30K批量处理。 我不明白为什么会这样。我的WCF在不同的过程中运行,就像MSMQ一样。另外,我的WCF不存储任何东西,它有空方法。那么为什么MSMQ赢得WCF?

    更新

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

    1. 它仍然比MSMQ慢
    2. 当我读到.Net Remoting被WCF弃用,根据this,WCF应该比.Net Remoting更快,那么为什么我得到的是我的wcf更慢?也许我的绑定错了?

3 个答案:

答案 0 :(得分:4)

你没有比较喜欢。

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

更重要的是,根据您配置服务实例化和限制旋钮的方式,客户端的请求可能比服务配置为处理更快,导致请求本身排队等待执行服务方面。

此外,根据您配置绑定的方式,可能存在其他重大差异,例如安全性。顺便说一句,你真的使用NetNamedPipeBinding(作为你的问题陈述)而不是NetMsmqBinding,因为标题似乎意味着什么?如果是这样,使用默认绑定配置,您将进行totally unnecessary加密并签署每个Bulk消息,这在您的直接MSMQ情况下不会发生。对大型消息的这些加密操作也会相对昂贵。

更好的比较将是定义为OneWay的WCF操作。

答案 1 :(得分:1)

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

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

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

除非我在我的结尾出错,否则WCF版本的速度几乎是硬编码MSMQ等效速度的两倍。

答案 2 :(得分:0)

我认为不同之处在于您的WCF操作与MSMQ接受请求时的操作之间的区别。

我希望用MSMQ简单排队消息时执行的方法接受消息而不接受任何其他消息。一些后端工作人员负担沉重。

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

通过使用.NET 4中的任务并行库来并行化您的请求,您还可以找到改进的性能。