簡體   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