我尝试验证使用异步Put()和Commit()使用下面的代码的速度。问题是它的速度比仅使用 asyncPut()或Commit()only 慢十倍,这是没有意义的。
我在这里错过了什么吗?
class AsyncProducerWithCommit
{
private MQQueueManager _queueManager;
private MQQueue _queue;
public void Run()
{
Produce();
}
void Produce()
{
Open(ConnectionMode.Write);
PutMessage(ConvertMessageToByte(message));
_queue.Close();
_queueManager.Disconnect();
}
void PutMessage(byte[] messageString)
{
MQMessage _message = new MQMessage();
_message.Write(messageString);
_message.Format = MQC.MQFMT_STRING;
_message.CharacterSet = 1208;// IbmUtf8Encoding;
_message.Persistence = MQC.MQPER_PERSISTENT;
var putMessageOptions = new MQPutMessageOptions();
putMessageOptions.Options = MQC.MQPMO_SYNCPOINT //unit of work
+ MQC.MQPMO_ASYNC_RESPONSE; //async
_queue.Put(_message, putMessageOptions); //send message asynchronously
_queueManager.Commit();
}
void Open(ConnectionMode connectionMode)
{
string _queueManagerName = _appSetting.MessagingServerSetting.QueueManagerName;
int openOptions = 0;
switch (connectionMode)
{
case ConnectionMode.Read:
openOptions = MQC.MQOO_INPUT_SHARED + MQC.MQOO_FAIL_IF_QUIESCING;
break;
case ConnectionMode.Write:
openOptions = MQC.MQOO_OUTPUT + MQC.MQOO_FAIL_IF_QUIESCING;
break;
}
var properties = new Hashtable
{
{MQC.TRANSPORT_PROPERTY, MQC.TRANSPORT_MQSERIES_MANAGED },
{MQC.CONNECT_OPTIONS_PROPERTY, MQC.MQCNO_RECONNECT },
{ MQC.HOST_NAME_PROPERTY, "192.168.1.10" },
{ MQC.PORT_PROPERTY, "1415"},
{ MQC.CHANNEL_PROPERTY, "LOCAL.DEF.SVRCONN" },
{MQC.USER_ID_PROPERTY, "user" },
{MQC.PASSWORD_PROPERTY, "pwd" }
};
_queueManager = new MQQueueManager(_queueManagerName, properties);
_queue = _queueManager.AccessQueue(QUEUE_NAME, openOptions);
}
public enum ConnectionMode
{
Read,
Write
}
}
Run Code Online (Sandbox Code Playgroud)
更新1
异步放置
putMessageOptions.Options = MQC.MQPMO_ASYNC_RESPONSE; //async
_queue.Put(_message, putMessageOptions); //send message asynchronously
Run Code Online (Sandbox Code Playgroud)
与提交一起放置
putMessageOptions.Options = MQC.MQPMO_SYNCPOINT; //unit of work
_queue.Put(_message, putMessageOptions);
_queueManager.Commit();
Run Code Online (Sandbox Code Playgroud)
QueueManager 版本:Redhat Linux 7+ 上的 8.0.0.5
MQ.NET:8.0.0.8
在 IBM MQ v8 知识中心页面“在客户端应用程序中使用异步放置”中指出:
通常,当应用程序使用 MQPUT 或 MQPUT1 将一条或多条消息放入队列时,应用程序必须等待队列管理器确认它已处理 MQI 请求。您可以通过选择异步放置消息来提高消息传递性能,特别是对于使用客户端绑定的应用程序以及将大量小消息放入队列的应用程序。当应用程序异步放置消息时,队列管理器不会返回每个调用的成功或失败,但您可以定期检查错误。
异步放置仅影响放置调用,该调用将立即返回,而不是等待队列管理器确认它已处理放置。
因此,如果您有以下内容,则预计它将是最快的,因为您永远不会等待消息写入磁盘。
_message.Persistence = MQC.MQPER_PERSISTENT;
putMessageOptions.Options = MQC.MQPMO_ASYNC_RESPONSE; //async
_queue.Put(_message, putMessageOptions); //send message asynchronously
Run Code Online (Sandbox Code Playgroud)
如果您有其中任何一个,提交将等待消息写入磁盘,因此速度会与磁盘写入一样慢。这很可能比上面的慢,但 3 秒与 30 秒似乎不合理。
_message.Persistence = MQC.MQPER_PERSISTENT;
putMessageOptions.Options = MQC.MQPMO_SYNCPOINT //unit of work
+ MQC.MQPMO_ASYNC_RESPONSE; //async
_queue.Put(_message, putMessageOptions); //send message asynchronously
_queueManager.Commit();
Run Code Online (Sandbox Code Playgroud)
或者
_message.Persistence = MQC.MQPER_PERSISTENT;
putMessageOptions.Options = MQC.MQPMO_SYNCPOINT; //unit of work
_queue.Put(_message, putMessageOptions);
_queueManager.Commit();
Run Code Online (Sandbox Code Playgroud)
如果使用 MQPMO_SYNCPOINT 和 MQPMO_ASYNC_RESPONSE 的调用为 30 秒,而仅使用 MQPMO_SYNCPOINT 的调用为 3 秒,那么我认为一定存在某种缺陷,我建议您与 IBM 建立 PMR,他们可能会要求您至少提供一个客户端 .NET 跟踪和可能的队列管理器跟踪来自同一时间。