我在带有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个项目(=批量)时,它将批量传递给另一个线程,它所做的就是使用以下两种方法之一将该批量排入队列:
wcfQueueService.Send(bulk);
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。但是,
答案 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中的任务并行库来并行化您的请求,您还可以找到改进的性能。