簡體   English   中英

在AWS Lambda和API網關中部署Flask sqlalchemy應用程序

[英]Deploying Flask sqlalchemy apps in AWS lambda and API gateway

我找不到很好的資源來幫助我理解如何將Flask和sqlalchemy應用程序遷移到AWS lambda和API網關並使之無服務器。 像下面這樣的示例是從flask_sqlalchemy文檔獲取的示例代碼:

from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////tmp/test.db'
db = SQLAlchemy(app)


class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(80), unique=True, nullable=False)
    email = db.Column(db.String(120), unique=True, nullable=False)

    def __repr__(self):
        return '<User %r>' % self.username

現在,我如何將該代碼遷移到AWS lambda。 甚至有可能。 例如,行app = Flask(__name__)應該不正確嗎? 如果沒有應用程序變量,我該如何初始化數據庫變量?

請有人能給我一些介紹或指向可以清除這些概念的優秀教程的鏈接嗎?

提前謝謝了。

要將Flask / sqlalchemy應用程序與Lambda一起使用,您需要將Flask包裝在Lambda調度模型中,並確保sqlalchemy可以訪問其數據庫。

將Lambda請求分派到Flask

您可以將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 Data API。 它基本上是一個AWS認證的HTTP 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)

首先,在AWS Lambda中,您不再使用Flask進行路由。 而是使用AWS API Gateway進行路由。 下面顯示了路由示例, 網址https://apievangelist.com/2017/10/23/a-simple-api-with-aws-dynamodb-lambda-and-api-gateway/

https://apievangelist.com/2017/10/23/a-simple-api-with-aws-dynamodb-lambda-and-api-gateway/

如您在圖片的右端看到的,“ Lambda”框顯示了您已上傳的Lambda函數的名稱。 有關Python中的Lambda,請參見https://docs.aws.amazon.com/lambda/latest/dg/python-programming-model-handler-types.html

基本上,Python lambda的主要功能是:

def handler_name(event, context): 
   ...
   return some_value

從事件和上下文中,您可以獲得所有信息:路徑,HTTP方法,標頭,參數,正文等(例如flask.request )。 您可能還需要知道執行Lambda LAMBDALAMBDA_PROXY的 兩種方法(請參見第一張圖片中的Integration Request框)。

簡短的版本差異是:

  • LAMBDA模式將自動預處理請求主體,並在event為Lambda函數提供一個Python對象。
  • LAMBDA_PROXY將給您原始的HTTP請求,您需要在Lambda函數內部自己轉換內容。

對於SQL Alchemy,您所需要做的就是將所有 SQL Alchemy庫代碼及其依賴項與Lambda函數一起壓縮,然后將其上傳到Lambda控制台,它無需任何修改即可工作。

請注意,由於Lambda函數無法訪問文件系統,因此SQLite 無法在Lambda中運行。 您應該將數據放在其他地方,例如Amazon RDS(使用MySQL,PostgreSQL,隨便使用什么),然后確保Lambda與RDS數據庫連接到同一VPC(Amazon內部路由器)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM