AWS SQS长轮询如果收到消息会提前返回吗?

3
如果我使用SQS长轮询,并将“ WaitTimeSeconds”设置为10秒,“ MaxNumberOfMessages”设置为1,然后在约0.1秒后将单个消息传递到队列中,那么调用sqs.receiveMessage()会立即返回,还是不应该在“ WaitTimeSeconds”的10秒已经过去之前返回?
在我的测试中,调用sqs.receiveMessage()似乎直到“ WaitTimeSeconds”的整个持续时间已经过去才返回。
以下是代码:
// Load the AWS SDK for Node.js
var AWS = require("aws-sdk");

const fmReqQ = "https://sqs.ap-southeast-2.amazonaws.com/myactid/fmReqQ";
const fmRspQ = "https://sqs.ap-southeast-2.amazonaws.com/myactid/fmRspQ";

const SydneyRegion = "ap-southeast-2";

var credentials = new AWS.SharedIniFileCredentials({ profile: "myprofile" });
AWS.config.credentials = credentials;

// Set the region
AWS.config.update({ region: SydneyRegion });

// Create an SQS service object
var sqs = new AWS.SQS({ apiVersion: "2012-11-05" });

async function sendRequest() {
  var sendParams = {
    MessageBody: "Information of 12/11/2016.",
    QueueUrl: fmReqQ,
  };

  try {
    data = await sqs.sendMessage(sendParams).promise();
    console.log("Success, request MessageId: ", data.MessageId);
  } catch (err) {
    console.log("Error", err);
  }
}

async function doModelling() {
  console.time("modelling");
  await sendRequest();
  await receiveResponse();
  console.timeEnd("modelling");
}

async function receiveResponse() {
  var receiveParams = {
    AttributeNames: ["SentTimestamp"],
    MaxNumberOfMessages: 1,
    MessageAttributeNames: ["All"],
    QueueUrl: fmRspQ,
    WaitTimeSeconds: 1,
  };

  let data = null;
  try {
    data = await sqs.receiveMessage(receiveParams).promise();
    console.log("Success, response MessageId: ", data);
  } catch (err) {
    console.log("Error", err);
  }
}

doModelling();


当我设置“WaitTimeSeconds: 3”时,我得到输出:
Success, request MessageId:  e5079c2a-050f-4681-aa8c-77b05ac7da7f
Success, response MessageId:  {
  ResponseMetadata: { RequestId: '1b4d6a6b-eaa2-59ea-a2c3-3d9b6fadbb3f' }
}
modelling: 3.268s

当我设置 "WaitTimeSeconds: 10" 时,我会得到输出:
Success, request MessageId:  bbf0a429-b2f7-46f2-b9dd-38833b0c462a
Success, response MessageId:  {
  ResponseMetadata: { RequestId: '64bded2d-5398-5ca2-86f8-baddd6d4300a' }
}
modelling: 10.324s

注意观察经过的时间与WaitTimeSeconds相匹配。
阅读关于AWS SQS长轮询的内容可以得知,长轮询会“尽快返回可用的消息”。
我似乎没有看到消息“尽快可用”,而是注意到sqs.receiveMessage()调用总是花费WaitTimeSeconds设置的时间。
正如您在示例代码中所看到的,我已将MaxNumberOfMessage设置为1。
3个回答

2

使用长轮询ReceiveMessage()方法,只要队列中至少有一条消息,就会立即返回。

虽然我不是Node专家,但以下是我的测试方法:

  • 创建一个Amazon SQS队列
  • 在一个窗口中运行以下命令:
aws sqs receive-message --queue-url https://sqs.ap-southeast-2.amazonaws.com/123/foo --visibility-timeout 1 --wait-time-seconds 10

然后,在另一个窗口中,我运行了:
aws sqs send-message --queue-url https://sqs.ap-southeast-2.amazonaws.com/123/foo --message-body bar
receive-message 命令在我使用 send-message 命令后迅速返回。
可能您的测试受到了消息被“接收”但被标记为“不可见”的影响,因为您的代码没有调用 DeleteMessage(),这些消息会对之后的测试产生影响。我通过明确指定 --visibility-timeout 1 来避免这种情况,使得消息会立即重新出现在队列中供下一个测试使用。
请求的消息数量 (--max-number-of-messages) 不会影响到此结果。只要至少有一条消息可用,它就会立即返回。

0
我指定的“WaitTimeSeconds”值确定了sqs.receiveMessage()调用的持续时间,因为我的队列上没有消息,所以sqs.receiveMessage()调用将等待“WaitTimeSeconds”指定的持续时间。

0

我将“WaitTimeSeconds”设置为0,现在似乎得到了我想要的行为:

Success, request MessageId:  9f286e22-1a08-4532-88ba-06c88be3dbc3
Success, response MessageId:  {
  ResponseMetadata: { RequestId: '5c264e27-0788-5772-a990-19d78c8b2565' }
}
modelling: 307.884ms

1
通过将“WaitTimeSeconds”设置为0,sqs.receiveMessage()调用在检查队列后立即返回,无论是否找到/返回任何消息。 - MattG
2
请注意,WaitTimeSeconds = 0 启用了短轮询,这不会检查所有的 SQS 服务器,因此有时您可能会收到错误的空消息。 - Maciej Pszczolinski

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接