上線 Python 應(yīng)用僅需一條命令的開源框架:Zappa(詳細教程)
本文面向有 Python Web 基礎(chǔ)的小伙伴

作者:HelloGitHub-吱吱
這里是 HelloGitHub 推出的《講解開源項目》系列,今天要向小伙伴們介紹一個 Python 無服務(wù)(Serverless)框架 Zappa。
Zappa 讓我們可以輕松部署 Python 應(yīng)用程序:僅需幾條命令、打包代碼、上傳云服務(wù)器、程序上線,bingo 一氣呵成!從此減少部署成本,放下運維的重擔。僅需你有一點點 Python Web 基礎(chǔ)!
它到底有多便捷?一條命令即刻部署!

項目地址:https://github.com/Miserlou/Zappa
下面就讓我們動手來試試吧!
一、前言
1.1 介紹 Serverless
剛開篇便提到了一個莫名其妙的名詞:無服務(wù)(Serverless),一開始我也是問號臉,經(jīng)過多方搜證,我們可以簡單的認為 Serverless 是指不必擔心底層基礎(chǔ)結(jié)構(gòu),不需要管理服務(wù)器,從而來構(gòu)建和運行應(yīng)用程序。具體概念小課堂如下:
1.1.1 什么鬼?
回憶一下,平時上線一個簡單的 Python Web 應(yīng)用的過程。
一個 24 小時不間斷運行的服務(wù)器:比如云主機,用以搭建代碼運行環(huán)境和進行系統(tǒng)配置,維持著運行我們的應(yīng)用; 部署 Web 服務(wù)器:我們需要選擇合適的 Web 服務(wù)器,經(jīng)過配置和啟動,實現(xiàn)反向代理和負載均衡; 域名綁定:最后如果要被廣泛用戶訪問,我們需要注冊域名,并且綁定在服務(wù)器; 運營維護:配置和啟動在應(yīng)用上線之后,我們還需要管理和維護我們的服務(wù)器,預(yù)防黑客攻擊,應(yīng)對未來用戶訪問高峰期。
而對于使用 Serverless 架構(gòu)的應(yīng)用,我們只需要關(guān)心我們的應(yīng)用編寫和核心業(yè)務(wù),無需操心云主機、操作系統(tǒng)、資源分配和 Web 服務(wù)器配置等相關(guān)問題,無需考慮服務(wù)器的規(guī)格大小、存儲類型、網(wǎng)絡(luò)帶寬、自動擴縮容問題,無需再對服務(wù)器進行運維、不斷打系統(tǒng)補丁和應(yīng)用補丁、無需進行數(shù)據(jù)備份等工作。一切非核心業(yè)務(wù)都外包給了公共云營運商,讓開發(fā)人員從復(fù)雜的部署和運維環(huán)境中脫身出來,專注于業(yè)務(wù)本身的價值。
用 Zappa 里的一句話說就是 “without any permanent infrastructure”(無需任何永久性基礎(chǔ)設(shè)施)。
敲黑板,盡管從名字上說是 Serverless,但是仍然需要物理服務(wù)器,只是我們開發(fā)人員成了甩手掌柜。
1.1.2 好處有?
降低運維需求和維護成本; 完全自動化的彈性擴容和縮容:在業(yè)務(wù)高峰期時,產(chǎn)品的計算能力和容量自動擴大,承載更多的用戶請求;反之,在業(yè)務(wù)下降時,所使用的資源也會同時收縮,避免資源浪費; 節(jié)省開支,全新的計量計費模式:開發(fā)者僅需根據(jù)使用量來付費。在無業(yè)務(wù)量的情況下,不會有空閑資源占用,也不會有費用產(chǎn)生。
1.1.3 普遍認為 Serverless = FaaS + BaaS
BaaS(Backedn as a Service 后端即服務(wù)) 后端,指的就是各種云產(chǎn)品和云服務(wù),例如對象存儲 OS ,消息隊列 MQ,云數(shù)據(jù)庫 DB,云緩存 Redis以及各種以 API 形式提供的服務(wù)。用戶直接開通即可使用,無需考慮部署、擴容、備份、安全等各種運維工作。 FaaS(Functions as a Service 函數(shù)即服務(wù)) 是 Serverless 的核心,讓用戶僅需編寫和上傳核心業(yè)務(wù)代碼,交由平臺完成部署、調(diào)度、流量分發(fā)和彈性伸縮等能力,它提供了一種新的方式來提供計算資源,進一步降低云計算的使用門檻。
1.1.4 AWS Lambda
在該項目中,伸手白piao AWS 海外區(qū)域賬戶免費 AWS Lambda 套餐。AWS Lambda 作為 Serverless 最早的框架產(chǎn)品由亞馬遜在2014年推出,是一種無服務(wù)器的計算服務(wù),無需預(yù)置或管理服務(wù)器即可運行代碼。Lambda 幾乎可以為任何類型的應(yīng)用程序或后端服務(wù)運行代碼,我們只需上傳相應(yīng)的代碼,它會處理運行和擴展代碼所需的一切工作。

1.2 Python 的 Serverless 框架
本篇文章的主角:Zappa 登場!我們可以通過 Zappa 工具體驗一下 Serverless 技術(shù),用它實現(xiàn)我們 Python 應(yīng)用程序的無服務(wù)器部署,初步體驗無限伸縮擴展、零宕機、零維護的快捷。有了 Zappa,我們無需:
配置 Web 服務(wù)器 付費 24/7 服務(wù)器的正常運行時間 擔心負載平衡和可擴展性 保持自己的服務(wù)器時刻在線狀態(tài)
二、親自動手
實戰(zhàn)時間:已經(jīng)實驗(踩坑)成功(不斷)的我就來分享部署一個簡單的 Flask 應(yīng)用的過程,不要擔心跟著做你也可以~
2.1 環(huán)境
Python版本要求:3.6/3.7/3.8 測試系統(tǒng):Ubuntu 18.04.4 LTS
2.2 準備
保證自己的項目是運行在虛擬環(huán)境下。
# 需要安裝 Python 3.x 版本
python --version
# 安裝 Pipenv
pip install --user pipenv
# 進入自己的項目
cd demo
# 實例化 pipfile 和 venv
pipenv shell
安裝 Zappa 和 Flask,項目需要其他庫的話,可自行添加。
$ pipenv install zappa flask
在目錄下創(chuàng)建
my_app.py文件,寫入官方樣例,可以先pipenv run python my_app.py看看是否能正常運行from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello():
return "hello, from Zappa!\n"
if __name__ == '__main__':
app.run()注冊 AWS 賬戶,并且正確安裝 AWS credentials file
登錄 AWS,找到
My Security Credentials下的Access keys (access key ID and secret access key),如果沒有則創(chuàng)建一個,記住access key ID和secret access key安裝 AWS 的命令行界面,添加 credentials
# 在虛擬環(huán)境下安裝
pipenv install awscli
# 查看信息
aws configure list
# 添加,并且按照提示將 access key ID 和 secret access key 填入
aws configure
# 后兩個 region name 和 output format 選填
此時在
~/.aws目錄下會出現(xiàn)兩個文件 config 和 credentials,credentials 中儲存了 AWS 的access key ID和secret access key, config 中儲存了 region name 和 output format 信息。如果是在 Windows 上操作的同學(xué),可以查看官方提供的安裝 AWS credentials file 的教程。
2.3 安裝與配置
通過執(zhí)行下面語句進行初始化,定義部署和配置的設(shè)置,自動檢測應(yīng)用類型(Flask 或 Django)
$ zappa init在執(zhí)行過程中,可能需要如下設(shè)置,后續(xù)也可以在新生成的
zappa_setting.json的配置文件中修改:
完成后,我們的項目目錄中將有一個
zappa_settings.json文件,里面是我們剛剛定義的基本部署設(shè)置,后期我們可以按照自己的需求修改此文件。{
"dev": {
"app_function": "my_app.app",
"profile_name": null,
"project_name": "demo",
"runtime": "python3.6",
"s3_bucket": "zappa-ti0ra29xi"
}
}注意如果之前已經(jīng)在
~/.aws/config文件中添加 region 信息,則會在zappa init的時候自動尋找到這些 region 信息,無需后續(xù)修改。如果之前沒有添加,則修改
zappa_settings.json,添加 region 信息如下:# 修改如下
{
"dev": {
"app_function": "my_app.app",
"profile_name": null,
"project_name": "demo",
"runtime": "python3.6",
"s3_bucket": "zappa-ti0ra29xi"
"aws_region": "us-west-2"
}
}region 的信息可以自行選擇。
2.4 部署和使用
配置設(shè)置后,可以使用如下命令將應(yīng)用程序打包并部署:
$ zappa deploy dev
當我們調(diào)用 deploy 時,Zappa 會自動將我們的應(yīng)用程序和本地虛擬環(huán)境打包到 Lambda 兼容的 archive,用為 Lambda 預(yù)先編譯的版本替換所有依賴項,設(shè)置功能處理程序和必要的 WSGI 中間件,然后上傳 archive 到 S3,創(chuàng)建和管理必要的Amazon IAM 策略和角色,將其注冊為新的 Lambda function,創(chuàng)建新的 API 網(wǎng)關(guān)資源,為其創(chuàng)建 WSGI 兼容的路由,將其鏈接到新的 Lambda function,最后從 S3 bucket 中刪除 archive。
執(zhí)行成功后,就會出現(xiàn)一個鏈接,點擊鏈接即可訪問我們的簡易 Web 應(yīng)用。看到已上線的應(yīng)用程序,心內(nèi)竊喜,直呼快準狠。

三、其他命令
更新操作:假設(shè)應(yīng)用程序已經(jīng)部署完畢,并且只需要上傳新的 Python 代碼,而無需修改基礎(chǔ)路由,則可以執(zhí)行以下操作:
$ zappa update dev這將創(chuàng)建一個新的 archive,將其上傳到 S3 并更新 Lambda function 以使用新代碼。
查看部署和事件計劃的狀態(tài),只需使用命令:
$ zappa status production查看部署的日志:
$ zappa tail dev
# 過濾 HTTP 請求
$ zappa tail dev --http
# 執(zhí)行相反操作,并且僅顯示非 HTTP 事件和日志消息
$ zappa tail dev --non-http
# 選擇時長
$ zappa tail dev --since 4h # 4 hours回滾操作:通過提供要返回的修訂版本數(shù)將部署的代碼回滾到以前的版本。
# 回滾到3年前部署的版本
$ zappa rollback production -n 3安排 function 定期執(zhí)行:修改
zappa_setting.json,加入如下內(nèi)容:{
"dev": {
...
"events": [{
// The function to execute
"function": "your_module.your_function",
// When to execute it (in cron or rate format)
"expression": "rate(1 minute)"
}],
...
}
}然后執(zhí)行如下操作,我們的 function 就會在每分鐘執(zhí)行一次。
$ zappa schedule dev
# cancal
$ zappa unschedule dev取消部署:如果要刪除以前發(fā)布的 API Gateway 和 Lambda function,則只需:
$ zappa unschedule dev
四、踩坑建議
在成功運行一次之前,踩坑千千萬萬遍,都是因為自己手殘眼瞎魔改了很多地方,把經(jīng)歷過的報錯記錄下來,分享給和我一樣的小小白。
“Unable to import module ‘handler’: attempted relative import with no known parent package”:原因是我們期望的依賴在虛擬的環(huán)境中沒有,需要查看自己虛擬環(huán)境中的依賴是否完整。出現(xiàn)如下報錯,可以更換一個 region 信息。
$ zappa deploy dev
Calling deploy for stage dev..
Creating demo-dev-ZappaLambdaExecutionRole IAM Role..
Error: Failed to manage IAM roles!
You may lack the necessary AWS permissions to automatically manage a Zappa execution role.
Exception reported by AWS:An error occurred (InvalidClientTokenId) when calling the CreateRole operation: The security token included in the request is invalid.
To fix this, see here: https://github.com/Miserlou/Zappa#custom-aws-iam-roles-and-policies-for-deployment如果我們在
zappa init的時候,不使用默認分配的s3_bucket,則須注意自己的名稱是不允許重名的,否則會報錯botocore.errorfactory.BucketAlreadyExists: An error occurred (BucketAlreadyExists) when calling the CreateBucket operation: The requested bucket name is not available. The bucket namespace is shared by all users of the system. Please select a different name and try again.。
五、寫在最后
是不是當自己成功部署后,突然覺得妙不可言,一身輕松,好像再也沒有了之前所說的繁瑣的過程,反而幾條命令,白piao AWS 的服務(wù),咱的應(yīng)用程序就輕巧上線了呢,還不趕緊把生成的鏈接分享給小伙伴們點擊一下。
至此,我們已經(jīng)可以基本實現(xiàn)快速部署一個簡單的 Flask 應(yīng)用了,由于篇幅有限,還有部分 Zappa 的高級功能沒有提及,以及如何使用 Zappa 部署 Django 應(yīng)用或者一個更為龐大的項目(包含數(shù)據(jù)庫等),希望感興趣的小伙伴們能夠多多嘗試,我已經(jīng)開始期待的搓搓手了。如果大家對開源項目感興趣,請第一時間關(guān)注 HelloGitHub,我們將會為大家?guī)砀嘤腥さ母韶泝?nèi)容。

??「點擊關(guān)注」更多驚喜等待你!
