【问题标题】:WCF service inside an MVC-app that uses msmqIntegrationBinding does not receive messages from msmq使用 msmqIntegrationBinding 的 MVC 应用程序内的 WCF 服务不接收来自 msmq 的消息
【发布时间】:2012-07-22 13:10:03
【问题描述】:

我有一个 MVC 应用程序,它有一个控制器,该控制器的操作应该从队列 (msmq) 中的最新消息中公开数据。我在本地机器上添加了一个私人队列。我希望应用程序在添加消息时自动从队列接收消息。为此,我在已添加到应用程序的 WCF 服务上使用 msmqIntegrationBinding。然后,在合同中获取消息的方法我应该将消息保存在应用程序缓存中,以便在客户端请求最新数据时可以访问它。

我现在面临的挑战是,当我将消息添加到队列时,WCF 服务不会接收到它。我需要关于我可能做错的事情的指导或对我的方法的反馈。请帮忙。

以下是 WCF 服务的端点配置:

<bindings>
<msmqIntegrationBinding>
  <binding name="MsmqBinding">
    <security mode="None" />
  </binding>
</msmqIntegrationBinding>
</bindings>

<services>
  <service name="TestApp.Web.Service.QueueMessageReceiver">
    <endpoint address="msmq.formatname:DIRECT=OS:.\private$\testsmessagequeue"
                      binding="msmqIntegrationBinding"
                      bindingConfiguration="MsmqBinding"
                      contract="TestApp.Web.Service.IQueueMessageReceiver" />
  </service>
</services>

以下代码来自 QueueMessageReceiver.cs WCF 服务:

public class QueueMessageReceiver : IQueueMessageReceiver
{
    private static readonly XmlSerializer Serializer = new XmlSerializer(typeof(ScrewInfoModel));

    [OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
    public void PutScrewInfoMessage(System.ServiceModel.MsmqIntegration.MsmqMessage<System.Xml.XmlDocument> msg)
    {
        CacheScrewInfoModelFromScrewInfoXmlDoc(msg.Body);
    }

    private static void CacheScrewInfoModelFromScrewInfoXmlDoc(XmlNode screwInfoXmlDoc)
    {
        var reader = new StringReader(screwInfoXmlDoc.InnerXml);
        var screwInfoModel = (ScrewInfoModel)Serializer.Deserialize(reader);
        Common.Utils.CacheScrewInfo(screwInfoModel);
    }
}

这是 WCF 的接口:

[ServiceContract]
public interface IQueueMessageReceiver
{
    [OperationContract(IsOneWay = true, Action = "*")]
    void PutScrewInfoMessage(MsmqMessage<XmlDocument> msg);
}

【问题讨论】:

  • 邮件是否保留在队列中?
  • 是的,这就是为什么我认为它从未被阅读过。

标签: wcf msmq


【解决方案1】:

尝试将您的运营合同更改为

void PutScrewInfoMessage(MsmqMessage<string> msg);

WCF 堆栈可能难以反序列化为 XmlDocument

更新

要尝试的事情:

  1. 让您的队列“testsmessagequeue”具有正确的权限集。在这种情况下,运行托管您的控制器的应用程序池的服务帐户需要设置“接收消息”权限。

  2. 启用 MSMQ 日志记录(如果您使用的是 windows 2008 服务器或 windows 7 及更高版本),可以在事件查看器中的以下位置找到:应用程序和服务日志 -> Microsoft -> Windows -> MSMQ -> End2End。这将捕获 MSMQ 中发生的所有事情,包括任何错误。

  3. 尝试使队列具有事务性(如果还没有)。这将确保消息未传递时存在错误情况。

  4. 在您的服务端点上启用 WCF 跟踪,以查看在消息出队时发生的任何特定 WCF 错误。

更新 2

我认为问题在于队列权限。您的应用程序池在用户 ApplicationPoolIdentity 下运行(如果它在 .net 4.0 应用程序池下运行)。与此身份对应的用户称为DefaultAppPool。您需要授予此用户在队列上接收消息的权限。要选择此用户,请在“选择用户”对话框中搜索名为 IIS AppPool\DefaultAppPool 的本地帐户。

更新 3

让我感到震惊的是,IIS 不是队列侦听器的合适托管容器。原因是应用程序池在一段时间不活动后卸载。这由 IIS 控制,不可配置。 (见here

我认为您应该在 Windows 服务中创建一个新的托管容器(您可以使用控制台主机来增加它)来托管队列端点。 Windows 服务将在实际服务帐户下运行,因此授予权限将不那么复杂。

此服务可以直接写入缓存,或者如果这不可能,则应写入网站控制器可以刷新缓存的数据库。

这有意义吗?

更新 4

中毒消息意味着消息由于某些问题而无法出队。检查名为 Transactional Dead Letter Queue 的系统队列,看看您的消息是否在其中。

【讨论】:

  • 我将合同更改为您建议的内容并重新部署到我的本地 IIS 并在队列中添加了一条消息。我一直在排队。我想在 IIS 或应用程序池中做一些特定的配置吗?
  • 感谢您的回答。我已尝试将 QUEUE 上的权限设置为接收消息,但我仍然无法正常工作。我是否需要对应用程序池正在使用的身份设置相同的权限?应用程序池正在使用“ApplicationPoolIdentity”,我该如何设置权限?
  • 我将队列地址从“msmq.formatname:DIRECT=OS:.\private$\testsmessagequeue”更改为“msmq.formatname:DIRECT=OS:LEIA\private$\testsmessagequeue”(其中Leia 是我的机器名称)并且它有效。消息不会保留在队列中。我现在遇到的问题是消息对象未存储在应用程序缓存中。我现在尝试同时使用 XmlDocument 和字符串。有什么建议吗?
  • 是的,我做到了,根据日志,消息都被放入队列中并被读取。我实现了 log4net,WCF 每次收到消息时都应该记录一个条目,但我没有。奇怪的是,当我向队列中添加一条消息时,它会立即消失,我可以阅读有关它被放置在队列中并在 MSMQ\End2End-log 中读取的信息。
  • 在回答您之前的问题时,需要为运行 IIS 应用程序池的名为“ApplicationPoolIdentity”的帐户授予队列权限。你在使用事务队列吗?
猜你喜欢
  • 2010-12-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-27
  • 1970-01-01
  • 2012-11-05
  • 2011-12-29
  • 2015-03-22
相关资源
最近更新 更多