通过 Amazon SQS 从 PHP 向 NodeJS 发送压缩文本

Sending compressed text over Amazon SQS from PHP to NodeJS

我似乎无法通过 Amazon SQS 将压缩消息从 PHP 发送到 NodeJS。

在PHP这边我有:

$SQS->sendMessage(Array(
    'QueueUrl'    => $queueUrl,
    'MessageBody' => 'article',
    'MessageAttributes' => Array(
        'json' => Array(
            'BinaryValue' => bzcompress(json_encode(Array('type'=>'article','data'=>$vijest))),
            'DataType' => 'Binary'
        )
    )
));

注意 1:我也试过将压缩数据直接放在消息中,但是库给了我一些无效字节数据的错误

在节点端,我有:

body = decodeBzip(message.MessageAttributes.json.BinaryValue);

其中消息来自 sqs.receiveMessage() 调用并且该部分有效,因为它适用于原始(未压缩的消息)

我得到的是类型错误:格式不正确

我也试过使用:

PHP - NODE

gzcompress() - zlib.inflateraw()

gzdeflate() - zlib.inflate()

gzencode() - zlib.gunzip()

每一对都给了我相同错误的版本(本质上,输入数据是错误的)

考虑到所有这些,我开始怀疑消息传输中的某处存在错误

我做错了什么?

编辑 1:似乎错误出在传输中,因为 bin2hex() 在 php 和 .toString('hex') 在 Node return 完全不同的值。 PHP 中的 Amazon SQS API 似乎使用 base64 传输 BinaryAttribute,但 Node 无法对其进行解码。我设法通过关闭 amazon aws 配置文件中的自动转换然后在节点中手动解码 base64 来部分解码它,但它仍然无法解码它。

编辑 2:我设法通过在 php 端使用 base64_encode() 并将 base64 作为 messageBody 发送来完成同样的事情(不使用 MessageAttributes)。在节点端,我使用了 new Buffer(messageBody,'base64') 然后在其上使用了 decodeBzip。一切正常,但我仍然想知道为什么 MessageAttribute 不能正常工作。当前的 base64 增加了开销,我喜欢按预期使用这些服务,而不是变通。

gzcompress() 将被 zlib.Inflate() 解码。 gzdeflate() 将被 zlib.InflateRaw() 解码。 gzencode() 将被 zlib.Gunzip() 解码。所以在你列出的三个中,两个是错误的,但一个应该有效。

This 是所有 SQS 库在幕后所做的事情。你可以拿到SQS库的php源码,自己看看。二进制数据将 总是 进行 base64 编码(使用 MessageAttributes 或不使用时,无关紧要)作为满足 API 要求的一种方式具有形式 url 编码的消息。

我不知道你的 $vijest 里的数据有多长,但我敢打赌,经过压缩和 base64 编码后,它会比以前更大。

所以我对你的回答分为两部分(如果你真的很固执,再加上第三部分):

  • 在查看底层原始 API 时,绝对清楚不使用 MessageAttributes 不会增加 base64 的额外开销。相反,由于 SQS php 库强制执行的数据结构,使用 MessageAttributes 会增加一些额外的开销。因此,不使用 MessageAttributes 显然不是一种解决方法,如果您想自己压缩数据并使其以这种方式工作,您应该这样做。
  • 由于 http POST 请求的性质,在您的应用程序中压缩您的数据是一个非常糟糕的主意。 Base64 开销可能会抵消压缩优势,您最好发送纯文本。
  • 如果您完全不相信我或 API 规范或 HTTP 规范并想继续,那么我建议在 BinaryValue 参数中发送一个简单的短字符串 'teststring' 并进行比较你发送了什么和你得到了什么。这将使理解 SQS 库对 BinaryValue 参数所做的转换变得非常容易。