如何通过AWS API Gateway触发EC2上的Python脚本并传递参数?
我之前刚好折腾过类似的需求,给你梳理几个实用的实现方案,你可以根据自己的场景挑最合适的:
这个方案适合你的脚本需要实时响应请求的场景,核心思路是在EC2上用Python搭个轻量HTTP服务,让API Gateway把用户的请求直接转发过去,脚本就能拿到参数了。
步骤拆解:
在EC2上搭建HTTP服务
用Flask或者FastAPI写个简单的服务,监听指定端口,接收并处理请求参数。举个Flask的例子:from flask import Flask, request import json app = Flask(__name__) @app.route('/handle-request', methods=['POST']) def handle_request(): # 从请求体获取参数(支持JSON、表单等格式) request_params = request.get_json() or request.form.to_dict() # 这里写你的业务逻辑,比如处理参数 print(f"收到参数:{json.dumps(request_params)}") # 返回响应给API Gateway,再传给用户 return { "status": "success", "message": "参数已接收并处理", "received_params": request_params } if __name__ == '__main__': # 生产环境建议用gunicorn/uwsgi替代自带的服务器,并且关闭debug app.run(host='0.0.0.0', port=5000, debug=False)运行脚本后,EC2的5000端口就会监听请求了。
配置API Gateway转发
- 创建一个REST API,添加POST方法,集成类型选择「HTTP」
- 集成端点填
http://<EC2公网IP>:5000/handle-request(如果EC2在VPC内,建议用VPC端点让API Gateway内网访问,避免公网暴露) - 部署API到一个阶段(比如prod),然后就能用API的URL测试了
安全配置
- EC2安全组只开放5000端口给API Gateway的IP段(或者VPC内部)
- API Gateway启用HTTPS,避免参数明文传输
- 给API加API Key或者IAM认证,防止非法请求
如果你的脚本不需要实时响应,或者担心EC2临时宕机导致请求丢失,这个解耦方案更靠谱:API Gateway把请求参数发送到SQS队列,EC2上的脚本持续监听队列,拿到消息后再处理。
步骤拆解:
创建SQS队列
在AWS控制台建一个标准队列,记住队列URL。配置API Gateway集成SQS
- REST API添加POST方法,集成类型选择「AWS Service」
- 服务选SQS,区域选你的队列所在区域,动作选
SendMessage - 设置请求模板,把API的请求体转成SQS的消息格式(比如
{"MessageBody": "$input.json('$')"}) - 给API Gateway的执行角色加SQS的
SendMessage权限
EC2上写SQS消费者脚本
用boto3监听队列,拿到消息后解析参数处理:import boto3 import json import time sqs_client = boto3.client('sqs', region_name='us-east-1') QUEUE_URL = "你的SQS队列URL" def process_params(params): # 这里写你的业务逻辑 print(f"处理参数:{json.dumps(params)}") while True: # 长轮询获取消息,减少空轮询次数 response = sqs_client.receive_message( QueueUrl=QUEUE_URL, MaxNumberOfMessages=1, WaitTimeSeconds=20 ) if 'Messages' in response: for message in response['Messages']: # 解析消息体(就是API Gateway传过来的参数) params = json.loads(message['Body']) process_params(params) # 处理完删除消息,避免重复消费 sqs_client.delete_message( QueueUrl=QUEUE_URL, ReceiptHandle=message['ReceiptHandle'] ) time.sleep(1)
这个方案的好处是:API Gateway不用关心EC2状态,请求存在SQS里不会丢;EC2可以随时重启、扩容,甚至换成多个实例消费队列。
如果你的脚本不需要一直运行(比如每天只执行几次),可以用Lambda做中间层:API Gateway触发Lambda,Lambda再通过SSM Run Command去EC2上执行脚本并传参,执行完可以停止EC2节省成本。
步骤拆解:
给EC2配置SSM权限
- EC2实例安装SSM Agent(Amazon Linux默认已装,其他系统需要手动安装)
- 给EC2的IAM角色加
AmazonSSMManagedInstanceCore权限,允许SSM管理实例
写Lambda函数
Lambda从API Gateway拿到参数,调用SSM执行EC2上的脚本:import boto3 import json ssm_client = boto3.client('ssm', region_name='us-east-1') def lambda_handler(event, context): # 从API Gateway的event里提取参数 request_body = json.loads(event['body']) params_json = json.dumps(request_body) # 调用SSM在EC2上执行脚本,把参数传进去 response = ssm_client.send_command( InstanceIds=["你的EC2实例ID"], DocumentName="AWS-RunShellScript", Parameters={ "commands": [ f"python3 /path/to/your/script.py '{params_json}'" ] } ) return { "statusCode": 200, "body": json.dumps({ "command_id": response['Command']['CommandId'], "message": "脚本已触发执行" }) }API Gateway配置
创建REST API的POST方法,集成类型选Lambda,关联上面写的Lambda函数即可。
这个方案适合按需执行脚本的场景,平时EC2可以停止,Lambda触发时再启动(可以在Lambda里加启动EC2的逻辑),能大幅降低成本。
方案选型建议:
- 实时响应、脚本持续运行 → 选方案1
- 高可靠、解耦、允许延迟 → 选方案2
- 按需执行、节省成本 → 选方案3
最后提醒下:不管用哪个方案,都要做参数校验,避免注入攻击;敏感参数要加密传输;IAM权限遵循最小化原则,只给必要的权限。
内容的提问来源于stack exchange,提问作者nnay84

