我希望提高我正在针对ActiveMQ编写的高吞吐量生产者的性能,并根据this useAsyncSend将:
强制使用Async Sends,这可以大大提升性能; 但意味着send()方法将立即返回 邮件已发送或未发送,可能导致邮件丢失。
但是我看不出它对我的简单测试用例有任何影响。
使用这个非常基本的应用程序:
const string QueueName = "....";
const string Uri = "....";
static readonly Stopwatch TotalRuntime = new Stopwatch();
static void Main(string[] args)
{
TotalRuntime.Start();
SendMessage();
Console.ReadLine();
}
static void SendMessage()
{
var session = CreateSession();
var destination = session.GetQueue(QueueName);
var producer = session.CreateProducer(destination);
Console.WriteLine("Ready to send 700 messages");
Console.ReadLine();
var body = new byte[600*1024];
Parallel.For(0, 700, i => SendMessage(producer, i, body, session));
}
static void SendMessage(IMessageProducer producer, int i, byte[] body, ISession session)
{
var message = session.CreateBytesMessage(body);
var sw = new Stopwatch();
sw.Start();
producer.Send(message);
sw.Stop();
Console.WriteLine("Running for {0}ms: Sent message {1} blocked for {2}ms",
TotalRuntime.ElapsedMilliseconds,
i,
sw.ElapsedMilliseconds);
}
static ISession CreateSession()
{
var connectionFactory = new ConnectionFactory(Uri)
{
AsyncSend = true,
CopyMessageOnSend = false
};
var connection = connectionFactory.CreateConnection();
connection.Start();
var session = connection.CreateSession(AcknowledgementMode.AutoAcknowledge);
return session;
}
我得到以下输出:
Ready to send 700 messages
Running for 2430ms: Sent message 696 blocked for 12ms
Running for 4275ms: Sent message 348 blocked for 1858ms
Running for 5106ms: Sent message 609 blocked for 2689ms
Running for 5924ms: Sent message 1 blocked for 2535ms
Running for 6749ms: Sent message 88 blocked for 1860ms
Running for 7537ms: Sent message 610 blocked for 2429ms
Running for 8340ms: Sent message 175 blocked for 2451ms
Running for 9163ms: Sent message 89 blocked for 2413ms
.....
这表明每条消息大约需要800毫秒才能发送,而session.Send()
的呼叫大约需要两秒半。即使文档说明
“send()方法将立即返回”
如果我将并行更改为正常for循环或将AsyncSend = true
更改为AlwaysSyncSend = true
,这些数字基本相同,所以我不相信异步开关正在工作...
任何人都可以看到我在这里失踪的发送异步吗?
经过进一步测试:
根据ANTS性能分析器,绝大多数运行时都在等待同步。似乎问题是各种传输类通过监视器内部阻塞。特别是我似乎挂了MutexTransport的OneWay方法,它只允许一个线程一次访问它。
看起来发送的调用将阻塞,直到上一条消息完成,这就解释了为什么我的输出显示第一条消息被阻止了12毫秒,而下一条消息则持续了1858毫秒。我可以通过实现每个消息连接模式来实现多个传输,这样可以改善问题并使消息发送并行工作,但是大大增加了发送单个消息的时间,并且耗尽了很多资源而看起来不像正确的解决方案。
我已经用1.5.6重新测试了所有这些并且没有看到任何差异。
答案 0 :(得分:0)
一如既往,最好的办法是更新到最新版本(撰写本文时为1.5.6)。如果代理启用了生成器流控制并且您已达到队列大小限制,则发送可以阻止,尽管使用异步发送,除非您使用producerWindowSize设置发送,否则不会发生这种情况。获得帮助的一个好方法是创建一个测试用例并通过Jira问题将其提交给NMS.ActiveMQ站点,以便我们可以使用您的测试代码进行调查。自1.5.1以来有很多修复,所以我建议尝试新版本,因为它可能已经不是问题了。