侧边栏壁纸
博主头像
翻斗

开始一件事最好是昨天,其次是现在

  • 累计撰写 44 篇文章
  • 累计创建 42 个标签
  • 累计收到 3 条评论

使用AWS Lambda做webhook

翻斗
2023-07-15 / 0 评论 / 0 点赞 / 1,419 阅读 / 2,439 字

这里有本博客另一篇类似的文章:Firebase应用报错信息发送到企业微信

缘由

最近总会遇到各种需要做及时通知的需求,不管是我们自己的各种性能监测,或者是其他重要的消息推送,总需要提供webhook接口,当然,直接使用比如钉钉或者企业微信接收是可以的,可是总会遇到某些系统(比如是三方的)只支持某一种,甚至都不支持,这个时候就需要有一个做中转的webhook接口,它可以适配各种通知平台,下发消息给钉钉/企业微信等。

思考

很显然,这里的中转webhook是需要可编程的,我们可以是在一台新的云主机(EC2)上跑一个服务,也可以是在Kubernetes集群中跑一个服务,但是这样总会要提供一个服务,而且这个服务一直存在,一直消耗着资源。这不是我想要的,毕竟通知这种事情发生的概率并不大,不需要一直消耗资源提供服务。

所以可以选择一个serverless平台做类似的事情,我们托管代码,按需启动即可,省钱省事,做serverless的鼻祖是AWSLambda,我就直接用Lambda就行。

一个使用aws lambda来实现的例子

这里举个例子,公司使用了一个比较小的SQL审计平台Yearning,里面的webhook只支持钉钉,那我们要支持企业微信的机器人通知,就需要额外代码处理。

前提准备

我们先创建Lambda Function并在高级选项里面选择Enable function URL,这表示可以提供外网直接访问的URL

到这个界面就没必要继续添加trigger或者destination了,因为AWS整个体系很庞大,这个Lambda Function可以有上游的触发器(某个事件触发),也可以处理完成后,根据结果,再调用下游的某个系统/接口。

我的代码很简单,就是将转发给钉钉的消息中的text改成content,转发给企业微信机器人就行

import json
import requests

def send_wechat(md):
    wechat_bot_url = "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxx"
    request_data = md
    r = requests.post(wechat_bot_url, data=json.dumps(request_data))

def lambda_handler(event, context):
    body = event['body']
    body = body.replace('text','content') 
    c = eval(body) 
    send_wechat(c)
    return {
        'statusCode': 200,
        'body': json.dumps('Hello from Lambda!')
    }

这里面的lambda_hander是我们创建的lambda入口, 点击Deploy发布即可

python依赖相关的问题

我们使用postman调用上面的公网访问URLhttps://xxxx.lambda.url.us-west-2.on.aws,进入 Monitor -> Logs 查看最新的日志,会发现报错了!

这是因为requests并不是python自带的库,需要额外安装,lambda运行时无法识别,需要我们额外处理,有几个办法:

在 AWS Lambda 中,默认情况下是没有安装第三方库的,包括 requests。您可以采取以下两种方法之一来解决这个问题:

方法一:将 requests 包打包到 Lambda 函数中

  1. 在本地环境中创建一个目录,并在其中安装 requests 包:

    mkdir lambda-package
    cd lambda-package
    pip install requests -t .
    
  2. requests 包及其依赖项打包成一个 ZIP 文件:

    zip -r9 ../lambda-package.zip .
    

注意,这里会生成很多依赖的文件库

  1. 在 AWS Lambda 控制台中创建或更新您的 Lambda 函数,并上传 lambda-package.zip 文件作为函数代码。

方法二:使用 Lambda Layer

  1. 在本地环境中创建一个目录,并在其中安装 requests 包:

    mkdir lambda-layer
    cd lambda-layer
    pip install requests -t .
    
  2. requests 包及其依赖项打包成一个 ZIP 文件:

    zip -r9 ../lambda-layer.zip .
    
  3. 在 AWS Lambda 控制台中创建一个新的 Lambda Layer,上传 lambda-layer.zip 文件作为 Layer 的内容。

  4. 在 Lambda 函数中将该 Layer 添加到函数的层配置中。

方法三:换一个库,比如使用urllib3

只是简单做一个网络请求的话,urllib3也可以了,并没有麻烦多少

import urllib3
http = urllib3.PoolManager()
wechat_bot_url = "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxxx"
md={"key1":"value1","key2":"value2"}
r = http.request('POST', wechat_bot_url, body=json.dumps(md))

这里我选择方法三,因为更快 😃

结果展示

修复上面问题后,内容如下:

最终将yearning审核平台的消息推送,转接到企业微信:

总结

不管是FAAS还是Serverless还是Lambda,这些并不只是概念里面的词,当我们有一些不那么频繁使用,不太想占用资源的需求是,就可以考虑使用这个技术。比较常见的webhook图片处理文本处理等等工具应用场景都可以考虑使用。

0

评论区