Как безопасно использовать. NET MQQueueManager в приложении WEB API? - PullRequest
0 голосов
/ 06 февраля 2020

Как можно безопасно использовать MQQueueManager () в неявной многопоточной среде, такой как WebAPI? Является ли синглтон (stati c) для срока службы хорошим подходом? Или подход «инициализация на запрос» подходит?

Типичные шаги, которые я использовал:

  • Инициализация администратора очередей
  • Инициализация очередей
  • Поместить что-то в очередь
  • Закрыть очередь
  • ПОЛУЧИТЬ что-нибудь из очереди ответов
  • Закрыть очередь
  • Отключить администратор очередей.

Обратите внимание, что это должно быть сделано для КАЖДОГО запроса веб-API и приводит к увеличению времени ответа. (Большую часть этого времени занимает инициализация MQQueueManager). Кроме того, после инициализации на каждом шаге, для исключения, мы должны убедиться, что администратор очередей отключен, в противном случае клиентские соединения складываются.

Следующий очевидный выбор - использовать один экземпляр c stati * MQQueueManager для всего срока службы сервиса. Благодаря единственному случаю улучшение времени отклика достигает 500%. Однако проблема здесь в том, что MQQueueManager имеет тенденцию блокироваться через некоторое время, и я начинаю получать ошибки (код ошибки 2009, 2059 и c.).

ОБНОВЛЕНИЕ 1 Когда у нас есть версия класса MQQueueManager stati c, самый первый сбой после периода бездействия - Код завершения 2, Причина 2009 , последующие вызовы приводят к Код завершения 2 Причина 2018 . Обратите внимание, что если мы перезапустим пул приложений, нормальная функциональность возобновится. Мы можем помещать и получать сообщения из очередей даже в условиях большой нагрузки.

ОБНОВЛЕНИЕ 2 (псевдокод для иллюстрации моих шагов)

public MQHelperClass
{

    static MQQueueManager mqmgr; // This is the actual MQeuemanager.
    static Hashtable connectionProperties;
    static MQQueue replyQueue;

    // Static constructor so that the MQQueueManager object
    // lasts the entirity of the app lifecycle once initialized
    static MQHelperClass
    {
        InitializeQueueManager();

    }

    static InitializeQueueManager()
    {
        // Set up connection properties
        connectionProperties = new Hashtable();

        connectionProperties.Add(MQC.TRANSPORT_PROPERTY, MQC.TRANSPORT_MQSERIES_MANAGED);
        connectionProperties.Add(MQC.USER_ID_PROPERTY, "XXXXXX"); 
        connectionProperties.Add(MQC.PASSWORD_PROPERTY, "XXXXXX");
        :
        :
        :
        mqQueManager = new MQQueueManager();

    }

    public void PutMessage(string)
    {
       //Put someting and then close;
    }

    public string GetMessage(string )
    {
    try
            {                
                MQQueue queue = AccessQueue(replyQueue,
                                    new int[] { MQC.MQOO_INPUT_AS_Q_DEF, MQC.MQOO_FAIL_IF_QUIESCING });


                MQMessage replyMessage = new MQMessage();
                MQGetMessageOptions getMessageOptions = new MQGetMessageOptions()
                {
                    //MatchOptions = MQC.MQMO_MATCH_CORREL_ID,
                    Options = MQC.MQGMO_WAIT,
                    WaitInterval = 30000
                };

                replyMessage.CorrelationId = messageId;
                queue.Get(replyMessage, getMessageOptions);
                string receivedMessage = replyMessage.ReadString(replyMessage.MessageLength);
                log.Debug($"Message received : {receivedMessage}");               
                queue.Close();                
                return receivedMessage;                    

            }
    }
}

public class MyApiController : ApiController 
{

    MQHelperClass helperClass = new MQHelperClass();

    helperClass.Put();
    helperClass.Get();
    :
    :
    :


}

        private static MQQueue AccessQueue(string queueName, params int[] 
        queueOpenOptions)
        {
            mqQueue = mqQMgr.AccessQueue(queueName, queueOpenOptions.Sum());
            return mqQueue;
        }

...