使用 Flask、Google 的 Cloud SQL 和 App Engine 设置 API
已发表: 2022-03-10一些 Python 框架可用于创建 API,其中两个是 Flask 和 Django。 框架附带的功能使开发人员可以轻松实现用户与其应用程序交互所需的功能。 当您选择使用哪个框架时,Web 应用程序的复杂性可能是一个决定性因素。
姜戈
Django 是一个健壮的框架,具有预定义的结构和内置功能。 然而,其稳健性的缺点是它可能使框架对于某些项目来说过于复杂。 它最适合需要利用 Django 高级功能的复杂 Web 应用程序。
烧瓶
另一方面,Flask 是用于构建 API 的轻量级框架。 开始使用它很容易,并且可以使用软件包使其在您使用时变得健壮。 本文将重点介绍定义视图函数和控制器,以及连接到 Google Cloud 上的数据库并部署到 Google Cloud。
出于学习的目的,我们将构建一个带有几个端点的 Flask API 来管理我们最喜欢的歌曲的集合。 端点将用于GET
和POST
请求:获取和创建资源。 除此之外,我们将使用 Google Cloud 平台上的服务套件。 我们将为我们的数据库设置 Google 的 Cloud SQL,并通过部署到 App Engine 来启动我们的应用程序。 本教程面向初次尝试将 Google Cloud 用于其应用程序的初学者。
设置 Flask 项目
本教程假设您已安装 Python 3.x。 如果您不这样做,请前往官方网站下载并安装它。
要检查是否安装了 Python,请启动命令行界面 (CLI) 并运行以下命令:
python -V
我们的第一步是创建项目所在的目录。 我们将其称为flask-app
:
mkdir flask-app && cd flask-app
启动 Python 项目时要做的第一件事就是创建一个虚拟环境。 虚拟环境隔离您的工作 Python 开发。 这意味着该项目可以有自己的依赖项,与您机器上的其他项目不同。 venv 是 Python 3 附带的一个模块。
让我们在flask-app
目录中创建一个虚拟环境:
python3 -m venv env
此命令在我们的目录中创建一个env
文件夹。 名称(在本例中为env
)是虚拟环境的别名,可以任意命名。
现在我们已经创建了虚拟环境,我们必须告诉我们的项目使用它。 要激活我们的虚拟环境,请使用以下命令:
source env/bin/activate
您将看到您的 CLI 提示现在以env
开头,表明我们的环境处于活动状态。
现在,让我们安装我们的 Flask 包:
pip install flask
在我们的当前目录中创建一个名为api
的目录。 我们正在创建这个目录,以便我们有一个文件夹,我们的应用程序的其他文件夹将驻留。
mkdir api && cd api
接下来,创建一个main.py
文件,它将作为我们应用程序的入口点:
touch main.py
打开main.py
,输入以下代码:
#main.py from flask import Flask app = Flask(__name__) @app.route('/') def home(): return 'Hello World' if __name__ == '__main__': app.run()
让我们了解我们在这里做了什么。 我们首先从 Flask 包中导入了Flask
类。 然后,我们创建了该类的一个实例并将其分配给app
。 接下来,我们创建了第一个端点,它指向我们应用的根目录。 总之,这是一个调用/
路由的视图函数——它返回Hello World
。
让我们运行应用程序:
python main.py
这将启动我们的本地服务器并在https://127.0.0.1:5000/
上为我们的应用程序提供服务。 在浏览器中输入 URL,您将在屏幕上看到打印的Hello World
响应。
瞧! 我们的应用程序已启动并正在运行。 下一个任务是让它发挥作用。
为了调用我们的端点,我们将使用 Postman,这是一种帮助开发人员测试端点的服务。 您可以从官方网站下载它。
让我们让main.py
返回一些数据:
#main.py from flask import Flask, jsonify app = Flask(__name__) songs = [ { "title": "Rockstar", "artist": "Dababy", "genre": "rap", }, { "title": "Say So", "artist": "Doja Cat", "genre": "Hiphop", }, { "title": "Panini", "artist": "Lil Nas X", "genre": "Hiphop" } ] @app.route('/songs') def home(): return jsonify(songs) if __name__ == '__main__': app.run()
在这里,我们包含了歌曲列表,包括歌曲的标题和艺术家的姓名。 然后我们将根/
路由更改为/songs
。 该路由返回我们指定的歌曲数组。 为了将我们的列表作为 JSON 值获取,我们通过将列表传递给jsonify
来对列表进行 JSON 化。 现在,当我们访问https://127.0.0.1:5000/songs
端点时,我们看到的不是一个简单的Hello world
,而是一个艺术家列表。
您可能已经注意到,每次更改后,我们都必须重新启动服务器。 要在代码更改时启用自动重新加载,让我们启用调试选项。 为此, app.run
更改为:
app.run(debug=True)
接下来,让我们使用 post 请求向我们的数组添加一首歌曲。 首先,导入request
对象,以便我们可以处理来自用户的传入请求。 稍后我们将在视图函数中使用request
对象来获取 JSON 格式的用户输入。
#main.py from flask import Flask, jsonify, request app = Flask(__name__) songs = [ { "title": "Rockstar", "artist": "Dababy", "genre": "rap", }, { "title": "Say So", "artist": "Doja Cat", "genre": "Hiphop", }, { "title": "Panini", "artist": "Lil Nas X", "genre": "Hiphop" } ] @app.route('/songs') def home(): return jsonify(songs) @app.route('/songs', methods=['POST']) def add_songs(): song = request.get_json() songs.append(song) return jsonify(songs) if __name__ == '__main__': app.run(debug=True)
我们的add_songs
视图函数获取用户提交的歌曲并将其附加到我们现有的歌曲列表中。
到目前为止,我们已经从 Python 列表中返回了数据。 这只是实验性的,因为在更健壮的环境中,如果我们重新启动服务器,我们新添加的数据将会丢失。 这是不可行的,因此我们需要一个实时数据库来存储和检索数据。 Cloud SQL 出现了。
为什么要使用 Cloud SQL 实例?
根据官方网站:
“Google Cloud SQL 是一项完全托管的数据库服务,可让您轻松地在云中设置、维护、管理和管理关系型 MySQL 和 PostgreSQL 数据库。 Cloud SQL 托管在 Google Cloud Platform 上,为在任何地方运行的应用程序提供了数据库基础架构。”
这意味着我们可以以灵活的价格将数据库基础架构的管理完全外包给 Google。
Cloud SQL 和自我管理的计算引擎之间的区别
在 Google Cloud 上,我们可以在 Google 的 Compute Engine 基础架构上启动虚拟机并安装我们的 SQL 实例。 这意味着我们将负责垂直可扩展性、复制和许多其他配置。 使用 Cloud SQL,我们可以获得很多开箱即用的配置,因此我们可以将更多时间花在代码上,而减少设置时间。
在我们开始之前:
- 注册谷歌云。 Google 为新用户提供 300 美元的免费信用额度。
- 创建一个项目。 这非常简单,可以直接从控制台完成。
创建 Cloud SQL 实例
注册 Google Cloud 后,在左侧面板中,滚动到“SQL”选项卡并单击它。
首先,我们需要选择一个 SQL 引擎。 我们将在本文中使用 MySQL。
接下来,我们将创建一个实例。 默认情况下,我们的实例会在美国创建,并且会自动为我们选择区域。
设置 root 密码并为实例命名,然后单击“创建”按钮。 您可以通过单击“显示配置选项”下拉菜单进一步配置实例。 这些设置允许您配置实例的大小、存储容量、安全性、可用性、备份等。 对于本文,我们将使用默认设置。 不用担心,这些变量可以稍后更改。
该过程可能需要几分钟才能完成。 当您看到绿色复选标记时,您将知道该实例已准备就绪。 单击您的实例名称以转到详细信息页面。
现在,我们已经启动并运行,我们将做一些事情:
- 创建一个数据库。
- 创建一个新用户。
- 将我们的 IP 地址列入白名单。
创建数据库
导航到“数据库”选项卡以创建数据库。
创建新用户
在“主机名”部分,将其设置为允许“%(任何主机)”。
白名单 IP 地址
您可以通过以下两种方式之一连接到您的数据库实例。 私有 IP地址需要虚拟私有云 (VPC)。 如果您选择此选项,Google Cloud 将创建一个由 Google 管理的 VPC 并将您的实例放入其中。 对于本文,我们将使用默认的公共 IP地址。 它是公开的,只有 IP 地址被列入白名单的人才能访问数据库。
要将您的 IP 地址列入白名单,请在 Google 搜索中输入my ip
以获取您的 IP。 然后,转到“连接”选项卡和“添加网络”。
连接到实例
接下来,导航到“概述”面板并使用云外壳进行连接。
连接到我们的 Cloud SQL 实例的命令将在控制台中预先输入。
您可以使用 root 用户或之前创建的用户。 在下面的命令中,我们说:以用户USERNAME
连接到flask-demo
实例。 系统将提示您输入用户密码。
gcloud sql connect flask-demo --user=USERNAME
如果您收到一个错误提示您没有项目 ID,您可以通过运行以下命令获取项目的 ID:
gcloud projects list
将上面命令输出的项目 ID 输入到下面的命令中,用它替换PROJECT_ID
。
gcloud config set project PROJECT_ID
然后,运行gcloud sql connect
命令,我们将被连接。
运行此命令以查看活动数据库:
> show databases;
我的数据库名为db_demo
,我将运行以下命令来使用db_demo
数据库。 您可能会看到一些其他数据库,例如information_schema
和performance_schema
。 这些用于存储表元数据。
> use db_demo;
接下来,创建一个表来反映我们的 Flask 应用程序中的列表。 在记事本上键入以下代码并将其粘贴到您的云外壳中:
create table songs( song_id INT NOT NULL AUTO_INCREMENT, title VARCHAR(255), artist VARCHAR(255), genre VARCHAR(255), PRIMARY KEY(song_id) );
此代码是一个 SQL 命令,用于创建一个名为song_id
songs
title
、 artist
和genre
)。 我们还指示该表应将song_id
定义为主键并从 1 自动递增。
现在,运行show tables;
确认表已创建。
就这样,我们创建了一个数据库和我们的songs
表。
我们的下一个任务是设置 Google App Engine,以便我们可以部署我们的应用程序。
谷歌应用引擎
App Engine 是一个完全托管的平台,用于大规模开发和托管 Web 应用程序。 部署到 App Engine 的一个优势是它使应用程序能够自动扩展以满足传入流量。
App Engine 网站说:
“通过零服务器管理和零配置部署,开发人员可以只专注于构建出色的应用程序,而无需管理开销。”
设置 App 引擎
有几种方法可以设置 App Engine:通过 Google Cloud Console 的 UI 或通过 Google Cloud SDK。 我们将在本节中使用 SDK。 它使我们能够从本地机器部署、管理和监控我们的 Google Cloud 实例。
安装谷歌云 SDK
按照说明下载并安装适用于 Mac 或 Windows 的 SDK。 该指南还将向您展示如何在 CLI 中初始化 SDK 以及如何选择 Google Cloud 项目。
现在 SDK 已安装,我们将使用数据库凭据更新 Python 脚本并部署到 App Engine。
本地设置
在我们的本地环境中,我们将更新设置以适应我们的新架构,其中包括 Cloud SQL 和 App Engine。
首先,将app.yaml
文件添加到我们的根文件夹。 这是 App Engine 托管和运行我们的应用程序所需的配置文件。 它告诉 App Engine 我们的运行时和其他可能需要的变量。 对于我们的应用程序,我们需要将数据库的凭据添加为环境变量,以便 App Engine 知道我们的数据库实例。
在app.yaml
文件中,添加以下代码段。 您将通过设置数据库获得运行时和数据库变量。 将这些值替换为您在设置 Cloud SQL 时使用的用户名、密码、数据库名称和连接名称。
#app.yaml runtime: python37 env_variables: CLOUD_SQL_USERNAME: YOUR-DB-USERNAME CLOUD_SQL_PASSWORD: YOUR-DB-PASSWORD CLOUD_SQL_DATABASE_NAME: YOUR-DB-NAME CLOUD_SQL_CONNECTION_NAME: YOUR-CONN-NAME
现在,我们要安装 PyMySQL。 这是一个 Python MySQL 包,用于连接 MySQL 数据库并在其上执行查询。 通过在 CLI 中运行此行来安装 PyMySQL 包:
pip install pymysql
此时,我们已准备好使用 PyMySQL 从应用程序连接到我们的 Cloud SQL 数据库。 这将使我们能够在我们的数据库中获取和插入查询。
初始化数据库连接器
首先,在我们的根文件夹中创建一个db.py
文件,并添加以下代码:
#db.py import os import pymysql from flask import jsonify db_user = os.environ.get('CLOUD_SQL_USERNAME') db_password = os.environ.get('CLOUD_SQL_PASSWORD') db_name = os.environ.get('CLOUD_SQL_DATABASE_NAME') db_connection_name = os.environ.get('CLOUD_SQL_CONNECTION_NAME') def open_connection(): unix_socket = '/cloudsql/{}'.format(db_connection_name) try: if os.environ.get('GAE_ENV') == 'standard': conn = pymysql.connect(user=db_user, password=db_password, unix_socket=unix_socket, db=db_name, cursorclass=pymysql.cursors.DictCursor ) except pymysql.MySQLError as e: print(e) return conn def get_songs(): conn = open_connection() with conn.cursor() as cursor: result = cursor.execute('SELECT * FROM songs;') songs = cursor.fetchall() if result > 0: got_songs = jsonify(songs) else: got_songs = 'No Songs in DB' conn.close() return got_songs def add_songs(song): conn = open_connection() with conn.cursor() as cursor: cursor.execute('INSERT INTO songs (title, artist, genre) VALUES(%s, %s, %s)', (song["title"], song["artist"], song["genre"])) conn.commit() conn.close()
我们在这里做了一些事情。
首先,我们使用os.environ.get
方法从app.yaml
文件中检索数据库凭据。 App Engine 能够使app.yaml
中定义的环境变量在应用程序中可用。
其次,我们创建了一个open_connection
函数。 它使用凭据连接到我们的 MySQL 数据库。
第三,我们添加了两个函数: get_songs
和add_songs
。 第一个通过调用open_connection
函数启动与数据库的连接。 然后它查询每一行的songs
表,如果为空,则返回“数据库中没有歌曲”。 add_songs
函数将一条新记录插入到songs
表中。
最后,我们回到我们开始的地方,我们的main.py
文件。 现在,我们不再像之前那样从对象中获取歌曲,而是调用add_songs
函数插入一条记录,然后调用get_songs
函数从数据库中检索记录。
让我们重构main.py
:
#main.py from flask import Flask, jsonify, request from db import get_songs, add_songs app = Flask(__name__) @app.route('/', methods=['POST', 'GET']) def songs(): if request.method == 'POST': if not request.is_json: return jsonify({"msg": "Missing JSON in request"}), 400 add_songs(request.get_json()) return 'Song Added' return get_songs() if __name__ == '__main__': app.run()
我们导入了get_songs
和add_songs
函数并在我们的songs()
视图函数中调用它们。 如果我们发出post
请求,我们调用add_songs
函数,如果我们发出get
请求,我们调用get_songs
函数。
我们的应用程序就完成了。
接下来是添加requirements.txt
文件。 此文件包含运行应用程序所需的软件包列表。 App Engine 会检查此文件并安装列出的软件包。
pip freeze | grep "Flask\|PyMySQL" > requirements.txt
此行获取我们用于应用程序的两个包(Flask 和 PyMySQL),创建一个requirements.txt
文件,并将包及其版本附加到文件中。
此时,我们添加了三个新文件: db.py
、 app.yaml
和requirements.txt
。
部署到 Google App Engine
运行以下命令来部署您的应用程序:
gcloud app deploy
如果一切顺利,您的控制台将输出以下内容:
您的应用现在正在 App Engine 上运行。 要在浏览器中查看它,请在 CLI 中运行gcloud app browse
。
我们可以启动 Postman 来测试我们的post
并get
请求。
我们的应用程序现在托管在 Google 的基础架构上,我们可以调整配置以获得无服务器架构的所有好处。 展望未来,您可以在本文的基础上构建您的无服务器应用程序,使其更加健壮。
结论
使用 App Engine 和 Cloud SQL 等平台即服务 (PaaS) 基础架构基本上可以抽象出基础架构级别,使我们能够更快地构建。 作为开发人员,我们不必担心配置、备份和恢复、操作系统、自动缩放、防火墙、迁移流量等等。 但是,如果您需要控制底层配置,那么使用定制服务可能会更好。
参考
- “下载 Python”
- “venv — 创建虚拟环境”,Python(文档)
- “下载邮递员”
- “云 SQL”,谷歌云
- 谷歌云
- “谷歌云免费套餐”,谷歌云
- “创建和管理项目”,谷歌云
- 《VPC概览》(虚拟私有云),谷歌云
- “应用引擎”,谷歌云
- “快速入门”(下载 Google Cloud SDK)、Google Cloud
- PyMySQL 文档