上線 Python 應用僅需一條命令的開源框架:Zappa(詳細教程)
阿新 • • 發佈:2021-03-08
> 本文面向有 Python Web 基礎的小夥伴
![](https://img2020.cnblogs.com/blog/759200/202103/759200-20210307162458929-100637304.jpg)
作者:HelloGitHub-吱吱
這裡是 **HelloGitHub 推出的[《講解開源專案》](https://github.com/HelloGitHub-Team/Article)系列**,今天要向小夥伴們介紹一個 Python 無服務(Serverless)框架 Zappa。
Zappa 讓我們可以輕鬆部署 Python 應用程式:僅需幾條命令、打包程式碼、上傳雲伺服器、程式上線,bingo 一氣呵成!從此減少部署成本,放下運維的重擔。僅需你有一點點 Python Web 基礎!
它到底有多便捷?一條命令即刻部署!
![](https://img2020.cnblogs.com/blog/759200/202103/759200-20210307163101326-1344495642.png)
> 專案地址:https://github.com/Miserlou/Zappa
下面就讓我們動手來試試吧!
## 一、前言
### 1.1 介紹 Serverless
剛開篇便提到了一個~~莫名其妙~~的名詞:**無服務(Serverless)**,一開始我也是問號臉,經過多方蒐證,我們可以簡單的認為 Serverless 是指不必擔心底層基礎結構,不需要管理伺服器,從而來構建和執行應用程式。具體概念小課堂如下:
#### 1.1.1 什麼鬼?
回憶一下,平時上線一個簡單的 Python Web 應用的過程。
- 一個 24 小時不間斷執行的伺服器:比如雲主機,用以搭建程式碼執行環境和進行系統配置,維持著執行我們的應用;
- 部署 Web 伺服器:我們需要選擇合適的 Web 伺服器,經過配置和啟動,實現反向代理和負載均衡;
- 域名繫結:最後如果要被廣泛使用者訪問,我們需要註冊域名,並且繫結在伺服器;
- 運營維護:配置和啟動在應用上線之後,我們還需要管理和維護我們的伺服器,預防黑客攻擊,應對未來使用者訪問高峰期。
而對於使用 Serverless 架構的應用,我們只需要關心我們的應用編寫和核心業務,無需操心雲主機、作業系統、資源分配和 Web 伺服器配置等相關問題,無需考慮伺服器的規格大小、儲存型別、網路頻寬、自動擴縮容問題,無需再對伺服器進行運維、不斷打系統補丁和應用補丁、無需進行資料備份等工作。一切非核心業務都外包給了公共雲營運商,讓開發人員從複雜的部署和運維環境中脫身出來,專注於業務本身的價值。
用 Zappa 裡的一句話說就是 **“without any permanent infrastructure”**(無需任何永久性基礎設施)。
敲黑板,儘管從名字上說是 Serverless,但是仍然需要物理伺服器,只是我們開發人員成了甩手掌櫃。
#### 1.1.2 好處有?
- 降低運維需求和維護成本;
- 完全自動化的彈性擴容和縮容:在業務高峰期時,產品的計算能力和容量自動擴大,承載更多的使用者請求;反之,在業務下降時,所使用的資源也會同時收縮,避免資源浪費;
- 節省開支,全新的計量計費模式:開發者僅需根據使用量來付費。在無業務量的情況下,不會有空閒資源佔用,也不會有費用產生。
#### 1.1.3 普遍認為 Serverless = FaaS + BaaS
- BaaS(Backedn as a Service 後端即服務)
- 後端,指的就是各種雲產品和雲服務,例如物件儲存 OS ,訊息佇列 MQ,雲資料庫 DB,雲快取 Redis以及各種以 API 形式提供的服務。使用者直接開通即可使用,無需考慮部署、擴容、備份、安全等各種運維工作。
- FaaS(Functions as a Service 函式即服務)
- 是 Serverless 的核心,讓使用者僅需編寫和上傳核心業務程式碼,交由平臺完成部署、排程、流量分發和彈性伸縮等能力,它提供了一種新的方式來提供計算資源,進一步降低雲端計算的使用門檻。
#### 1.1.4 AWS Lambda
在該專案中,伸手白嫖[ AWS 海外區域賬戶免費 AWS Lambda 套餐](https://amazonaws-china.com/cn/free/?cs-awsft-actsft&sc_channel=ta&sc_campaign=freetier_crosslink&sc_country=cn&sc_geo=chna&sc_category=mult&sc_outcome=acq&trkCampaign=freetier_crosslink_acts&trk=request_for_pilot_account&all-free-tier.sort-by=item.additionalFields.SortRank&all-free-tier.sort-order=asc)。[AWS Lambda](https://amazonaws-china.com/cn/lambda/?did=ft_card&trk=ft_card) 作為 Serverless 最早的框架產品由亞馬遜在2014年推出,是一種無伺服器的計算服務,無需預置或管理伺服器即可執行程式碼。Lambda 幾乎可以為任何型別的應用程式或後端服務執行程式碼,我們只需上傳相應的程式碼,它會處理執行和擴充套件程式碼所需的一切工作。
![](https://img2020.cnblogs.com/blog/759200/202103/759200-20210307162636374-1812230031.png)
### 1.2 Python 的 Serverless 框架
本篇文章的主角:Zappa 登場!我們可以通過 Zappa 工具體驗一下 Serverless 技術,用它實現我們 Python 應用程式的無伺服器部署,初步體驗無限伸縮擴充套件、零宕機、零維護的快捷。有了 Zappa,我們無需:
- **配置** Web 伺服器
- **付費** 24/7 伺服器的正常執行時間
- **擔心**負載平衡和可擴充套件性
- **保持**自己的伺服器時刻線上狀態
## 二、親自動手
實戰時間:已經實驗(踩坑)成功(不斷)的我就來分享部署一個簡單的 `Flask` 應用的過程,不要擔心跟著做你也可以~
### 2.1 環境
1. Python版本要求:3.6/3.7/3.8
2. 測試系統:Ubuntu 18.04.4 LTS
### 2.2 準備
1. **保證**自己的專案是執行在[虛擬環境](https://docs.python-guide.org/dev/virtualenvs/)下。
```bash
# 需要安裝 Python 3.x 版本
python --version
# 安裝 Pipenv
pip install --user pipenv
# 進入自己的專案
cd demo
# 例項化 pipfile 和 venv
pipenv shell
```
![](https://img2020.cnblogs.com/blog/759200/202103/759200-20210307162655264-2050329917.png)
2. **安裝** Zappa 和 Flask,專案需要其他庫的話,可自行新增。
```bash
$ pipenv install zappa flask
```
![](https://img2020.cnblogs.com/blog/759200/202103/759200-20210307162711544-1362294982.png)
3. 在目錄下建立 `my_app.py` 檔案,寫入官方樣例,可以先 `pipenv run python my_app.py`看看是否能正常執行
```python
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello():
return "hello, from Zappa!\n"
if __name__ == '__main__':
app.run()
```
4. [註冊 AWS 賬戶](https://portal.aws.amazon.com/gp/aws/developer/registration/index.html?nc2=h_ct&src=default),並且正確安裝 AWS credentials file
- 登入 AWS,找到 `My Security Credentials` 下的 `Access keys (access key ID and secret access key)` ,如果沒有則建立一個,記住 `access key ID` 和 `secret access key`
- 安裝 AWS 的命令列介面,新增 credentials
```bash
# 在虛擬環境下安裝
pipenv install awscli
# 檢視資訊
aws configure list
# 新增,並且按照提示將 access key ID 和 secret access key 填入
aws configure
# 後兩個 region name 和 output format 選填
```
![](https://img2020.cnblogs.com/blog/759200/202103/759200-20210307162746338-1692138123.png)
- 此時在 `~/.aws` 目錄下會出現兩個檔案 config 和 credentials,credentials 中儲存了 AWS 的 ` access key ID` 和 `secret access key`, config 中儲存了 region name 和 output format 資訊。
- 如果是在 Windows 上操作的同學,可以檢視官方提供的安裝 AWS credentials file 的[教程](https://amazonaws-china.com/cn/blogs/security/a-new-and-standardized-way-to-manage-credentials-in-the-aws-sdks/)。
### 2.3 安裝與配置
1. 通過執行下面語句進行初始化,定義部署和配置的設定,自動檢測應用型別(Flask 或 Django)
```bash
$ zappa init
```
在執行過程中,可能需要如下設定,後續也可以在新生成的 `zappa_setting.json` 的配置檔案中修改:
![](https://img2020.cnblogs.com/blog/759200/202103/759200-20210307162807862-2028465910.png)
完成後,我們的專案目錄中將有一個 `zappa_settings.json` 檔案,裡面是我們剛剛定義的基本部署設定,後期我們可以按照自己的需求修改此檔案。
```json
{
"dev": {
"app_function": "my_app.app",
"profile_name": null,
"project_name": "demo",
"runtime": "python3.6",
"s3_bucket": "zappa-ti0ra29xi"
}
}
```
2. 注意如果之前已經在 `~/.aws/config` 檔案中新增 region 資訊,則會在 `zappa init` 的時候自動尋找到這些 region 資訊,無需後續修改。
如果之前沒有新增,則修改 `zappa_settings.json`,新增 region 資訊如下:
```bash
# 修改如下
{
"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 的資訊可以自行選擇,[具體資訊請移步](https://docs.aws.amazon.com/zh_cn/general/latest/gr/rande.html)。
### 2.4 部署和使用
配置設定後,可以使用如下命令將應用程式打包並部署:
```bash
$ zappa deploy dev
```
當我們呼叫 deploy 時,Zappa 會自動將我們的應用程式和本地虛擬環境打包到 Lambda 相容的 archive,用為 Lambda 預先編譯的版本替換所有依賴項,設定功能處理程式和必要的 WSGI 中介軟體,然後上傳 archive 到 S3,建立和管理必要的Amazon IAM 策略和角色,將其註冊為新的 Lambda function,建立新的 API 閘道器資源,為其建立 WSGI 相容的路由,將其連結到新的 Lambda function,最後從 S3 bucket 中刪除 archive。
執行成功後,就會出現一個連結,點選連結即可訪問我們的簡易 Web 應用。看到已上線的應用程式,心內竊喜,直呼快準狠。
![](https://img2020.cnblogs.com/blog/759200/202103/759200-20210307162826915-1967286154.png)
## 三、其他命令
1. 更新操作:假設應用程式已經部署完畢,並且只需要上傳新的Python程式碼,而無需修改基礎路由,則可以執行以下操作:
```bash
$ zappa update dev
```
這將建立一個新的 archive,將其上傳到 S3 並更新 Lambda function 以使用新程式碼。
2. 檢視部署和事件計劃的狀態,只需使用命令:
```bash
$ zappa status production
```
3. 檢視部署的日誌:
```bash
$ zappa tail dev
# 過濾 HTTP 請求
$ zappa tail dev --http
# 執行相反操作,並且僅顯示非 HTTP 事件和日誌訊息
$ zappa tail dev --non-http
# 選擇時長
$ zappa tail dev --since 4h # 4 hours
```
4. 回滾操作: 通過提供要返回的修訂版本數將部署的程式碼回滾到以前的版本。
```bash
# 回滾到3年前部署的版本
$ zappa rollback production -n 3
```
5. 安排 function 定期執行:修改 `zappa_setting.json` ,加入如下內容:
```json
{
"dev": {
...
"events": [{
// The function to execute
"function": "your_module.your_function",
// When to execute it (in cron or rate format)
"expression": "rate(1 minute)"
}],
...
}
}
```
然後執行如下操作,我們的 function 就會在每分鐘執行一次。
```bash
$ zappa schedule dev
# cancal
$ zappa unschedule dev
```
6. 取消部署:如果要刪除以前釋出的 API Gateway 和 Lambda function,則只需:
```bash
$ zappa unschedule dev
```
## 四、踩坑建議
在成功執行一次之前,踩坑千千萬萬遍,都是因為自己手殘眼瞎魔改了很多地方,把經歷過的報錯記錄下來,分享給和我一樣的小小白。
1. `“Unable to import module ‘handler’: attempted relative import with no known parent package”`:原因是我們期望的依賴在虛擬的環境中沒有,需要檢視自己虛擬環境中的依賴是否完整,[解決請移步](https://medium.com/@gregorypierce/unable-to-import-module-handler-attempted-relative-import-with-no-known-parent-package-f3545ab91df1)。
2. 出現如下報錯,可以更換一個 region 資訊,[解決請移步](https://github.com/Miserlou/Zappa/issues/1194)。
```bash
$ 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
```
3. 如果我們在 `zappa init` 的時候,不使用預設分配的 `s3_bucket` ,則須注意自己的名稱是不允許重名的,點選檢視[官方方法](https://amazonaws-china.com/cn/premiumsupport/knowledge-center/s3-error-bucket-already-exists/),否則會報錯 `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 的服務,咱的應用程式就輕巧上線了呢,還不趕緊把生成的連結分享給小夥伴們點選一下。
至此,我們已經可以基本實現快速部署一個簡單的 Flask 應用了,由於篇幅有限,還有部分 Zappa 的高階功能沒有提及,以及如何使用 Zappa 部署 Django 應用或者一個更為龐大的專案(包含資料庫等),希望感興趣的小夥伴們能夠多多嘗試,我已經開始期待的搓搓手了。如果大家對開源專案感興趣,請第一時間關注 HelloGitHub,我們將會為大家帶來更多有趣的乾貨