我有一个在WCF和MSMQ上运行的特定服务。 一切正常但我们有这样的要求,即如果在处理一项工作期间出现意外情况,则不应影响任何其他工作。 该服务旨在提供强大的功能。我们从未在两年的运营中崩溃,但最近我们的客户一直喜欢杀死服务流程并抱怨失去了多个工作。
为了调查我已经添加了一个定时器,它每200ms跟踪一次队列的内容并发现一些意想不到的东西。 处理请求时,WCF会从队列中删除多条消息。 这是相关事件的smartinspec跟踪(中间列中的数字是线程ID):
似乎总是在服务进程中的某处缓冲一条消息。 我一直在查看WCF文档,但我没有找到任何对此行为的引用 我有什么办法可以阻止这种缓冲吗?或者你可以参考一些相关的文章吗?
这是服务类:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Single)]
public class TheService : ITheService
{
private readonly ITraceFacade trace = TraceFactory.Resolve();//for tracing
public ClientCodeWrapper clientCodeWrapper { get; set; }// a wrapper for libraries written by our client. it's instantiated and set in the OnStart method of the service host class
public void ProcessJob(long jobId)
{
using (this.trace.ActivityScope(string.Format(CultureInfo.InvariantCulture, "The Service.ProcessJob({0})", jobId)))
{
this.clientCodeWrapper.ProcessJob(jobId);
}
}
}
这是我的服务配置
<system.serviceModel>
<bindings>
<netMsmqBinding>
<binding name="MsmqBindingNonTransactionalNoSecurity" exactlyOnce="false">
<security mode="None"/>
</binding>
</netMsmqBinding>
</bindings>
<services>
<service name="TheService">
<host>
<baseAddresses>
<add baseAddress="http://localhost:8080/TheServiceIn" />
</baseAddresses>
</host>
<endpoint address="net.msmq://localhost/private/TheServiceIn"
binding="netMsmqBinding"
bindingConfiguration="MsmqBindingNonTransactionalNoSecurity"
contract="ITheService">
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
</system.serviceModel>
答案 0 :(得分:2)
你所看到的似乎只是我所期待的。确实,WCF可以读取队列的多个消息以进行处理。通常,这不是问题,并且对于事务队列,这肯定不是问题(因为每个单独的事务只会在消息处理完成后提交,否则事务将中止并且消息返回到队列)
基本上,您选择不通过禁用事务和使用非事务性队列来避免丢失消息来处理消息。基本上你告诉MSMQ和WCF,偶尔丢失消息是完全可以的。
考虑如果你的机器(或MSMQ服务)崩溃会发生什么:你不会失去一份工作;你会失去所有这些,因为邮件不会被保留。