【问题标题】:How to configure Amazon queue service consuming count如何配置亚马逊队列服务消费计数
【发布时间】:2019-04-23 13:43:21
【问题描述】:

我一直在编写一些群发邮件脚本。它的工作原理是这样的。
1. 从数据库中拉取必须接收电子邮件的用户。目前这个数量约为 11k。
2. 将他们的电子邮件地址放入亚马逊队列服务中。
3. 触发另一个从队列服务拉取的 Lambda 代码,有间隔。
4. 找到每个用户的相关产品,构建html模板(Amazon s3)进行邮寄。
5. 使用 Amazon SES 发送它们。

由于 Amazon SES 仅允许每秒最多 14 封电子邮件,因此我必须在拉取时配置消费计数。但它以某种方式消耗太多,SES 给了我错误。

当前代码sn-p:

module.exports.mail_puller = (event, context, callback) => {
  init_aws();
  const Consumer = require('sqs-consumer');
  const app = Consumer.create({
    queueUrl: process.env.QUEUE_URL,
    handleMessage: (msg, done) => {
      build_email(JSON.parse(msg.Body));
      done();
    },
    waitTimeSeconds: 20,
    size: 1,
    visibilityTimeout: 1,
    sqs: sqs
  });

  app.on('error', (err) => {
    if (err) console.log(err);
  });
  app.on('empty', (err) => {
    if (err) console.log(err);
    if (connection && connection.state !== 'disconnected') connection.end();
    app.stop();
    callback(null, response);
  });
  app.start();
};

function build_email(obj) {
  init_cheerio();
  const $t = cheerio.load(obj.tpl);

  find_chosen(obj.id).then(products => {
    for (let product of products) {
      $t('.products-container').prepend(build_product(obj.product_tpl, product));
    }
    send_email(obj.email, obj.subject, $t.html().toString(), obj.id);
  });
}

错误信息:

2018-11-21T01:51:11.039Z    daf6727a-ed2f-11e8-9330-c581beef6958    { Throttling: Maximum sending rate exceeded.
at Request.extractError (/var/task/node_modules/aws-sdk/lib/protocol/query.js:47:29)
at Request.callListeners (/var/task/node_modules/aws-sdk/lib/sequential_executor.js:105:20)
at Request.emit (/var/task/node_modules/aws-sdk/lib/sequential_executor.js:77:10)
at Request.emit (/var/task/node_modules/aws-sdk/lib/request.js:683:14)
at Request.transition (/var/task/node_modules/aws-sdk/lib/request.js:22:10)
at AcceptorStateMachine.runTo (/var/task/node_modules/aws-sdk/lib/state_machine.js:14:12)
at /var/task/node_modules/aws-sdk/lib/state_machine.js:26:10
at Request.<anonymous> (/var/task/node_modules/aws-sdk/lib/request.js:38:9)
at Request.<anonymous> (/var/task/node_modules/aws-sdk/lib/request.js:685:12)
at Request.callListeners (/var/task/node_modules/aws-sdk/lib/sequential_executor.js:115:18)
at Request.emit (/var/task/node_modules/aws-sdk/lib/sequential_executor.js:77:10)
at Request.emit (/var/task/node_modules/aws-sdk/lib/request.js:683:14)
at Request.transition (/var/task/node_modules/aws-sdk/lib/request.js:22:10)
at AcceptorStateMachine.runTo (/var/task/node_modules/aws-sdk/lib/state_machine.js:14:12)
at /var/task/node_modules/aws-sdk/lib/state_machine.js:26:10
at Request.<anonymous> (/var/task/node_modules/aws-sdk/lib/request.js:38:9)
message: 'Maximum sending rate exceeded.',
code: 'Throttling',
time: 2018-11-21T01:51:11.039Z,
requestId: 'ebcebbd1-ed2f-11e8-b6d5-130ef17efa56',
statusCode: 400,
retryable: true }

【问题讨论】:

  • 你不能限制你的 lambda 函数的最大并发数吗?
  • 当您说“触发另一个从队列服务拉取的 Lambda 代码,有间隔”时,该代码是只拉取并处理一条消息,还是继续循环处理多条消息?
  • 它应该拉多条消息,但每秒不超过 14 条,这是 SES 限制。它应该按照 Cron 计划运行,并且只要池中有消息就会拉取。您会看到 module.exports.mail_puller 它正在拉取代码,但并非有意为之。

标签: amazon-web-services npm aws-lambda amazon-sqs amazon-ses


【解决方案1】:

限制是正常事件,您应该通过在延迟一段时间后重新驱动限制请求来处理此异常 - AWS 提供了一个 retry policy 框架来执行此操作(该链接适用于 Java SDK,但所有 SDK 都存在类似的概念)。更多关于重试的阅读可用here

您也可以通过对自己的速率进行一些限制来帮助缓解这种情况 - 基本上是在您的 send_email 调用中添加一些人为延迟以减少 SES 限制。

尝试不同配置的重试策略和客户端速率限制,以确定哪些数字可以为您的用例提供最佳结果。

【讨论】:

    猜你喜欢
    • 2011-07-15
    • 2017-02-25
    • 2010-11-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-12
    • 1970-01-01
    相关资源
    最近更新 更多