MSMQ WCF Throttling

断了今生、忘了曾经 提交于 2019-12-23 14:56:26

问题


I have a windows service that reads my message queue through WCF. I want the service to process one message before another message (intensive memory actions per msg). I set the throttling configuration to 1, but it does not seem to do anything. If i have 6 messages in my queue, it takes 4 right after the start.

Am i missing something?

My 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>

My servicehost creation :

  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();
        }
    }

Class with contract :

  [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:


Your service as configured in the question should only process message at a time. Although you are not using the ServiceBehavior attribute for the service implementation class, the default value for the ConcurrencyMode is Single not Multiple (which could cause the behavior you are seeing). The default value of InstanceContextMode is Per Session but the maxConcurrentInstances and maxConcurrentSessions values force support for a single session at a time.

The only other option that I see is to force the ServiceHost to use only one service instance by using a different constructor. Here is the code:

// ... snipped ...

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


// ... snipped ...


来源:https://stackoverflow.com/questions/6112754/msmq-wcf-throttling

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!