最佳化網路連線 (第 1 代)
Cloud Run 函式簡單易用,可讓您快速開發程式碼,並在無伺服器環境中執行。在中等規模情況下,函式的執行費用較低,最佳化程式碼似乎顯得不那麼迫切。但隨著開發規模的增長,最佳化程式碼就會變得越來越重要。
本文件說明如何針對您的函式最佳化網路。最佳化網路的部分優點如下所述:
- 可減少 CPU 在每次呼叫函式時建立新連線花費的時間。
- 降低連線或 DNS 配額用盡的可能性。
維持持續連線
本節提供如何在函式中保持永久連線的範例。如果不能永久連線,會導致快速用盡連線配額。
本節介紹下列情境:
- HTTP/S
- Google API
HTTP/S 要求
下列最佳化程式碼片段說明如何維護持續性連線,而非在每次函式叫用時建立新連線:
存取 Google API
下列範例使用 Cloud Pub/Sub,但這個方法也適用於其他用戶端程式庫,例如 Cloud Natural Language 或 Cloud Spanner。請注意,效能的提升可能取決於特定用戶端程式庫的目前實作。
建立 Pub/Sub 用戶端物件時,每次叫用都會產生一個連線和兩個 DNS 查詢。為避免不必要的連線和 DNS 查詢,請在全域範圍中建立 Pub/Sub 用戶端物件,如下列範例所示:
Node.js
Python
Go
// Package contexttip is an example of how to use Pub/Sub and context.Context in // a Cloud Function. package contexttip import ( "context" "encoding/json" "fmt" "log" "net/http" "os" "sync" "cloud.google.com/go/pubsub" "github.com/GoogleCloudPlatform/functions-framework-go/functions" ) // client is a global Pub/Sub client, initialized once per instance. var client *pubsub.Client var once sync.Once // createClient creates the global pubsub Client func createClient() { // GOOGLE_CLOUD_PROJECT is a user-set environment variable. var projectID = os.Getenv("GOOGLE_CLOUD_PROJECT") // err is pre-declared to avoid shadowing client. var err error // client is initialized with context.Background() because it should // persist between function invocations. client, err = pubsub.NewClient(context.Background(), projectID) if err != nil { log.Fatalf("pubsub.NewClient: %v", err) } } func init() { // register http function functions.HTTP("PublishMessage", PublishMessage) } type publishRequest struct { Topic stringjson:"topic"
Message stringjson:"message"
} // PublishMessage publishes a message to Pub/Sub. PublishMessage only works // with topics that already exist. func PublishMessage(w http.ResponseWriter, r *http.Request) { // use of sync.Once ensures client is only created once. once.Do(createClient) // Parse the request body to get the topic name and message. p := publishRequest{} if err := json.NewDecoder(r.Body).Decode(&p); err != nil { log.Printf("json.NewDecoder: %v", err) http.Error(w, "Error parsing request", http.StatusBadRequest) return } if p.Topic == "" || p.Message == "" { s := "missing 'topic' or 'message' parameter" log.Println(s) http.Error(w, s, http.StatusBadRequest) return } m := &pubsub.Message{ Data: []byte(p.Message), } // Publish and Get use r.Context() because they are only needed for this // function invocation. If this were a background function, they would use // the ctx passed as an argument. id, err := client.Topic(p.Topic).Publish(r.Context(), m).Get(r.Context()) if err != nil { log.Printf("topic(%s).Publish.Get: %v", p.Topic, err) http.Error(w, "Error publishing message", http.StatusInternalServerError) return } fmt.Fprintf(w, "Message published: %v", id) }
重設外送連線
函式與 VPC 和網際網路之間的連線串流,可能會在基礎架構重新啟動或更新時終止並取代。如果應用程式會重複使用長期連線,建議您將應用程式設為重新建立連線,避免重複使用已失效的連線。
傳出要求逾時
系統可在傳出通訊端閒置 10 分鐘後將其收回,如有任何通訊端相關作業,通訊端有效時間會延長 10 分鐘。
對函式執行負載測試
如要評估函式平均執行的連線數,請將函式部署為 HTTP 函式,並使用效能測試架構以特定 QPS 叫用函式。其中一個可能的選擇是 Artillery,您可以使用單行叫用:
$ artillery quick -d 300 -r 30 URL
這個指令會以 30 QPS 的頻率擷取指定網址 300 秒。
執行測試後,請前往 Google Cloud 控制台的 Cloud Run Functions API 配額頁面,查看連線配額用量。如果用量持續在 30 左右 (或 30 的倍數),表示您在每次呼叫時建立一或多個連線。最佳化程式碼之後,您應該會發現只有在測試開始時,建立了一些連線 (數目大概是10-30 個)。
您也可以在同一頁面的 CPU 配額圖中比較最佳化前後的 CPU 費用。