Amazon web services 使用AWS SQS的最有效方式(与Golang一起)

Amazon web services 使用AWS SQS的最有效方式(与Golang一起),amazon-web-services,go,gzip,amazon-sqs,Amazon Web Services,Go,Gzip,Amazon Sqs,使用AWS SQS(简单队列服务)时,您需要为向服务发出的每个请求(推送、拉送等)付费。您可以发送到队列的每条消息的最大容量为256kb 为了省钱,我想先缓冲发送到Go应用程序的消息,然后再将它们发送到SQS,直到我有足够的数据来有效地使用256kb的限制 因为我的Go应用程序是一个Web服务器,所以我当前的想法是使用字符串互斥体并附加消息,只要超过256kb的限制,然后发出SQS推送事件。为了节省更多空间,我可以在将每条消息附加到字符串互斥体之前对其进行gzip处理 我想知道是否有某种gzip

使用AWS SQS(简单队列服务)时,您需要为向服务发出的每个请求(推送、拉送等)付费。您可以发送到队列的每条消息的最大容量为256kb

为了省钱,我想先缓冲发送到Go应用程序的消息,然后再将它们发送到SQS,直到我有足够的数据来有效地使用256kb的限制

因为我的Go应用程序是一个Web服务器,所以我当前的想法是使用字符串互斥体并附加消息,只要超过256kb的限制,然后发出SQS推送事件。为了节省更多空间,我可以在将每条消息附加到字符串互斥体之前对其进行gzip处理

我想知道是否有某种gzip流可以用于此目的。我的假设是,将所有连接的消息压缩在一起将导致更小的大小,而不是在将消息附加到字符串互斥体之前压缩每条消息。一种方法是在每次追加后gzip字符串互斥体,以验证其大小。但这可能非常缓慢


有更好的办法吗?还是有更好的渠道参与方式?我必须承认,我还是个新手。

我会采取以下方法

  • 使用通道接受go例程的传入“内部”消息
  • 在该go例程中,将消息保持为“原始”格式,因此10条消息就是10个原始未压缩项
  • 每次新的原始项到达时,将所有原始消息压缩为一个。如果新消息的大小>256k,则压缩除最后一条消息之外的消息并推送到SQS

这在计算上很昂贵。每个消息都会对所有挂起的消息进行完全压缩。但是,它对于SQS的使用是有效的

我将采用以下方法

  • 使用通道接受go例程的传入“内部”消息
  • 在该go例程中,将消息保持为“原始”格式,因此10条消息就是10个原始未压缩项
  • 每次新的原始项到达时,将所有原始消息压缩为一个。如果新消息的大小>256k,则压缩除最后一条消息之外的消息并推送到SQS

这在计算上很昂贵。每个消息都会对所有挂起的消息进行完全压缩。但是,使用SQS是有效的

您可以猜测gzip消息的大小,并计算是否已达到最大大小阈值。跟踪消息大小计数器,对于每一条新消息,计数器按预期的压缩大小递增。仅当计数器超过256kb时,才执行实际压缩并发送到SQS。因此,您可以避免每次收到新消息时都进行压缩。
对于这样的用例,对一组示例消息运行一些测试应该给出预期的大致压缩百分比。

您可以猜测gzip消息的大小,并计算是否达到最大大小阈值。跟踪消息大小计数器,对于每一条新消息,计数器按预期的压缩大小递增。仅当计数器超过256kb时,才执行实际压缩并发送到SQS。因此,您可以避免每次收到新消息时都进行压缩。
对于这样的用例,对消息样本集运行一些测试应该给出预期的大致压缩百分比。

在关注压缩之前,请消除双方都知道的冗余数据。这就是像、、等编码所做的

假设所有消息都是这样的结构:

{"bar":"whatever","qux",123}{"bar":"hello world","qux",0}{"bar":"answer to life, the universe, and everything","qux",42}{"bar":"nice","qux",69}
"whatever"123"hello world"0"answer to life, the universe, and everything"42"nice"69
类型Foo struct{
棒串
qux int
}
您正在考虑将其编码为JSON。那么你能做的最有效的事情就是:

{"bar":"whatever","qux",123}
如果您只想将所有这些附加到内存中,您可能会得到如下结果:

{"bar":"whatever","qux",123}{"bar":"hello world","qux",0}{"bar":"answer to life, the universe, and everything","qux",42}{"bar":"nice","qux",69}
"whatever"123"hello world"0"answer to life, the universe, and everything"42"nice"69
一个真正好的压缩算法可能会查看数百条这样的消息,并识别
{“bar”:“
”、“qux”、
的重复性

但每次压缩都必须从数据中找出原因

如果接收代码已经知道每条消息的“schema”(数据的
{“bar”:some_string,“qux”:some_int}
“shape”),那么您可以像这样序列化消息:

{"bar":"whatever","qux",123}{"bar":"hello world","qux",0}{"bar":"answer to life, the universe, and everything","qux",42}{"bar":"nice","qux",69}
"whatever"123"hello world"0"answer to life, the universe, and everything"42"nice"69
请注意,在这个例子中,你不能只从数据的中间开始,明确地找到你的位置。如果你有一组消息,比如“代码> { bar”:“2 } <代码>,<代码> {“bar”:“2”,“Qux”:“3 } <代码>,<代码> {“bar”:“3”,“Qux”:“4 } <代码>,然后编码将产生:“代码>”1“2”2“3”3。4 ,你不能只从中间开始,如果你正在看一个数字或一个字符串,你必须确定。你必须从结尾计数。这是否重要取决于你的用例。

您可以提出其他更明确的简单方案,或者使用于编写或读取消息的代码更容易或更简单,比如使用字段分隔符或消息分隔符,在对其他数据的编码中转义(就像在引用的JSON字符串中转义
\
”)

如果你不能让接收者知道或硬编码预期的消息模式——如果你需要像JSON之类的完全灵活性,那么你总是会被编排成一个类似于<代码> MAP[String ]接口{} < /代码>或其他什么的东西,那么你应该考虑使用类似的东西。

当然,您不能直接使用msgpack、protobuf、AVRO或BSON-它们需要一种允许任意字节的介质,如
0x0
。根据以下内容:

问:我可以在邮件中包含什么样的数据

Amazon SQS消息最多可包含256 KB的文本数据,包括XML、JSON和无格式文本。可接受以下Unicode字符:

#x9 | xA | xD |[| x20至#xD7FF]|[#xE000至#xffd]|[#x10000至#x10FFFF]

因此,如果您想为您的确切用例实现最大的空间效率,您必须编写