利用負載平衡進行容量管理

Last reviewed 2018-01-18 UTC

大多數的負載平衡器都使用循環配置演算法,或以流量為基礎的雜湊演算法來分配流量。使用這兩種演算法的負載平衡器,在遇到尖峰需求超過可用服務容量的情況時卻很難應變。這個教學課程說明 Cloud Load Balancing 如何最佳化您的全域應用程式容量,這種做法與大部分負載平衡實作方法相比,更能提供優質的使用者體驗且為您省下更多費用。

本文是 Cloud Load Balancing 產品最佳做法系列指南的一部分。這個教學課程隨附利用全域負載平衡進行應用程式容量最佳化的概念文章,詳細說明全域負載平衡溢流的基礎機制。如要深入瞭解延遲時間,請參閱利用 Cloud Load Balancing 最佳化應用程式的延遲時間一文。

本教學課程假設您曾經使用過 Compute Engine。您也應該熟悉外部應用程式負載平衡器基礎知識

目標

在這個教學課程中,您會設定簡易網路伺服器,並在該伺服器執行用來計算 Mandelbrot 集的 CPU 密集型應用程式。首先,您將使用負載測試工具 (siegehttperf) 測量網路負載能力。接下來,您可以在單一區域中調度多個 VM 執行個體的網路資源,並測量工作負載情況下的回應時間。最後,您會使用全域負載平衡來調度多個地區的網路資源,然後測量伺服器在工作負載情況下的回應時間,再將其結果與單一地區負載平衡進行比較。執行這一系列測試可讓您看到 Cloud Load Balancing 跨區域負載管理的正面效果。

當您採用典型的三層網路伺服器架構,不是網路伺服器上的 CPU 負載時,通常網路通訊速度會受到應用程式伺服器速度或資料庫容量的限制。完成教學課程的瀏覽之後,您可以使用相同的負載測試工具和容量設定,將實際運作應用程式的負載平衡行為最佳化。

您將學會以下內容:

  • 瞭解如何使用負載測試工具 (siegehttperf)。
  • 決定單一 VM 執行個體的服務規模。
  • 使用單一地區負載平衡,測量超載效果。
  • 使用全域負載平衡,測量溢流到其他地區的效果。

費用

本教學課程使用 Google Cloud的計費元件,包括:

  • Compute Engine
  • 負載平衡和轉寄規則

使用 Pricing Calculator 可根據您的預測使用量來產生費用預估。

事前準備

  1. 在 Google Cloud 控制台的專案選擇器頁面中,選取或建立 Google Cloud 專案。

    選取或建立專案所需的角色

    • 選取專案:選取專案時,不需要具備特定 IAM 角色,只要您已獲授角色,即可選取任何專案。
    • 建立專案:如要建立專案,您需要具備專案建立者角色 (roles/resourcemanager.projectCreator),其中包含 resourcemanager.projects.create 權限。瞭解如何授予角色

    前往專案選取器

  2. 確認專案已啟用計費功能 Google Cloud

  3. 啟用 Compute Engine API。

    啟用 API 時所需的角色

    如要啟用 API,您需要服務使用情形管理員 IAM 角色 (roles/serviceusage.serviceUsageAdmin),其中包含 serviceusage.services.enable 權限。瞭解如何授予角色

    啟用 API

設定環境

在本節中,您會進行專案、虛擬私人雲端網路和基本防火牆規則所需的設定,以便完成教學課程。

啟動 Cloud Shell 執行個體

Google Cloud 控制台開啟 Cloud Shell。除非另有註明,否則您可以從 Cloud Shell 內部執行教學課程中的其他部分。

配置專案設定

如要更簡便地執行 gcloud 指令,您可以設定屬性,這樣就不需要在每個指令中提供這些屬性的選項。

  1. 設定您的預設專案,請將 [PROJECT_ID] 替換為您的專案 ID。

    gcloud config set project [PROJECT_ID]
  2. 設定預設 Compute Engine 區域,請將 [ZONE] 替換為您偏好的區域。接著將這個區域設為環境變數,以供稍後使用。

    gcloud config set compute/zone [ZONE]
    export ZONE=[ZONE]

建立及設定虛擬私人雲端網路

  1. 建立測試用的虛擬私人雲端網路:

    gcloud compute networks create lb-testing --subnet-mode auto
  2. 定義允許內部流量的防火牆規則:

    gcloud compute firewall-rules create lb-testing-internal \
        --network lb-testing --allow all --source-ranges 10.128.0.0/11
  3. 定義允許 SSH 流量的防火牆規則,以便與虛擬私人雲端網路進行通訊。

    gcloud compute firewall-rules create lb-testing-ssh \
        --network lb-testing --allow tcp:22 --source-ranges 0.0.0.0/0

決定單一 VM 執行個體的服務規模

如要檢查 VM 執行個體類型的效能特性,您可以執行以下操作:

  1. 設定可提供工作負載範例的 VM 執行個體 (網路伺服器執行個體)。

  2. 在相同的區域建立第二個 VM 執行個體 (負載測試執行個體)。

您可以透過第二個 VM 執行個體,使用簡易負載測試與效能測量工具來評估成效。您日後會在教學課程中使用這些測量數據,協助執行個體群組定義正確的負載平衡容量設定。

第一個 VM 執行個體會使用 Python 指令碼,透過在每個傳到根 (/) 路徑的要求上計算並顯示 Mandelbrot 集圖片,來建立會耗用大量 CPU 資源的工作。系統無法快取結果。您會在教學課程期間從這個解決方案所使用的 GitHub 存放區中取得 Python 指令碼。

測試網路伺服器回應的雙伺服器設定

設定 VM 執行個體

  1. 您需要安裝並啟動 Mandelbrot 伺服器,才能將 webserver VM 執行個體設為 4 核心 VM 執行個體。

    gcloud compute instances create webserver --machine-type n1-highcpu-4 \
        --network=lb-testing --image-family=debian-12 \
        --image-project=debian-cloud --tags=http-server \
        --metadata startup-script='#! /bin/bash
    apt-get -y update
    apt-get install -y git python-numpy python-matplotlib
        git clone \
    https://github.com/GoogleCloudPlatform/lb-app-capacity-tutorial-python.git
        cd lb-app-capacity-tutorial-python
    python webserver.py' 
  2. 建立防火牆規則,允許自己的機器從外部存取執行個體:webserver

    gcloud compute firewall-rules create lb-testing-http \
        --network lb-testing --allow tcp:80 --source-ranges 0.0.0.0/0 \
        --target-tags http-server 
  3. 取得 webserver 執行個體的 IP 位址:

    gcloud compute instances describe webserver \
        --format "value(networkInterfaces[0].accessConfigs[0].natIP)"
    
  4. 在網路瀏覽器中,前往前一個指令傳回的 IP 位址。 畫面上會顯示經過運算的 Mandelbrot 集:

    瀏覽器螢幕擷取畫面顯示轉譯的 Mandelbrot 集

  5. 建立負載測試執行個體:

    gcloud compute instances create loadtest --machine-type n1-standard-1 \
        --network=lb-testing --image-family=debian-12 \
        --image-project=debian-cloud
    

測試 VM 執行個體

下一步是執行要求,以評估負載測試 VM 執行個體的效能特性。

  1. 使用 ssh 指令連線至負載測試 VM 執行個體:

    gcloud compute ssh loadtest
  2. 在負載測試執行個體上,安裝 siegehttperf 做為負載測試工具:

    sudo apt-get install -y siege httperf

    siege 工具能讓模擬指定數量的使用者所發出的要求,並且僅在使用者收到回應後,才會發出後續要求。這項工具可協助您深入瞭解,實際運作環境中應用程式的容量和預估回應時間。

    httperf 工具可讓您每秒傳送特定數量的要求,不論收到的是回應或是錯誤。這項工具可協助您深入瞭解應用程式如何回應特定工作負載。

  3. 為傳送至網路伺服器的簡易要求計時:

    curl -w "%{time_total}\n" -o /dev/#objectives_2 -s webserver

    您會得到類似 0.395260 的回應。這表示伺服器花了 395 毫秒 (ms) 來回應您的要求。

  4. 使用下列指令來並行執行來自 4 位使用者的 20 個要求:

    siege -c 4 -r 20 webserver

    畫面會顯示類似以下內容的輸出:

    ** SIEGE 4.0.2
    ** Preparing 4 concurrent users for battle.
    The server is now under siege...
    Transactions:                    80 hits
    Availability:                 100.00 %
    Elapsed time:                  14.45 secs
    Data transferred:               1.81 MB
    Response time:                  0.52 secs
    Transaction rate:               5.05 trans/sec
    Throughput:                     0.12 MB/sec
    Concurrency:                    3.92
    Successful transactions:         80
    Failed transactions:               0
    **Longest transaction:            0.70
    Shortest transaction:           0.37
    **
    

    輸出內容會在 Siege 使用手冊中完整說明,但您應該會看到,在這個範例中回應時間是介於 0.37 秒到 0.7 秒之間。一般來說,系統每秒會回應 5.05 個要求。這項資料能夠協助預估系統的服務規模。

  5. 請使用 httperf 負載測試工具,執行下列指令來驗證發現項目:

    httperf --server webserver --num-conns 500 --rate 4

    這個指令可以每秒 4 個要求的速度執行 500 個要求,siege 所完成的是每秒回應 5.05 筆交易資料。

    畫面會顯示類似以下內容的輸出:

    httperf --client=0/1 --server=webserver --port=80 --uri=/ --rate=4
    --send-buffer=4096 --recv-buffer=16384 --num-conns=500 --num-calls=1
    httperf: warning: open file limit > FD_SETSIZE; limiting max. # of open files to
    FD_SETSIZE
    Maximum connect burst length: 1
    
    Total: connections 500 requests 500 replies 500 test-duration 125.333 s
    
    Connection rate: 4.0 conn/s (251.4 ms/conn, <=2 concurrent connections)
    **Connection time [ms]: min 369.6 avg 384.5 max 487.8 median 377.5 stddev 18.0
    Connection time [ms]: connect 0.3**
    Connection length [replies/conn]: 1.000
    
    Request rate: 4.0 req/s (251.4 ms/req)
    Request size [B]: 62.0
    
    Reply rate [replies/s]: min 3.8 avg 4.0 max 4.0 stddev 0.1 (5 samples)
    Reply time [ms]: response 383.8 transfer 0.4
    Reply size [B]: header 117.0 content 24051.0 footer 0.0 (total 24168.0)
    Reply status: 1xx=0 2xx=100 3xx=0 4xx=0 5xx=0
    
    CPU time [s]: user 4.94 system 20.19 (user 19.6% system 80.3% total 99.9%)
    Net I/O: 94.1 KB/s (0.8*10^6 bps)
    
    Errors: total 0 client-timo 0 socket-timo 0 connrefused 0 connreset 0
    Errors: fd-unavail 0 addrunavail 0 ftab-full 0 other 0
    

    輸出內容會在 httperf README 檔案中說明。請留意以 Connection time [ms] 為開頭的那一行,該行說明總計的連線時間是介於 369.6 毫秒和 487.8 毫秒之間,而且完全沒有產生錯誤。

  6. 重複 3 次測試,將 rate 選項分別設為每秒 5 個、7 個和 10 個要求。

    下列區塊顯示 httperf 指令和其輸出內容 (只顯示相關的行與當中的連線時間資訊)。

    每秒 5 個要求的指令:

    httperf --server webserver --num-conns 500 --rate 5 2>&1| grep 'Errors\|ion time'
    

    每秒 5 個要求的結果:

    Connection time [ms]: min 371.2 avg 381.1 max 447.7 median 378.5 stddev 7.2
    Connection time [ms]: connect 0.2
    Errors: total 0 client-timo 0 socket-timo 0 connrefused 0 connreset 0
    Errors: fd-unavail 0 addrunavail 0 ftab-full 0 other 0
    

    每秒 7 個要求的指令:

    httperf --server webserver --num-conns 500 --rate 7 2>&1| grep 'Errors\|ion time'
    

    每秒 7 個要求的結果:

    Connection time [ms]: min 373.4 avg 11075.5 max 60100.6 median 8481.5 stddev
    10284.2
    Connection time [ms]: connect 654.9
    Errors: total 4 client-timo 0 socket-timo 0 connrefused 0 connreset 4
    Errors: fd-unavail 0 addrunavail 0 ftab-full 0 other 0
    

    每秒 10 個要求的指令:

    httperf --server webserver --num-conns 500 --rate 10 2>&1| grep 'Errors\|ion time'
    

    每秒 10 個要求的結果:

    Connection time [ms]: min 374.3 avg 18335.6 max 65533.9 median 10052.5 stddev
    16654.5
    Connection time [ms]: connect 181.3
    Errors: total 32 client-timo 0 socket-timo 0 connrefused 0 connreset 32
    Errors: fd-unavail 0 addrunavail 0 ftab-full 0 other 0
    
  7. 登出 webserver 執行個體:

    exit

您可以從這些測量數據斷定,系統每秒能夠回應大約 5 個要求 (RPS)。和 4 個連線時間相比,VM 執行個體在每秒 5 個要求的速度下,會以延遲時間應對。每秒 7 個和 10 個連線的情況下,平均回應時間大幅增加到超過 10 秒鐘,而且出現多個連線錯誤。換言之,只要每秒超過 5 個要求,要求的回應速度便會大幅變慢。

在更為複雜的系統中,伺服器容量也是以類似的方式決定,但絕大部分是取決於所有的元件。您可以使用 siegehttperf 工具,再加上 CPU 和 I/O 工作負載來監控所有元件 (例如,前端伺服器、應用程式伺服器和資料庫伺服器等),以協助找出瓶頸。因此,這樣的做法會協助每個元件以最佳方式調度資源。

使用單一地區負載平衡器測量超載效果

在本節中,您將在單一地區負載平衡器上 (例如內部部署使用的典型負載平衡器,或是 Google Cloud 外部直通式網路負載平衡器) 檢查超載效果。當負載平衡器是用於地區部署(而非全域部署) 時,您也可以透過 HTTP (S) 負載平衡器來觀察這個效果。

在單一區域地區部署中的負載平衡器設定

建立單一地區 HTTP(S) 負載平衡器

下列步驟說明如何透過 3 個固定大小的 VM 執行個體,建立單一地區 HTTP(S) 負載平衡器。

  1. 透過您先前使用的 Python Mandelbrot 產生指令碼,建立針對網路伺服器 VM 執行個體的執行個體範本。在 Cloud Shell 中執行下列指令:

    gcloud compute instance-templates create webservers \
        --machine-type n1-highcpu-4 \
        --image-family=debian-12 --image-project=debian-cloud \
        --tags=http-server \
        --network=lb-testing \
        --metadata startup-script='#! /bin/bash
    apt-get -y update
    apt-get install -y git python-numpy python-matplotlib
    git clone \
        https://github.com/GoogleCloudPlatform/lb-app-capacity-tutorial-python.git
    cd lb-app-capacity-tutorial-python
    python webserver.py'
  2. 依據上一個步驟中的範本,使用 3 個執行個體,建立代管執行個體群組。

    gcloud compute instance-groups managed create webserver-region1 \
        --size=3 --template=webservers
    
  3. 建立您所需的健康狀態檢查、後端服務、網址對應、目標 Proxy 和通用轉送規則,以便產生 HTTP(S) 負載平衡

    gcloud compute health-checks create http basic-check \
        --request-path="/health-check" --check-interval=60s
    
    gcloud compute backend-services create web-service \
        --health-checks basic-check --global
    gcloud compute backend-services add-backend web-service \
        --global --instance-group=webserver-region1 \
        --instance-group-zone $ZONE
    
    gcloud compute url-maps create web-map --default-service web-service
    
    gcloud compute target-http-proxies create web-proxy --url-map web-map
    
    gcloud compute forwarding-rules create web-rule --global \
        --target-http-proxy web-proxy --ports 80
    
  4. 取得轉送規則的 IP 位址:

    gcloud compute forwarding-rules describe --global web-rule --format "value(IPAddress)"

    輸出您建立的負載平衡器公開 IP 位址。

  5. 在瀏覽器中前往先前指令傳回的 IP 位址。等待幾分鐘後,畫面上會顯示您先前所看到的相同 Mandelbrot 圖片。不過,這次的映像檔是從新建立群組中的其中一個 VM 執行個體所提供。

  6. 登入 loadtest 機器:

    gcloud compute ssh loadtest
  7. 以每秒可回應的不同要求數 (RPS),在 loadtest 機器的指令列上測試伺服器回應。請確認您所使用的 RPS 值至少是 5 到 20 的範圍。

    舉例來說,下列指令會產生 RPS 10。將 [IP_address] 替換為這個程序先前步驟中的負載平衡器 IP 位址。

    httperf --server [IP_address] --num-conns 500 --rate 10 2>&1| grep 'Errors\|ion time'
    

    隨著 RPS 數量增加到超過 RPS 12 或 13,其回應延遲時間也跟著大幅提高。下列是經過視覺化的常見結果:

    顯示回應時間隨著每分鐘要求數增加而大幅增加的圖形

  8. 登出 loadtest VM 執行個體:

    exit

這樣的效能對地區性負載平衡器系統來說十分常見。由於工作負載增加幅度超過其服務規模,因此導致平均和最大要求延遲時間均急遽增加。在 RPS 為 10 的情況下,平均要求延遲時間已達到 500 毫秒,但在 RPS 為 20 的情況下,則要求延遲時間已來到了 5000 毫秒。延遲時間已增加十倍,而使用者體驗則是迅速惡化,最後導致使用者退出或應用程式逾時,或是兩者同時發生。

在下一節中,您將會新增第二個地區至負載平衡拓撲中,並比較跨地區容錯移轉如何影響使用者的延遲時間。

測量溢流到其他地區的效果

如果您是透過外部應用程式負載平衡器來使用全域應用程式,同時您在多個區域均部署後端,當在單一區域發生容量超載時,流量會自動流入其他區域。您可以將在其他地區的第二個 VM 執行個體群組新增到您在上一節中所建立的設定中,來驗證這個結果。

在多地區部署中的負載平衡器設定

在多個地區建立伺服器

在下列步驟中,您將在其他地區新增另一個後端群組,並在每個地區指派 RPS 10 的容量。您接著可以查看在超過上限時,負載平衡功能會如何反應。

  1. 透過 Cloud Shell 在地區中選擇與預設區域不同的區域,並將該區域設為環境變數:

    export ZONE2=[zone]
  2. 在第二個地區中,建立具有 3 個 VM 執行個體的新執行個體群組:

    gcloud compute instance-groups managed create webserver-region2 \
        --size=3 --template=webservers --zone $ZONE2
    
  3. 將執行個體群組新增到現有的後端服務,同時將最大容量設為 RPS 10:

    gcloud compute backend-services add-backend web-service \
        --global --instance-group=webserver-region2 \
        --instance-group-zone $ZONE2 --max-rate 10
    
  4. 將現有後端服務的 max-rate 調整至 RPS 10:

    gcloud compute backend-services update-backend web-service \
        --global --instance-group=webserver-region1 \
        --instance-group-zone $ZONE --max-rate 10
    
  5. 在所有執行個體啟動後,請登入 loadtest VM 執行個體:

    gcloud compute ssh loadtest
  6. 在 RPS 10 的速度下執行 500 個要求。請將 [IP_address] 替換為負載平衡器的 IP 位址:

    httperf --server [IP_address] --num-conns 500 --rate 10 2>&1| grep 'ion time'
    

    您會看到類似下列的結果:

    Connection time [ms]: min 405.9 avg 584.7 max 1390.4 median 531.5 stddev
    181.3
    Connection time [ms]: connect 1.1
    

    這些結果與地區性負載平衡器所產生的結果類似。

  7. 由於您的測試工具會立即執行完整的工作負載,而且不會如同實際實作一樣,緩慢增加工作負載,因此您需要重複幾次測試,才會讓溢流機制生效。在 RPS 20 的速度下執行 500 個要求 5 次。請將 [IP_address] 替換為負載平衡器的 IP 位址。

    for a in \`seq 1 5\`; do httperf --server [IP_address] \
        --num-conns 500 --rate 20 2>&1| grep 'ion time' ; done
    

    您會看到類似下列的結果:

    Connection time [ms]: min 426.7 avg 6396.8 max 13615.1 median 7351.5 stddev
    3226.8
    Connection time [ms]: connect 0.9
    Connection time [ms]: min 417.2 avg 3782.9 max 7979.5 median 3623.5 stddev
    2479.8
    Connection time [ms]: connect 0.9
    Connection time [ms]: min 411.6 avg 860.0 max 3971.2 median 705.5 stddev 492.9
    Connection time [ms]: connect 0.7
    Connection time [ms]: min 407.3 avg 700.8 max 1927.8 median 667.5 stddev 232.1
    Connection time [ms]: connect 0.7
    Connection time [ms]: min 410.8 avg 701.8 max 1612.3 median 669.5 stddev 209.0
    Connection time [ms]: connect 0.8
    

系統穩定之後,在 RPS 10 的速度下,平均回應時間為 400 毫秒,而 RPS 20 秒的回應時間只增加到 700 毫秒。這與地區性負載平衡器所產生的 5000 毫秒相比,可說是大幅改善,而且使用者體驗也大幅提升。

下圖顯示使用全域負載平衡的 RPS 測量後的回應時間:

顯示回應時間隨著每分鐘要求數增加仍保持平穩的圖形

比較地區性與全域負載平衡的結果

建立單一節點的容量之後,您便可以將地區部署的使用者所觀察到的延遲時間,與全域負載平衡架構下的延遲時間相比較。雖然單一地區的要求數低於該地區服務規模總數,但由於系統一律都是將使用者重新導向鄰近地區,因此這兩個系統都會出現相似的使用者延遲時間。

當一個地區的工作負載超出該地區的服務規模時,不同的解決方案也會帶來不同的使用者延遲時間。

  • 當流量增加到超過容量時,由於流量無處可去,因此只能流向已超載的後端 VM 執行個體,造成「地區性負載平衡解決方案」超載。這包含傳統的地端部署負載平衡器、外部直通式網路負載平衡器 (位於 Google Cloud上),以及單一區域設定中的外部應用程式負載平衡器 (例如使用標準級網路)。平均和最大要求延遲時間增加到 10 倍以上,導致使用者體驗變差,進而造成使用人數大幅下降。

  • 使用在多個地區具有後端的「全域外部應用程式負載平衡器」,能讓流量溢流至鄰近可提供服務容量的地區。這樣可以相對降低使用者延遲時間且更方便評估,因此提供較佳的使用者體驗。如果您的應用程式在區域中的水平擴展速度不夠快,那麼全域外部應用程式負載平衡器便是我們建議的選項。即使整個地區的使用者應用程式伺服器都發生錯誤,流量也能夠迅速導向其他地區,有助於避免整個服務發生中斷的情形。

清除所用資源

刪除專案

如要避免付費,最簡單的方法就是刪除您為了本教學課程所建立的專案。

刪除專案的方法如下:

  1. 前往 Google Cloud 控制台的「Manage resources」(管理資源) 頁面。

    前往「Manage resources」(管理資源)

  2. 在專案清單中選取要刪除的專案,然後點選「Delete」(刪除)
  3. 在對話方塊中輸入專案 ID,然後按一下 [Shut down] (關閉) 以刪除專案。

後續步驟

以下頁面提供 Google 負載平衡選項的更多資訊及背景: