AWS Lambda - 使用 MySQL 的 Telegram Bot - 循环消息 \ 相同消息

Posted

技术标签:

【中文标题】AWS Lambda - 使用 MySQL 的 Telegram Bot - 循环消息 \\ 相同消息【英文标题】:AWS Lambda - Telegram Bot with MySQL - Loop Message \ Same MessageAWS Lambda - 使用 MySQL 的 Telegram Bot - 循环消息 \ 相同消息 【发布时间】:2020-07-29 03:39:06 【问题描述】:

我正在开发一个 AWS Lambda 函数来托管我的 Telegram Bot。

项目详情:

它正在使用 webhook(API 网关); Lambda 函数将接收 Telegram 消息并检查数据库; 我正在使用 mysql 来存储用户和一些详细信息。

简单的工作流程:

用户发送 Telegram 消息 -> Telegram Webhook -> API Gateway -> AWS Lambda -> MYSQL 查询 -> 回复 Telegram 用户

守则

索引.js

const bot = require('./Bot')
exports.handler = function(event, context, callback) 
    const tmp = JSON.parse(event.body)
    bot.handleUpdate(tmp)
    .then(() => 
        var response = "statusCode": 200, "body": "OK"
        //callback(null, response)
        //context.succeed(response)
    )

在 Bot.js 中,有一个 MYSQL 查询来检查用户是否在允许的日期和小时内发送消息。

问题:

如果我使用回调(null, response)

查询以正确的方式运行; 用户收到回复。

在这种情况下,我不断从 webhook 循环接收相同的消息。据我所见,响应不起作用

如果我使用 context.succeed(response)

查询未运行; 用户没有收到回复

在这种情况下,我只收到一次原始消息。

任何人都知道什么可以解决这个问题。我已经尝试使用上下文和回调,但是查询没有运行,用户也没有收到回复。

【问题讨论】:

【参考方案1】:

经过长时间检查所有日志并了解我的基础架构的场景后,我解决了这个问题。让我们首先以更好的方式了解情况:

场景的更多细节:

我检查了 API Gateway 和 Lambda 中可接受的最大超时值是:

Lambda:最多 15 分钟 API 网关: 最长 - 30 秒

了解这些值后,我开始查看我的 Lambda 函数日志:

原代码: 1分钟完成执行 改进的代码: 40 秒完成执行

如您所见,即使在改进了我的代码之后,它也没有在 API 网关超时之前完成。它开始了我面临的问题。

如果您查看 Telegram Webhook 信息:

要检查的网址: https://api.telegram.org/botYOUR TOKEN/getWebhookInfo

我一遍又一遍地在待处理状态中收到相同的消息。它导致收到的消息出现循环。如果您没有对状态为 200 的 Telegram Webhook 做出响应,它将继续为您发送该消息。

回到简单的工作流程

用户发送 Telegram 消息 -> Telegram Webhook -> API Gateway -> AWS Lambda -> MYSQL 查询 -> 回复 Telegram 用户

问题发生在 Telegram Webhook 和 API 网关之间。由于我的 Lambda 函数需要 30 多秒才能完成,我们的 API 网关永远不会发送响应。它使 Telegram Webhook 不断重复发送相同的消息。

我的解决方法:

我们需要在 API Gateway 超时(30 秒)内发回响应,但我们还需要保持 Lambda 函数运行,直到它以预期结果完成。

搜索后发现题目:Nodejs - Invoke an AWS.Lambda function from within another lambda function

如果我们调用第二个 Lambda,我们可以并行运行它,而第一个 Lambda 可以为 Telegram Webhook 发送预期的响应。

解决方案:

基于这个主题,我检查了一下如何在不等待响应的情况下运行第二个 Lambda 函数,答案是:“Lambda as an EVENT

更多详情在这里: https://docs.aws.amazon.com/lambda/latest/dg/lambda-invocation.html

正如本主题所解释的,如果您将 Lambda 函数作为 EVENT 调用,将会发生什么:

Lambda 1 -> 调用 Lambda 2 Lambda 2 -> 为 Lambda 1 发送状态 202 Lambda 1 -> 为 Telegram Webhook 发送状态 200 Lambda 2 -> 继续运行直到完成工作

这解决了整个问题。

现在 Telegram Webhook 正在接收预期状态,并且我的 Bot 正在并行运行。 现在也许你期待最终的代码。所以我会和你分享。

代码:

Lambda 1
    AWS = require('aws-sdk');
    AWS.config.region = 'sa-east-1';  //Change for your own region
    var lambda = new AWS.Lambda();

    exports.handler = function(event, context, callback) 
    console.log(event)
    var params = 
      FunctionName: 'Lambda Function Name',
      InvocationType: 'Event',
      Payload: JSON.stringify(event)
    ;

    lambda.invoke(params, function(err, data) 
      if (err) 
        console.log(err)
      
    )
      callback(null, statusCode: 200, body: '')
    
Lambda 2

    const bot = require('./Bot')

    exports.handler = function(event) 
        const tmp = JSON.parse(event.body)
        bot.handleUpdate(tmp)
    

附加提示:

您的 Lambda 1 将需要运行 Lambda 2 所需的角色。如果您启用 CloudWatch Logs,它将为您提供所有必要的角色,但我将分享我在下面设置的角色:

【讨论】:

以上是关于AWS Lambda - 使用 MySQL 的 Telegram Bot - 循环消息 \ 相同消息的主要内容,如果未能解决你的问题,请参考以下文章

无法从 AWS Lambda 连接到 AWS RDS MySql DB。 ClassNotFoundException:com.mysql.jdbc

Lambda AWS 不调用节点 mysql 回调

使用 Node.js 从 AWS Lambda 函数连接到 MySql 数据库,没有连接回调

AWS Lambda Invoke 不执行 lambda 函数

从 NodeJS AWS Lambda 函数查询 MySQL 数据库

Lambda 在本地连接到 Aurora MySql - 部署到 AWS 时超时