如何编写WCF服务实现自动从MSMQ队列抓取消息
基于WCF + MSMQ实现持续监听队列的实现方案
1. 服务契约与数据契约的职责划分
首先明确:必须单独定义服务操作契约,不能将处理逻辑放到DataContract类中。二者职责完全分离:
- DataContract(你已经定义的传输对象类):仅负责描述队列中消息的序列化/反序列化结构,不承载任何业务逻辑
- ServiceContract:用于定义WCF服务对外暴露的操作,也就是消息到达时触发的处理入口
2. 核心代码编写
2.1 定义服务契约
你只需要定义一个单向操作契约,参数直接用你已经实现的DataContract类型即可,无需手动处理MSMQ原生消息对象,WCF会自动完成消息的接收、反序列化、事务管控:
[ServiceContract] public interface IQueueProcessingService { // 单向操作,队列消息到达时自动触发 [OperationContract(IsOneWay = true)] void ProcessMessage(FolderScanResultContract message); }
2.2 实现服务逻辑
把你原来手动抓取后的业务逻辑(入库等)挪到服务实现类中,WCF可以原生支持MSMQ事务,无需你手动创建和提交/回滚事务:
// 配置事务行为,消息处理成功自动提交事务,异常则自动回滚,消息放回队列 [ServiceBehavior(TransactionIsolationLevel = IsolationLevel.ReadCommitted, TransactionTimeout = "00:00:30")] public class QueueProcessingService : IQueueProcessingService { [OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)] public void ProcessMessage(FolderScanResultContract message) { // 这里直接拿到反序列化完成的对象,写你的入库逻辑即可 // 无需再手动处理队列连接、消息接收、事务管控 SaveToDatabase(message); } }
3. 配置文件配置
你需要在服务的配置文件(App.config/Web.config)中添加如下配置,绑定到你已有的队列地址:
<system.serviceModel> <bindings> <netMsmqBinding> <binding name="MsmqBindingConfig" exactlyOnce="true" durable="true"> <security mode="None" /> <!-- 根据你的队列权限调整安全配置 --> </binding> </netMsmqBinding> </bindings> <services> <service name="你的命名空间.QueueProcessingService"> <endpoint address="net.msmq://localhost/private/你的队列名称" binding="netMsmqBinding" bindingConfiguration="MsmqBindingConfig" contract="你的命名空间.IQueueProcessingService" /> </service> </services> </system.serviceModel>
注意:队列地址要转换为WCF要求的net.msmq://前缀格式,如果你用的是公有队列去掉路径中的private段即可。
4. 额外需要实现的内容
你还需要实现WCF服务的宿主,用来持续运行服务:
- 如果是Windows服务部署:在Windows服务的OnStart方法中启动ServiceHost
- 如果是IIS部署:需要开启WCF非HTTP激活功能,且队列应用池要配置为始终运行
启动宿主的示例代码:
private ServiceHost _host; protected override void OnStart(string[] args) { _host = new ServiceHost(typeof(QueueProcessingService)); _host.Open(); } protected override void OnStop() { if(_host != null && _host.State == CommunicationState.Opened) { _host.Close(); } }
常见注意点
- 确保运行服务的账号有队列的读取、删除权限
- 如果消息要保证不丢失,配置
durable="true",exactlyOnce="true"要求MSMQ必须是事务性队列 - 你原来手动写的MessageQueue相关逻辑全部可以删掉,WCF会自动完成连接维护、消息监听、反序列化、事务处理的所有操作
内容的提问来源于stack exchange,提问作者splindo
相关产品推荐
相关产品推荐

