使用 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 文檔