Как можно безопасно использовать 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;
}