1

我有一个 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);
}
4

1 回答 1

0

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

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 控制,不可配置。(见这里

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

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

这有意义吗?

更新 4

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

于 2012-07-24T09:05:18.750 回答