SQS( 简单消息队列 )是Amazon Web Services的消息队列即服务产品。 它仅支持少量的消息传递操作,远没有AMQP这样的复杂性,但是由于易于理解的界面和即服务的性质,它在许多情况下都非常有用。
但是SQS有多快? 它如何缩放? 它仅适用于小批量消息传递,还是可以用于高负载应用程序?
如果您知道SQS的工作原理,并且想跳过测试方法的详细信息,则可以直接跳至测试结果 。
SQS语义
SQS公开基于HTTP的接口。 要访问它,您需要AWS凭证对请求进行签名。 但这通常是由客户端库完成的(存在用于大多数流行语言的库;我们将使用官方Java SDK )。
与消息相关的基本操作是:
- 发送最大为256 KB且编码为字符串的消息。 最多可以发送10条消息(但总大小上限为256 KB)。
- 收到一条消息。 如果队列中可用,则最多可以批量接收10条消息
- 长时间轮询消息。 如果最初没有可用的消息,则请求最多等待20秒
- 删除留言
还有其他一些操作,涉及安全性,延迟消息传递以及更改消息的可见性超时,但是我们不会在测试中使用它们。
SQS提供至少一次的交货保证。 如果收到一条消息,则将其阻塞一段称为“可见性超时”的时间。 除非在该期限内删除该邮件,否则它将再次可以传递。 因此,如果处理消息的节点崩溃,它将再次被传递。 但是,我们也面临两次处理消息的风险(例如,删除消息时网络连接死了,或者SQS服务器死了),这必须在应用程序侧进行管理。
SQS是复制的消息队列,因此可以确保一旦发送了消息,它便是安全的并且可以传递; 从网站引用:
Amazon SQS在Amazon高可用性数据中心内运行,因此队列将在应用程序需要时可用。 为了防止消息丢失或变得不可用,所有消息都冗余存储在多个服务器和数据中心之间。
测试方法
为了测试SQS的速度及其扩展速度,我们将运行各种数量的节点,每个节点运行各种数量的线程,以发送或接收简单的100字节消息。
每个发送节点都根据要发送的消息数进行参数设置,并尝试尽快执行此操作。 邮件是批量发送的,批量大小在1到10之间随机选择。消息发送是同步的,也就是说,我们要确保在发送下一个批量之前请求已成功完成。 最后,节点报告每秒发送的平均消息数。
接收节点最多接收10条消息。使用AmazonSQSBufferedAsyncClient
,它可以预提取消息以加快传递速度。 接收后,每条消息均被异步删除。 一旦节点在一分钟内未收到任何消息,就假定测试已完成,并报告每秒接收到的平均消息数。
每个测试每个线程发送1万到5万条消息。 因此测试相对较短,为2-5分钟。 还有更长的测试,持续约15分钟。
完整(但仍然很短)的代码在这里: Sender
, Receiver
, SqsMq
。 一组节点运行MqSender
代码,另一组节点运行MqReceiver
代码。
发送和接收节点是eu-west区域中的m3.large EC2服务器,因此具有以下参数:
- 2芯
- 英特尔至强E5-2670 v2
- 7.5 GB内存
当然,队列也在欧洲西部地区创建。
最少的设置
最小设置包括1个发送节点和1个接收节点,它们都运行一个线程。 结果以消息/秒为单位:
平均 | 分 | 最高 | |
---|---|---|---|
发件人 | 429 | 365 | 466 |
接收者 | 427 | 363 | 463 |
缩放线程
当我们添加更多线程(仍然使用一个发送者和一个接收者节点)时,这些结果如何缩放? 测试使用1、5、25、50和75个线程进行。 这些数字是平均味精/秒的吞吐量。
线程数: | 1个 | 5 | 25 | 50 | 75 |
---|---|---|---|---|---|
每个线程的发送者 | 429,33 | 407,35 | 354,15 | 289,88 | 193,71 |
发件人总数 | 429,33 | 2 036,76 | 8853,75 | 14 493,83 | 14528,25 |
每个线程的接收者 | 427,86 | 381,55 | 166,38 | 83,92 | 47,46 |
接收者总数 | 427,86 | 1 907,76 | 4 159,50 | 4 196,17 | 3 559,50 |
如您所见,在发送方,随着线程数量的增加,我们获得了接近线性的可扩展性,在50个线程中(在单个节点上!)发送峰值为14k msgs /秒。 再往前走似乎没有什么不同。
接收方较慢,这是可以预期的,因为接收单个消息实际上是两个操作:接收+删除,而发送是单个操作。 可伸缩性较差,但仍然可以得到每秒4k msgs的接收速度。
扩展节点
扩展的另一种(更有希望的)扩展方法是添加节点,这很容易,因为我们位于“云中”。 运行多个节点(每个节点运行一个线程)时的测试结果为:
节点数: | 1个 | 2 | 4 | 8 |
---|---|---|---|---|
每个节点的发送者 | 429,33 | 370,36 | 350,30 | 337,84 |
发件人总数 | 429,33 | 740,71 | 1 401,19 | 2702,75 |
每个节点的接收者 | 427,86 | 360,60 | 329,54 | 306,40 |
接收者总数 | 427,86 | 721,19 | 1 318,15 | 2 451,23 |
在这种情况下,在发送和接收方面,我们都获得了近乎线性的可伸缩性,通过8个节点,每秒可发送和接收2.5k消息。
扩展节点和线程
当然,下一步自然是扩展节点和线程! 在每个节点上使用25个线程时,结果如下:
节点数: | 1个 | 2 | 4 | 8 |
---|---|---|---|---|
每个节点和线程的发送者 | 354,15 | 338,52 | 305,03 | 317,33 |
发件人总数 | 8853,75 | 16 925,83 | 30 503,33 | 63 466,00 |
每个节点和线程的接收者 | 166,38 | 159,13 | 170,09 | 174,26 |
接收者总数 | 4 159,50 | 7 956,33 | 17 008,67 | 34851,33 |
同样,我们获得了出色的可伸缩性结果,每秒接收操作的数量约为发送操作数量的一半。 处理的每秒34k消息是一个非常不错的数字!
到极点
我设法获得的最高结果是:
- 使用50个线程和8个节点时发送的108k msgs /秒
- 使用25个线程和8个节点时收到35k msgs /秒
我还尝试使用200k消息/线程,8个节点和25个线程运行更长的“压力”测试,结果与较短的测试相同。
从技术上运行测试
为了运行测试,我构建了包含Sender
/ Receiver
二进制文件的Docker映像,推送到Docker的Hub,然后由Chef下载到节点上。 为了配置服务器,我使用了Amazon OpsWorks。 这使我能够快速启动并配置许多节点以进行测试(以上测试中最多16个)。 有关如何工作的详细信息,请参阅我的“使用Docker,Chef和Amazon OpsWorks进行集群范围的Java / Scala应用程序部署”博客 。
Sender
/ Receiver
守护程序监视(通过每秒检查上次修改日期)S3上的文件。 如果检测到修改,则下载文件-其中包含测试参数-并开始测试。
加起来
SQS具有良好的性能和非常好的可伸缩性。 我无法达到其可能性的顶峰-可能总共需要16个以上的节点。 但是,一旦您的要求达到每秒35,000条消息以上,您无论如何都需要定制解决方案。 更不用说SQS便宜了,但在这样的负载下它可能变得昂贵。
从上面的结果中,我认为很明显,SQS可以安全地用于大容量消息传递应用程序,并且可以按需扩展。 加上其可靠性保证,它非常适合执行各种异步处理的小型和大型应用程序。 特别是如果您的服务已经位于Amazon云中。
由于基准测试并非易事,因此欢迎对测试方法进行任何评论,以及如何改进测试代码的想法!
翻译自: https://www.javacodegeeks.com/2014/06/benchmarking-sqs.html