为了账号安全,请及时绑定邮箱和手机立即绑定

如何在分布式系统中使用AWS Lambda发送通知

将 AWS Lambda 集成到分布式系统中是一种利用无服务器计算优势的强大方法,可以在无需管理基础设施的情况下执行代码。AWS Lambda 在事件驱动架构模式中表现出色,其中函数会在响应特定事件时被触发,通过仅对使用的计算时间收费来实现成本效益。在使用 Lambda 的过程中,保证函数是无状态这一点非常重要,这意味着它们不应在不同的调用之间存储状态。然而,触发 Lambda 函数需要与诸如 SNS 或 SQS 等其他 AWS 服务进行集成,这会增加架构的复杂性,因此全面理解系统设计至关重要。

在本文中,我将展示如何将AWS Lambda用作通知服务的一部分,其中SNS用来发布消息到主题,Lambda将被触发来处理这些通知。我们将逐步配置所需的AWS服务,包括IAM、SNS、SES和Lambda,来创建一个简单的通知服务系统。

AWS Lambda 介绍

AWS Lambda 是一种无服务器计算服务 AWS Lambda,允许您无需预置或管理服务器就能运行代码。此服务根据传入流量自动扩展,使您的应用程序能够处理不同的工作量而无需手动干预。您只需为使用的计算时间付费,这使其对于事件驱动的应用程序来说既经济又可扩展。

Lambda 可以被触发或直接触发其他 AWS 服务(如 API Gateway、SNS 或 S3),响应事件执行代码(推送模型)。根据不同的事件来源,AWS 决定调用是同步还是异步:Lambda 将结果返回给触发的服务,或异步处理事件并根据需要重试。

AWS Lambda 推送模型

在拉模型中,Lambda 函数从队列或流中获取并处理数据,定期处理新到来的事件,当它们进来时。

AWS Lambda 拉取模式

在Lambda中,安全性至关重要,它使用两种类型的权限:调用权限(invocation权限)允许事件源触发该函数,以及执行角色(execution角色),赋予Lambda访问其他AWS服务的权限。这些角色通过IAM策略来管理。

AWS Lambda 权限种类

Lambda 可以用多种方式配置,比如:

  • AWS 管理控制台(UI 界面)
  • AWS CLI
  • AWS SDK(特定语言的SDK API)
  • AWS Cloudformation — 基础设施即代码(JSON, YAML)
  • AWS 无服务器应用模型(用于创建不同类型的函数的模板)。
建筑

当用户预订房间或服务时,我们希望通知该用户。在这种情况下,可以使用 AWS Lambda 作为通知服务。然而,我们无法从代码中触发 Lambda 函数。例如,我们可以利用 AWS 简单通知服务(SNS)发布消息到一个主题,然后 Lambda 函数可以订阅该主题。AWS Lambda 处理程序函数可以封装通知逻辑(例如选择通知类型、用户白名单等),但不能直接发送电子邮件和短信。可以使用 AWS 简单电子邮件服务(SES)发送电子邮件。

预订系统架构,其中包括 AWS Lambda 作为其中的通知服务

向 AWS SNS 发布消息,

我们的预订服务应提供API以在生产环境中的系统中执行操作。然而,为了简化,我们将使用一个简单的函数来模拟预订过程。

    import boto3  
    import json  
    import os  
    import random  

    # 初始化SNS客户端  
    sns = boto3.client(  
        'sns',  
        region_name=os.environ.get('REGION'),  
        aws_access_key_id=os.environ.get('ACCESS_KEY_ID'),  
        aws_secret_access_key=os.environ.get('SECRET_ACCESS_KEY'),  
    )  

    # 您的SNS主题的ARN  
    sns_topic_arn = os.environ.get('TOPIC_ARN')  

    # 定义一个发布消息的函数  
    def publish_message(message):  
        response = sns.publish(  
            TopicArn=sns_topic_arn,  
            Message=json.dumps({'default': json.dumps(message)}),  
            MessageStructure='json',  
        )  
        print(f"消息已成功发送到SNS: {response['MessageId']}")  

    if __name__ == "__main__":  
        # 如果该脚本被直接运行,而不是被导入  
        r = random.randint(0, 1000000)  
        message = {  
            'event': '预订',  
            'user_id': '12345',  
            'email': f'user+{r}@example.com',  
            'body': '内容:预订成功',  
        }  
        publish_message(message)

为了使用 AWS SDK for Python,我们需要先安装 boto3 包。我们可以使用 pip 来安装它:

$ pip install boto3 # 使用pip安装boto3库

为了将我们的代码与任何AWS服务集成,最简单的方法是创建一个具有编程访问权限的新IAM用户并附加所需的策略。

导航到 AWS IAM

  • 点击“用户”选项卡,接着点击Create user按钮。

用户页

  • 输入用户名。

用户名区域

  • 选择 直接附加策略 的权限选项。
  • 添加以下策略:AmazonSNSFullAccess

用户权限设置

  • 继续进行下一步,创建用户。
  • 选择刚刚创建的用户并点击 创建访问密钥

我的页面

  • 下载 CSV 文件。

创建了一个用户账号

  • 在系统中设置环境变量:
export: ACCESS_KEY_ID = 将你的access_key_id  
export: SECRET_ACCESS_KEY = 将你的secret_access_key

接下来,我们需要创建一个SNS,用来发布消息。

  • 进入 AWS 管理控制台中的 SNS 控制台。
  • 点击 新建主题 按钮并点击 下一步 >

SNS 话题 banner

  • 使用默认设置,并点击 创建话题

zh: SNS话题模板

  • 复制刚刚创建的主题的ARN。

zh: SNS话题页

  • 设置环境变量:
export TOPIC_ARN=arn:aws:sns:us-east-1:338535437683:notifications  
export REGION=us-east-1

当我们执行代码时

    $ python app.py  
    消息已通过SNS发布: ea014270-af41-52d3-acb4-1de1320e28fa

我们应该获取一条日志信息,表明消息已成功发布到SNS话题。

在下一节中,我们将添加一个处理来自主题的事件的 AWS Lambda 函数。

AWS SES 配置

在准备AWS Lambda函数之前,我们需要配置AWS简单邮件服务(SES)来发送邮件。默认SES服务是在沙盒模式下运行,这意味着您只能向经过验证的电子邮件发送信息。如果要向任何邮箱发送邮件,您需要申请进入生产环境。在我们的例子中,我们将继续使用沙盒模式。

  • 打开 AWS Management Console 并进入 SES 服务。
  • 提供您希望在沙盒模式下接收测试消息的电子邮件地址。

SES 邮件验证, 部分

  • 提供域名(但无需在测试模式下),。

SES领域部分

完成验证过程

SES 配置页面概要

  • 确认您邮箱中的地址。
  • 发送一封测试邮件。

在SES配置面板里找到发送测试邮件的部分

要离开SES沙盒并向任何收件地址发送邮件,你需要申请生产权限并提供你已验证的域名。

AWS Lambda 函数

现在,我们可以创建一个由SNS主题触发的Lambda函数。不过,我们需要创建一个IAM角色,以便Lambda函数可以被SNS主题触发。

  • 在 AWS Management Console 中转到 IAM 服务。

前往IAM(身份与访问管理)

  • 点击 角色 选项卡,然后点击 创建角色 按钮。
  • 选择 Lambda 服务,并将其作为服务或用例,并将其设为 AWS 服务,作为受信任的实体。

IAM角色的信任实体类型

添加以下策略:AWSLambdaBasicExecutionRoleAmazonSESFullAccess

IAM权限部分

  • 输入角色名称(比如 LambdaUseSES),然后单击 创建角色按钮

创建好角色(Role)后,接下来我们就可以创建 Lambda 函数了。

  • 在 AWS Management Console 中导航到 Lambda 服务。
  • 点击 创建函数 按钮。

AWS Lambda 函数创建

  • 选择 使用蓝图选项 并查找 sns 蓝图。我们使用的是 py3.10 的 SNS 集成。

使用蓝图来创建AWS Lambda函数

  • 指定函数名(本例中为 notification-handler)。
  • 选择 使用现有角色 选项,然后选择我们之前创建的用于 Lambda 的角色 LambdaUseSES

AWS Lambda 权限设置

  • 在SNS触发器部分中,选择我们创建的notifications SNS主题。它会自动创建一个订阅。

AWS Lambda SNS 触发器

  • 函数代码稍后会更新。
  • 点击 创建函数 按钮来继续。

我们的 AWS Lambda 函数现在已设置为响应由 notifications 主题发送的 SNS 消息。

AWS Lambda 图解

最后一步就是更新Lambda函数的代码。我们将用下面这段代码。

    import json  
    import boto3  

    client = boto3.client('ses', region_name='eu-central-1')  

    def lambda_handler(event, context):  
        data = json.loads(event['Records'][0]['Sns']['Message'])  
        body = data.get('body')  
        email = data.get('email')  

        response = client.send_email(  
        Destination={  
            'ToAddresses': ['verified@mail.com']  
        },  
        Message={  
            'Body': {  
                'Text': {  
                    'Charset': 'UTF-8',  
                    'Data': body,  
                }  
            },  
            'Subject': {  
                'Charset': 'UTF-8',  
                'Data': '预订邮件发送给:' + email,  
            },  
        },  
        Source='verified@mail.com'  
        )  
        print("发送邮件给:" + email)  
        return {  
            'statusCode': 200,  
            'body': json.dumps("邮件发送成功,MessageId 为: " + response['MessageId'])  
        }

在Lambda函数内部,我们可以使用boto3包来使用SES服务发送邮件,而无需任何额外的配置。我们需要在代码中记录想要发送的邮件地址。由于我们处于沙箱模式,所以我们只能向经过验证的邮件地址发送邮件。因此,发送的邮件地址必须是我们在SES服务中验证过的地址。当代码准备就绪时,我们可以通过点击Deploy来更新Lambda函数代码。新的Lambda函数版本已经准备好,可以通过SNS主题触发。

为了从头到尾测试它,我们可以运行 app.py 脚本来验证它。

    $ python app.py  
    消息已发到SNS, 87633e01-380e-5060-a9a4-619089a9bc6a

邮件应该已经到了我们的邮箱。不过,给 Lambda 函数赋予 AWSLambdaBasicExecutionRole 权限后,它就可以访问 CloudWatch 日志了。怎么查看这个日志呢?

  • 导航到您的Lambda函数的页面。
  • 点击监控(Monitoring)选项卡。
  • 点击在CloudWatch中查看日志按钮。

AWS Lambda 监控选项卡,

  • 点击最新的一条日志流。(每个部署的版本都会有自己独立的日志流。)

AWS Lambda 日志流清单

  • 看看日志。

AWS Lambda 日志流

我们可以看到请求 21c1841e-a6c2-4ecc-9856-fe6a1682454d 这一信息,成功发送邮件给 user+577461@example.com 的日志。邮件我也在我的收件箱里找到了。

收到了一封邮件

结论部分

最终,虽然我们的示例Lambda函数很直接,但一个准备投入生产的版本应该考虑到更多的复杂性,例如重试机制、针对不同通知类型(电子邮件、短信、推送)的决策,以及强大的错误处理措施。需要仔细考虑这些场景,以确保可靠性和可扩展性。如果您对成本有所顾虑,可以使用诸如AWS定价计算器之类的工具来估算,根据您的使用情况估算Lambda的成本。

虽然 AWS Lambda 是一个强大的无服务器事件驱动工具,但重要的是要认识到它不是一个适用于所有情况的解决方案。了解它的局限性和它在某些特定场景中的优势是最大化利用此服务,特别是在分布式系统架构中的关键。

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消