本文介紹如何使用 Nginx、uWSGI、Gunicorn、Supervisor 和 Tornado 等工具佈署 Flask 應用程式,並詳細說明設定步驟與注意事項。同時,也涵蓋了利用 Amazon S3 進行檔案儲存、使用 New Relic 和 Datadog 監控應用程式效能,以及透過 Docker 和 Kubernetes 容器化和協調應用程式的方法,提供全面的佈署和效能最佳化。最後,文章也觸及了微服務架構的概念,並介紹瞭如何使用 GitHub Actions 實作持續佈署。

使用 Nginx 和 uWSGI 佈署 Flask 應用程式

在佈署 Flask 應用程式時,Nginx 和 uWSGI 是常見的選擇。Nginx 是一個高效的反向代理伺服器,而 uWSGI 則是一個 WSGI 伺服器,能夠與 Nginx 協同工作,提供高效的應用程式佈署。

設定 Nginx 和 uWSGI

首先,我們需要建立一個新的檔案 nginx-wsgi.conf,用於存放 Nginx 的設定內容:

server {
    location / {
        include uwsgi_params;
        uwsgi_pass 0.0.0.0:9090;
    }
    location /static/uploads/ {
        alias /home/ubuntu/cookbook3/Chapter-11/flask_test_uploads/;
    }
}

在上述設定中,uwsgi_pass 指定了 uWSGI 伺服器的位址和埠號。

內容解密:

  1. server 區塊定義了 Nginx 的虛擬伺服器設定。
  2. location / 區塊定義了根 URL 的處理方式,包括引入 uwsgi_params 檔案和將請求轉發到 0.0.0.0:9090 的 uWSGI 伺服器。
  3. location /static/uploads/ 區塊定義了靜態檔案的處理方式,將 /static/uploads/ 路徑的請求對映到 /home/ubuntu/cookbook3/Chapter-11/flask_test_uploads/ 目錄。

建立軟連結和重新載入 Nginx

接下來,我們需要建立一個軟連結,將 nginx-wsgi.conf 檔案連結到 /etc/nginx/sites-enabled/ 目錄下:

$ sudo ln -s ~/cookbook3/Chapter-11/nginx-wsgi.conf /etc/nginx/sites-enabled/

然後,取消預設的 Nginx 設定:

$ sudo unlink /etc/nginx/sites-enabled/default

最後,重新載入 Nginx 伺服器:

$ sudo systemctl reload nginx.service

使用 Gunicorn 和 Supervisor 佈署

Gunicorn 是一個簡單易用的 WSGI HTTP 伺服器,而 Supervisor 則是一個用於監控和管理子程式的工具。

安裝 Gunicorn 和 Supervisor

首先,我們需要安裝 Gunicorn 和 Supervisor:

$ pip install gunicorn
$ pip install supervisor

設定 Gunicorn 和 Supervisor

接下來,我們需要建立一個 Supervisor 設定檔:

$ mkdir etc
$ echo_supervisord_conf > etc/supervisord.conf

然後,在 supervisord.conf 檔案中新增以下設定:

[program:flask_catalog]
command=<path to virtual environment>/bin/gunicorn -w 4 -b 0.0.0.0:8000 my_app:app
directory=<path to application directory>
user=someuser
autostart=true
autorestart=true
stdout_logfile=/tmp/app.log
stderr_logfile=/tmp/error.log

內容解密:

  1. [program:flask_catalog] 定義了一個名為 flask_catalog 的程式。
  2. command 指定了要執行的命令,包括 Gunicorn 的路徑和引數。
  3. directory 指定了應用程式的目錄。
  4. user 指定了執行程式的使用者。
  5. autostartautorestart 指定了程式的啟動和重啟行為。
  6. stdout_logfilestderr_logfile 指定了標準輸出和錯誤輸出的日誌檔案。

使用 Tornado 佈署

Tornado 是一個完整的 Web 框架和獨立的 Web 伺服器。在這裡,我們將使用 Flask 建立應用程式,並使用 Tornado 作為伺服器。

Tornado 能夠支援數千個同時連線,使得應用程式具有很高的可擴充套件性。

使用 Tornado 佈署 Flask 應用程式

Tornado 是一個強大的 Python 網路框架和非同步網路函式庫,可以用來佈署 WSGI 應用程式,如 Flask。雖然 Tornado 有一些限制,但它仍然是一個很好的選擇。

安裝 Tornado

要使用 Tornado,首先需要安裝它。可以使用 pip 進行安裝:

$ pip install tornado

建立 Tornado 伺服器

建立一個名為 tornado_server.py 的檔案,並在其中加入以下程式碼:

from tornado.wsgi import WSGIContainer
from tornado.httpserver import HTTPServer
from tornado.ioloop import IOLoop
from my_app import app

http_server = HTTPServer(WSGIContainer(app))
http_server.listen(8000)
IOLoop.instance().start()

程式碼解密:

  1. 匯入必要的模組:從 Tornado 匯入 WSGIContainerHTTPServerIOLoop,並從 my_app 匯入 Flask 應用程式例項 app
  2. 建立 WSGI 容器:使用 WSGIContainer 包裝 Flask 應用程式,使其能夠在 Tornado 上執行。
  3. 建立 HTTP 伺服器:使用 HTTPServer 建立一個 HTTP 伺服器,並將 WSGI 容器傳遞給它。
  4. 監聽埠:使用 listen 方法指定伺服器要監聽的埠(在此例中為 8000)。
  5. 啟動事件迴圈:使用 IOLoop.instance().start() 啟動 Tornado 的事件迴圈,使伺服器開始接受請求。

執行 Tornado 伺服器

執行 tornado_server.py 檔案:

$ python tornado_server.py

然後,在瀏覽器中存取 http://0.0.0.0:8000/http://<IP 地址或網域名稱>:8000/,即可看到 Flask 應用程式的首頁。

結合 Nginx 和 Supervisor

為了獲得最佳效能,可以將 Tornado 與 Nginx(作為反向代理伺服器)和 Supervisor(作為行程管理器)結合使用。

使用 S3 儲存檔案上傳

Amazon S3 是一種物件儲存服務,可以用來儲存和檢索大量的資料。在本文中,我們將修改現有的 Flask 應用程式,以使用 S3 儲存檔案上傳。

安裝 boto3

首先,需要安裝 boto3,這是一個 Python 函式庫,用於與 AWS 服務互動:

$ pip install boto3

修改應用程式組態

my_app/__init__.py 中加入以下組態:

app.config['AWS_ACCESS_KEY'] = 'AWS 存取金鑰'
app.config['AWS_SECRET_KEY'] = 'AWS 私密金鑰'
app.config['AWS_BUCKET'] = 'AWS Bucket 名稱'

程式碼解密:

  1. 設定 AWS 存取金鑰和私密金鑰:用於驗證與 AWS 的連線。
  2. 設定 AWS Bucket 名稱:指定用於儲存檔案的 S3 Bucket。

修改 views.py

views.py 中,修改 create_product 方法,以使用 S3 儲存檔案上傳:

import boto3

# ...

session = boto3.Session(
    aws_access_key_id=current_app.config['AWS_ACCESS_KEY'],
    aws_secret_access_key=current_app.config['AWS_SECRET_KEY']
)
s3 = session.resource('s3')
bucket = s3.Bucket(current_app.config['AWS_BUCKET'])

if bucket not in list(s3.buckets.all()):
    bucket = s3.create_bucket(
        Bucket=current_app.config['AWS_BUCKET'],
        CreateBucketConfiguration={
            'LocationConstraint': 'ap-south-1'
        },
    )

bucket.upload_fileobj(
    image, filename,
    ExtraArgs={'ACL': 'public-read'}
)

程式碼解密:

  1. 建立 boto3 Session:使用 AWS 存取金鑰和私密金鑰建立與 AWS 的連線。
  2. 取得 S3 資源:使用 Session 物件取得 S3 資源。
  3. 檢查 Bucket 是否存在:檢查指定的 Bucket 是否存在,如果不存在則建立它。
  4. 上傳檔案到 S3:將檔案上傳到 S3 Bucket 中,並設定 ACL 為公開讀取。

修改 product.html

product.html 中,修改圖片的 src 路徑,以使用 S3 儲存的圖片:

<img src="{{ 'https://s3.ap-south-1.amazonaws.com/' + config['AWS_BUCKET'] + '/' + product.image_path }}"/>

使用 New Relic 管理和監控應用程式效能

New Relic 是一種應用程式效能監控工具,可以用來監控和分析 Flask 應用程式的效能。

建立 New Relic 帳戶

首先,需要建立一個 New Relic 帳戶,並選擇 Application Monitoring 作為要使用的產品。

安裝 newrelic Python 函式庫

安裝 newrelic Python 函式庫:

$ pip install newrelic

設定 newrelic.ini

使用以下命令產生 newrelic.ini 檔案:

$ newrelic-admin generate-config <LICENSE-KEY> newrelic.ini

程式碼解密:

  1. 產生 newrelic.ini 檔案:使用 New Relic 的授權金鑰產生 newrelic.ini 檔案。
  2. 設定應用程式名稱:在 newrelic.ini 檔案中設定應用程式的名稱。

初始化 New Relic

my_app/__init__.py 中,加入以下程式碼,以初始化 New Relic:

import newrelic.agent
newrelic.agent.initialize('newrelic.ini')

程式碼解密:

  1. 匯入 newrelic.agent:匯入 New Relic 的 agent 模組。
  2. 初始化 New Relic:使用 newrelic.ini 檔案初始化 New Relic agent。

檢視 New Relic 資料

執行 Flask 應用程式後,即可在 New Relic 的儀錶板中檢視應用程式的效能資料。

使用 Datadog 進行基礎設施和應用程式監控

Datadog 是一個可觀測性服務,提供對基礎設施、資料函式庫、應用程式和服務的詳細分析。與 New Relic 類別似,Datadog 是一個全端式平台,允許全方位監控,提供對應用程式和基礎設施健康狀態的深入洞察。

雖然 Datadog 和 New Relic 在幾乎所有方面都很相似,但它們各自具有一些優勢。例如,一種流行的觀點認為,New Relic 在應用程式效能監控(APM)方面表現出色,而 Datadog 在基礎設施監控方面更強大。

簡而言之,這兩個平台都非常適合大多數用途,您可以根據自己的需求選擇使用其中之一或其他工具/平台。

準備工作

就像前面的配方一樣,我們將使用在本文中建立的目錄應用程式。基本上,這裡使用的應用程式並不重要;它應該只是一個正在執行的 Flask 應用程式。

第一步是在 Datadog 上建立一個新帳戶。他們有一個免費層,足以進行測試,就像我們的案例一樣。註冊並登入後,第一步是在 Datadog 控制檯中啟用/安裝 Python 整合:

在上述螢幕截圖中,點選 Python 圖塊並安裝整合。

操作步驟

請按照以下步驟設定使用 Datadog 進行基礎設施和應用程式監控:

  1. 取得 API 金鑰後,下一步是在您的作業系統上安裝 Datadog 代理程式,以允許基礎設施監控。按照您的 OS 或基礎設施的指示,導航到 Integrations | Agent:

如上圖所示,選擇您的 OS 並按照指示進行操作。您的 OS 可能會要求一些許可權,您需要授予這些許可權才能使 Datadog 正常運作。

  1. 安裝代理程式後,導航到 Infrastructure | Infrastructure List 以驗證您的基礎設施是否正在被監控:

您可以隨意探索其他選項或深入瞭解這裡的詳細資訊,以檢視更多分析結果。

  1. 下一步是安裝 ddtrace 工具,這是 Datadog 的 Python APM 使用者端,允許您將程式碼、請求和追蹤資料的效能分析傳送到 Datadog:
$ pip install ddtrace

重要

如果您的應用程式正在執行在連線埠 5000 上,請確保將連線埠更改為其他連線埠 – 連線埠 5000 至 5002 被 Datadog 用於其代理程式和其他實用工具。

  1. 安裝 ddtrace 後,使用以下命令執行您的 Flask 應用程式:
$ DD_SERVICE="<您的服務名稱>" DD_ENV="<您的環境名稱>" ddtrace-run python run.py

注意 DD_SERVICEDD_ENV 環境變數。這些對於 Datadog 決定如何區分和分組您的應用程式日誌非常重要。

如果出現錯誤,如下圖所示,只需設定 DD_REMOTE_CONFIGURATION_ENABLED=false

因此,在我的案例中,命令如下所示:

$ DD_SERVICE="flask-cookbook" DD_ENV="stage" DD_REMOTE_CONFIGURATION_ENABLED=false ddtrace-run python run.py
  1. 現在,只需等待幾分鐘 – 您的應用程式統計資訊應該開始在 Datadog 上反映出來:

您可以隨意操作並深入瞭解更多細節,以瞭解 Datadog 的運作方式以及它提供的統計資訊型別。

相關資源

您可以在以下連結閱讀更多關於 Datadog 和 ddtrace 的資訊:

  • Flask 設定 for ddtrace:https://ddtrace.readthedocs.io/en/stable/integrations.html#flask
  • Datadog 檔案:https://docs.datadoghq.com/

微服務和容器

到目前為止,我們一直在開發完整的應用程式作為一個程式碼區塊(通常稱為單體),它通常被設計、測試和佈署為單個單元。擴充套件也以類別似的方式發生,即要麼整個應用程式被擴充套件,要麼不被擴充套件。然而,隨著應用程式規模的增長,很自然地希望將單體分解為可以單獨管理和擴充套件的較小區塊。微服務是解決這個問題的一種方案。本章將介紹微服務,並探討一些建立和管理微服務的方法。

微服務是一種開發和架構軟體應用程式的方法,將其作為多個鬆散耦合的服務的集合。這些服務被設計和開發,以幫助建立具有清晰和細粒度介面的單一功能模組。如果設計和架構得當,這種模組化的好處是整體應用程式變得更容易理解、開發、維護和測試。多個小型自治團隊可以平行處理多個微服務,因此開發和交付應用程式的時間有效地減少了。每個微服務現在可以單獨佈署和擴充套件,這使得停機時間更少,擴充套件更具成本效益,因為只有高流量服務可以根據預定義的標準進行擴充套件。其他服務可以照常執行。

本章將從一些常見的術語開始,這些術語在討論微服務時經常被提及 – 即容器和 Docker。首先,我們將瞭解如何使用 Docker 容器佈署 Flask 應用程式。然後,我們將瞭解如何使用 Kubernetes(最好的容器協調工具之一)有效地擴充套件和管理多個容器。然後,我們將瞭解如何使用一些雲端平台(如 AWS Lambda 和 GCP Cloud Run)建立完全託管的微服務。最後,我們將瞭解如何使用 GitHub Actions 將所有內容整合到一個無縫的佈署管道中。

在本章中,我們將涵蓋以下配方:

  • 使用 Docker 進行容器化
  • 使用 Kubernetes 協調容器
  • 使用 Google Cloud Run 無伺服器佈署
  • 使用 GitHub Actions 進行持續佈署