Дросселирование WCM MSMQ - PullRequest
4 голосов
/ 24 мая 2011

У меня есть служба Windows, которая читает мою очередь сообщений через WCF.Я хочу, чтобы служба обрабатывала одно сообщение перед другим (интенсивные действия с памятью на сообщение).Я установил настройку регулирования на 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>

Мой сервис-хостсоздание:

  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 Ответ

3 голосов
/ 25 мая 2011

Ваша служба, настроенная в вопросе, должна обрабатывать только сообщения одновременно. Хотя вы не используете атрибут 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 ...
...