MSMQ WCF限制

时间:2011-05-24 15:18:06

标签: wcf msmq throttling

我有一个通过WCF读取我的消息队列的Windows服务。我希望服务在另一条消息之前处理一条消息(每个消息的密集内存操作)。我将限制配置设置为1,但似乎没有做任何事情。如果我的队列中有6条消息,则在开始后就会有4条消息。

我错过了什么吗?

我的web.config:

  <system.serviceModel>
<client>
  <endpoint
    address="net.tcp://spserv30:9999/services/SPInterface"
    binding="netTcpBinding" bindingConfiguration="tcpspbinding"
    contract="Itineris.OPM.WCFSP.ActionContracts.ISPActions" >
  </endpoint>
</client>
<services>
  <service name="Itineris.OPM.MSMQProcessorV2.MSMQProcessor" behaviorConfiguration="Throttled" >
    <endpoint address="msmq.formatname:DIRECT=OS:localhost\private$\documents" binding="msmqIntegrationBinding"
              bindingConfiguration="MSMQProcessorBinding" contract="Itineris.OPM.MSMQProcessorV2.IMSMQProcessor" />
  </service>
</services>
<bindings>
  <netTcpBinding>
    <binding name="tcpspbinding" transferMode="StreamedRequest" />
  </netTcpBinding>
  <msmqIntegrationBinding>
    <binding name="MSMQProcessorBinding" maxReceivedMessageSize="2147483647" 
             receiveRetryCount="0" retryCycleDelay="00:10:00" maxRetryCycles="0"
             receiveErrorHandling="Move">
      <security mode="None" />
    </binding>
  </msmqIntegrationBinding>


   </bindings>
 <behaviors>
      <serviceBehaviors>
        <behavior name="Throttled">
          <serviceThrottling 
            maxConcurrentCalls="1" 
            maxConcurrentSessions="1" 
            maxConcurrentInstances="1"
          />
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>

我的servicehost创建:

  protected override void OnStart(string[] args)
    {

            if (_serviceHost != null)
            {
                if (_serviceHost.State != CommunicationState.Faulted)
                    _serviceHost.Close();
                else
                    _serviceHost.Abort();
            }
            //create servicehost
            _serviceHost = new ServiceHost(typeof(MSMQProcessor));
            _serviceHost.Open();
            _serviceHost.Faulted += serviceHost_Faulted;

            // Already load configuration here so that service does not start if there is a configuration error.
            new DocumentGeneratorV2.LoadGeneratorConfigurator().Load();

            var startLog = new LogEntry {Message = "Itineris MSMQ Processor Service V2 has started"};
            startLog.Categories.Add(CategoryGeneral);
            startLog.Priority = PriorityNormal;

            Logger.Write(startLog);






    }

    private void serviceHost_Faulted(object sender, EventArgs e)
    {
        if (!_isClosing)
        {
            _serviceHost.Abort();
            _serviceHost = new ServiceHost(typeof(MSMQProcessor));
            _serviceHost.Faulted += serviceHost_Faulted;
            _serviceHost.Open();
        }
    }

合同类:

  [ServiceContract(Namespace = "http://Itineris.DocxGenerator.MSMQProcessor")]
[ServiceKnownType(typeof(string))]
public interface IMSMQProcessor

{
    [OperationContract(IsOneWay = true, Action = "*")]
    void GenerateWordDocument(MsmqMessage<string> message);
}

public class MSMQProcessor : IMSMQProcessor
{
    /// <summary>
    /// Method that processed the message and generates a word document
    /// </summary>
    /// <param name="message">message from MSMQ to be processed</param>
    [OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
    public void GenerateWordDocument(MsmqMessage<string> message)
    {
        DocumentGeneration documentGenerator = null;
        var state = new DocumentStatus();
        var docGenerator = new DocumentGenerator(new LoadGeneratorConfigurator().Load());


            var deserializer = new XmlSerializer(typeof(DocumentGeneration));

            documentGenerator = deserializer.Deserialize(new StringReader(message.Body)) as DocumentGeneration;
            if(documentGenerator == null)
                throw new Exception("Deserializing of the message has failed");

            docGenerator.MailQueue = appSettings["MAILQUEUE"];
            docGenerator.GenerateDocument(documentGenerator);


            var builder = new StringBuilder();
            builder.Append("The documents have been saved to the following locations: \r\n");

            }
            }

1 个答案:

答案 0 :(得分:3)

问题中配置的服务应该一次只处理消息。虽然您没有为服务实现类使用ServiceBehavior属性,但ConcurrencyMode的默认值是Single而不是Multiple(这可能会导致您看到的行为)。 InstanceContextMode的默认值是Per Session,但maxConcurrentInstances和maxConcurrentSessions值一次强制支持单个会话。

我看到的唯一其他选项是强制ServiceHost使用不同的构造函数仅使用一个服务实例。这是代码:

// ... snipped ...

//force single service instance to be used by servicehost
var singleton = new MSMQProcessor();
_serviceHost = new ServiceHost(singleton);
_serviceHost.Open();


// ... snipped ...