本指南提供設計、實作、測試及部署 Knative 服務的最佳做法。如要進一步瞭解秘訣,請參閱遷移現有的服務。
編寫有效的服務
本節說明設計和實作 Knative 服務的一般最佳做法。
避免背景活動
Knative Serving 上的應用程式處理完要求後,容器執行個體對 CPU 的存取權會遭到停用或大幅限制。因此,您不應啟動在要求處理常式範圍外執行的背景執行緒或常式。
執行背景執行緒可能會導致非預期行為,因為任何傳送到同一容器執行個體的後續要求都會恢復所有已暫停的背景活動。
背景活動是指在 HTTP 回應送出後發生的任何活動。請審查您的程式碼,確認在您傳送回應之前,所有非同步作業皆已完成。
如果懷疑您的服務可能有無法立即得知的背景活動,您可以查看記錄:在 HTTP 要求項目後面尋找是否有記錄任何活動。
刪除暫存檔
Cloud Run 環境中的磁碟儲存空間是一個記憶體內部檔案系統。 寫入磁碟的檔案會耗用用於服務的記憶體,而且會在叫用間持續存在。未刪除這些檔案最終可能會導致發生記憶體不足的錯誤,並造成後續冷啟動。
最佳化效能
本節說明最佳化效能的最佳做法。
快速啟動服務
由於容器執行個體會視需要調度資源,常用的方法是將執行環境完整初始化。這種初始化方法稱為「冷啟動」。如果用戶端要求觸發了冷啟動,則容器執行個體的啟動會發生額外的延遲。
啟動例行程序包含:
- 啟動服務
- 啟動容器
- 執行 entrypoint 指令來啟動伺服器。
- 檢查開啟的服務通訊埠。
最佳化服務啟動速度可將延誤容器執行個體處理要求的延遲時間縮至最短。
謹慎使用依附元件
如果您使用動態語言搭配相依的程式庫,例如匯入使用 Node.js 的模組,這些模組的載入時間會增加冷啟動期間的延遲時間。您可以透過以下方式縮短啟動延遲時間:
- 儘可能減少相依元件的數量和大小以建置精簡的服務。
- 只有在必要時才載入不常用的程式碼 (如果您使用的語言支援)。
- 使用程式碼載入的最佳化,例如 PHP 的 composer 自動載入器最佳化。
使用全域變數
在 Knative serving 中,您無法假設服務會保留要求之間的狀態。不過,Knative 服務確實可重複使用個別的容器執行個體來處理不間斷的流量,所以您可以在全域範圍內宣告變數,來允許後續叫用可重複使用其值。任何個別要求是否會因重複使用而獲益,無法事先得知。
如果每次收到服務要求時重新建立物件的作業成本高昂,您也可以快取記憶體內的物件。將這個作業從要求邏輯移至全域範圍會帶來更好的效能。
Node.js
Python
Go
Java
對全域變數執行延遲初始化
系統在啟動時一律會初始化全域變數,這會增加冷啟動時間。對不常用的物件使用延遲初始化,可推遲時間成本並縮短冷啟動時間。
Node.js
Python
Go
Java
最佳化並行
Knative 服務執行個體可同時處理多個要求 (即「並行」),最多可達可設定的並行要求數量上限。這與使用 concurrency = 1
的 Cloud Run 函式不同。
除非程式碼有特定的並行要求,否則請保留預設的並行要求數量上限設定。
為您的服務調整並行
每個容器執行個體可處理的並行要求數量,可能會受限於技術堆疊和共用資源的使用,例如變數和資料庫連線。
如何最佳化您的服務來達到最大的穩定並行:
- 最佳化您的服務效能。
- 在任何程式碼層級並行設定中,設定您預期的並行支援層級。並非所有技術堆疊都需要這樣設定。
- 部署您的服務。
- 為您的服務設定等於或小於任何程式碼層級設定的 Knative serving 並行。如果沒有程式碼層級設定,請使用您預期的並行。
- 使用支援可設定並行的負載測試工具。您必須確認您的服務在預期的負載和並行處理下是否仍可維持穩定。
- 如果服務效能不佳,請前往步驟 1 來改善服務,或前往步驟 2 來減少並行。如果服務執行效能很好,請回到步驟 2 增加並行。
繼續反覆操作,直到您找到最大的穩定並行。
使記憶體與並行相配
您的服務在處理每一個要求時,都需要使用額外少量的記憶體。 所以,當您上下調整並行時,請務必一併調整記憶體。
避免可變動的全域狀態
如果您想在並行情況下利用可變動的全域狀態,請在您的程式碼中採取額外的步驟來確保安全完成。將全域變數限制為一次性初始化,來儘可能避免爭用狀況,然後按照效能底下的說明重複使用。
如果您在一次處理多個要求的服務中使用可變動的全域變數,請務必使用鎖定或互斥鎖來避免發生競爭狀況。
容器安全性
很多一般用途的軟體安全性做法都適用於經過容器化的應用程式。 有些做法專屬於容器或吻合容器的原理和架構。
如要改善容器安全性:
定期重新建構容器映像檔並重新部署您的服務,以將安全性更新套用到您的服務。
在容器中僅包含執行服務所必要的項目。額外的程式碼、套件和工具都可能是安全漏洞。如要瞭解相關的效能影響,請參閱上文說明。
實作確定性建構程序,其包含特定軟體和程式庫版本。這可以防止將未經驗證的程式碼納入容器中。
使用 Dockerfile
USER
陳述式,將容器設為以root
以外的用者身分執行。某些容器映像檔可能已有設定的特定使用者。
自動執行安全性掃描
啟用安全漏洞掃描,對儲存在 Artifact Registry 的容器映像檔進行安全性掃描。
您也可以使用二進位授權,確保只部署安全的容器映像檔。
建構最小容器映像檔
大型容器映像檔可能增加安全漏洞,因為其中包含的內容超出程式碼需求。
在 Knative 服務中,容器映像檔的大小不會影響冷啟動或要求處理時間,也不會計入容器的可用記憶體。
如要建構最小的容器,請考慮使用精簡的基本映像檔,例如:
Ubuntu 比較大,但也是經常與立即可用的更完整伺服器環境搭配使用的基本映像檔。
如果您的服務具有需要大量使用工具的建構程序,請考慮使用多階段建構來確保您的容器在執行階段不會占用大量資源。
以下資源提供建立精簡容器映像檔的進一步資訊: