要将 Flask/sqlalchemy 应用程序与 Lambda 一起使用,您需要将 Flask 包装在 Lambda 调度模型中,并确保 sqlalchemy 可以访问其数据库。
向 Flask 发送 Lambda 请求
您可以像这样将Chalice 与 Flask 集成:
class ChaliceWithFlask(chalice.Chalice):
"""
Subclasses Chalice to host a Flask app, route and proxy requests to it.
"""
def __init__(self, flask_app, *args, **kwargs):
super().__init__(*args, **kwargs)
self.flask_app = flask_app
self.trailing_slash_routes = []
routes = collections.defaultdict(list)
for rule in self.flask_app.url_map.iter_rules():
route = re.sub(r"<(.+?)(:.+?)?>", r"{\1}", rule.rule)
if route.endswith("/"):
self.trailing_slash_routes.append(route.rstrip("/"))
routes[route.rstrip("/")] += rule.methods
for route, methods in routes.items():
self.route(route, methods=list(set(methods) - {"OPTIONS"}), cors=True)(self.dispatch)
def dispatch(self, *args, **kwargs):
uri_params = self.current_request.uri_params or {}
path = self.current_request.context["resourcePath"].format(**uri_params)
if self.current_request.context["resourcePath"] in self.trailing_slash_routes:
if self.current_request.context["path"].endswith("/"):
path += "/"
else:
return chalice.Response(status_code=requests.codes.found, headers={"Location": path + "/"}, body="")
req_body = self.current_request.raw_body if self.current_request._body is not None else None
base_url = "https://{}".format(self.current_request.headers["host"])
query_string = self.current_request.query_params or {}
with self.flask_app.test_request_context(path=path,
base_url=base_url,
query_string=list(query_string.items()),
method=self.current_request.method,
headers=list(self.current_request.headers.items()),
data=req_body,
environ_base=self.current_request.stage_vars):
flask_res = self.flask_app.full_dispatch_request()
res_headers = dict(flask_res.headers)
res_headers.pop("Content-Length", None)
res_body = b"".join([c for c in flask_res.response])
return chalice.Response(status_code=flask_res._status_code, headers=res_headers, body=res_body)
flask_app = flask.Flask(app_name)
# add routes, etc. to your Flask app here
app = ChaliceWithFlask(app_name, flask_app=flask_app)
将 sqlalchemy 连接到数据库
您可以直接访问数据库,但这意味着将数据库端口打开到 Internet 或将您的 Lambda 放置在 VPC 中(这使得 Lambda 无法通过 Internet 访问)。此外,传统的数据库驱动程序对其连接的持久性做出了 Lambda 不满足的假设。
AWS 最近为此推出了完美的解决方案 - AWS Aurora RDS 数据 API。它基本上是一个 AWS 认证的 SQL-over-HTTP 隧道。我为它写了一个 SQLAlchemy 适配器:sqlalchemy-aurora-data-api。安装后,你可以这样做:
from sqlalchemy import create_engine
cluster_arn = "arn:aws:rds:us-east-1:123456789012:cluster:my-aurora-serverless-cluster"
secret_arn = "arn:aws:secretsmanager:us-east-1:123456789012:secret:MY_DB_CREDENTIALS"
app = Flask(app_name)
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql+auroradataapi://:@/my_db_name'
engine_options=dict(connect_args=dict(aurora_cluster_arn=cluster_arn, secret_arn=secret_arn))
db = flask_sqlalchemy.SQLAlchemy(app, engine_options=engine_options)