繁体   English   中英

从 lambda 向 sns 主题发布消息

[英]publish a message to a sns topic from lambda

我有一个 lambda 函数,它通过 AWS lambda 函数处理 POST 请求。 它处理 post 请求的主体并进行查询并返回响应。

我的 LAMBDA 函数

const { Pool, Client } = require("pg");
const userName = 'blah';
const hostEndPoint = 'blah';
const databaseType = 'blahblah';
const pwd = 'pass pass';
const portNumber = 5432;
var AWS = require('aws-sdk');

const pool = new Pool({
  user: userName,
  host: hostEndPoint,
  database: databaseType,
  password: pwd,
  port: portNumber
});


exports.handler = async (event) => {
  let body = JSON.parse(event.body);
  let name = body.name;
  let money = body.money;
  let todayDate = new Date();
  var status = 0;
  let text = 'INSERT INTO employee(name, date, salary) VALUES($1, $2, $3) RETURNING *';
  let values = [name, todayDate, money];
  var message = '';
  var status = 0;

  try {
    const res = await pool.query(text, values)
    message += 'successful'
    status = 200;
  } catch (err) {
    message += 'unsuccessful'
    if (err.code === '23505') {
      status = 406;
    }
  }

  var params = {
    Message: 'Hello From Lambda', /* required */
    TopicArn: 'arn:aws:sns:us-east-1:blahblahblah'
  };

  // Create promise and SNS service object
  var publishTextPromise = new AWS.SNS({ apiVersion: '2010-03-31' }).publish(params).promise();

  publishTextPromise.then(
    function (data) {
      console.log(`Message ${params.Message} send sent to the topic ${params.TopicArn}`);
      console.log("MessageID is " + data.MessageId);
    }).catch(
      function (err) {
        console.error(err, err.stack);
      });



  const response = {
    statusCode: status,
    body: JSON.stringify(message),
    headers: {
      "Access-Control-Allow-Origtin": '*'
    }
  };
  return response;
};

我的Lambda 资源策略如下所示

{
  "Version": "2012-10-17",
  "Id": "default",
  "Statement": [
    {
      "Sid": "blah-blah-blah-blah",
      "Effect": "Allow",
      "Principal": {
        "Service": "apigateway.amazonaws.com"
      },
      "Action": "lambda:InvokeFunction",
      "Resource": "arn:aws:lambda:us-east-1:blah-blah-blah-blah-blah",
      "Condition": {
        "ArnLike": {
          "AWS:SourceArn": "arn:aws:execute-api:us-east-1:blahblahblahblha:blah/*/POST/"
        }
      }
    }
  ]
}

我还创建了一个 SNS 主题。 如果我的状态是 200,我想向 SNS 主题发布一条消息。所以在我返回响应之前。 我想做这样的事情。

if (status === 200){
  pubish some message to my sns topic
}

我对 aws 很陌生,希望得到一些关于如何发布消息的指导。 我觉得我很接近。 我确实遇到过这个话题,但它让我感到困惑,因为我正在 lambda 函数中编辑代码,所以为什么我需要 aws-sdk 并且他们也没有谈论更改权限。

尝试以下建议答案后更新了代码

我假设你的架构看起来像这样:

API 网关接受请求并调用您向我们展示的 lambda 函数。 该 Lambda 函数连接到数据库并插入一条记录。 您现在希望此 Lambda 函数也发布到 SNS 主题。

要实现这一点,您需要做两件事:

  1. 授予对 SNS 主题的 Lambda 函数权限
  2. 编写代码向主题发布消息

应首先执行第 1 步,为此您需要编辑您的函数正在使用的 IAM 角色。 IAM 角色指定允许此 lambda 函数调用哪些 AWS 服务。 您向我们展示的 Lambda 资源策略授予 API 网关调用/调用您的 Lambda 函数的权限 - 这对函数可以做什么没有影响。

如果这只是为了测试,您可以在 Identity and Access Management 中找到该函数的 IAM 角色并附加AmazonSNSFullAccess策略 -不要对任何类型的生产环境执行此操作,这会授予比必要更多的权限(在生产中,您d 添加允许操作sns:Publish only on your topic 的自定义策略)。

现在您的函数有权向您的主题发布消息。

第 2 步意味着您需要编辑代码。 您链接文档中所述,导入 AWS 开发工具包是必要的,因为您希望您的代码与 AWS 服务交互——为此您需要开发工具包。 除了设置区域外,该文档中的其他步骤似乎合理,如果您的主题与 lambda 函数位于同一 AWS 区域,则不需要这样做。

一些额外的意见/建议:

  • 您的 CORS-Header Access-Control-Allow-Origtin - 应该是 Origin。 您也可以在 API 网关上设置它,这样您的函数就不必处理它。
  • 我建议您从 AWS Secrets Manager 或 Systems Manager Parameter Store 之类的东西中获取数据库凭证,而不是将它们存储在代码中
  • 通过在处理程序之外设置连接池,您可以使您的代码重新使用现有的 DB-Connections,做得好!

可以看到, return response; publish未完成其任务时,行将立即运行 - 将消息发布到 SNS。 因为publishpublishTextPromise.thenreturn只是同步代码,所以只需一滴答(~0,00..1 秒)即可完成。 当处理函数调用return ,该函数将完成,这意味着所有正在执行的任务都将被取消(包括publish过程,该过程需要太多时间(~ < 1 秒和 > 一滴答完成)。

您将async/await语法与 promise 语法(.then .catch)混合使用,然后进程将无法按您的想法(或想要)工作,如果可以,我建议您只使用async/await语法。

使用您的代码,我来宾publish任务不会影响响应,它只是尝试将消息发布到 SNS。 我的建议,改变

  publishTextPromise.then(
    function (data) {
      console.log(`Message ${params.Message} send sent to the topic ${params.TopicArn}`);
      console.log("MessageID is " + data.MessageId);
    }).catch(
      function (err) {
        console.error(err, err.stack);
      });

  await publishTextPromise // wait until the task done
    .then((data) => {
      console.log(`Message ${params.Message} send sent to the topic ${params.TopicArn}`);
      console.log("MessageID is " + data.MessageId);
    })
    .catch((err) => {
      console.error(err, err.stack);
    });

添加了await关键字,我更喜欢箭头函数语法

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM