Cloud Functions 操作簡單,可讓您在無伺服器環境中快速開發及執行程式碼。在中等規模環境中,函式的執行費用較低,最佳化程式碼的急迫性似乎不高。不過,隨著部署作業擴大,程式碼最佳化也變得越來越重要。
本文件說明如何針對您的函式最佳化網路。最佳化網路的部分優點如下所述:
- 可縮短每次呼叫函式時,建立新傳出連線花費的 CPU 作業時間。
- 可減少連線中斷或 DNS 配額用盡的可能性。
保持永久連線
本節提供如何在函式中保持永久連線的範例。如果不能永久連線,會導致快速用盡連線配額。
本節介紹下列情境:
- HTTP/S
- Google API
HTTP/S 要求
以下經過最佳化的程式碼片段顯示如何保持永久連線,而不必在每次叫用函式時建立新連線:
Node.js
const http = require('http'); const functions = require('firebase-functions'); // Setting the `keepAlive` option to `true` keeps // connections open between function invocations const agent = new http.Agent({keepAlive: true}); exports.function = functions.https.onRequest((request, response) => { req = http.request({ host: '' , port: 80, path: '' , method: 'GET', agent: agent, // Holds the connection open after the first invocation }, res => { let rawData = ''; res.setEncoding('utf8'); res.on('data', chunk => { rawData += chunk; }); res.on('end', () => { response.status(200).send(`Data: ${rawData}`); }); }); req.on('error', e => { response.status(500).send(`Error: ${e.message}`); }); req.end(); });
Python
from firebase_functions import https_fn import requests # Create a global HTTP session (which provides connection pooling) session = requests.Session() @https_fn.on_request() def connection_pooling(request): # The URL to send the request to url = "http://example.com" # Process the request response = session.get(url) response.raise_for_status() return https_fn.Response("Success!")
這個 HTTP 函式會使用連線集區提出 HTTP 要求。這個函式會接收要求物件 (flask.Request),並傳回回應文字,或可使用 make_response 轉換為 Response 物件的任何值組合。
存取 Google API
以下範例使用 Cloud Pub/Sub,但這個方法也適用於其他用戶端程式庫,例如 Cloud Natural Language 或 Cloud Spanner。請注意,效能提升情況取決於特定用戶端程式庫的目前實作。
建立 Pub/Sub 用戶端物件後,每次叫用都會建立一個連線和兩個 DNS 查詢。為避免不必要的連線和 DNS 查詢,請在全域範圍內建立 Pub/Sub 用戶端物件,如下列範例所示:
node.js
const PubSub = require('@google-cloud/pubsub'); const functions = require('firebase-functions'); const pubsub = PubSub(); exports.function = functions.https.onRequest((req, res) => { const topic = pubsub.topic('' ); topic.publish('Test message', err => { if (err) { res.status(500).send(`Error publishing the message: ${err}`); } else { res.status(200).send('1 message published'); } }); });
Python
import os from firebase_functions import https_fn from google.cloud import pubsub_v1 # from firebase_functions import https_fn # Create a global Pub/Sub client to avoid unneeded network activity pubsub = pubsub_v1.PublisherClient() @https_fn.on_request() def gcp_api_call(request): project = os.getenv("GCP_PROJECT") request_json = request.get_json() topic_name = request_json["topic"] topic_path = pubsub.topic_path(project, topic_name) # Process the request data = b"Test message" pubsub.publish(topic_path, data=data) return https_fn.Response("1 message published")
這個 HTTP 函式使用快取用戶端程式庫執行個體,以減少每次函式叫用所需的連線數。這個函式會採用要求物件 (flask.Request),並傳回回應文字,或可使用 make_response 轉換為 Response 物件的任何值組合。
Python 3.7 執行階段會自動設定 GCP_PROJECT 環境變數。在後續執行階段中,請務必在函式部署時指定此值。請參閱「設定環境變數」。
傳出連線
傳出要求逾時
函式要求連線至虛擬私有雲網路時,如果閒置 10 分鐘,就會發生逾時。如果函式要求連上網際網路,閒置 20 分鐘後就會逾時。
傳出連線重設
從函式傳至 VPC 網路和網際網路的連線串流,可能會在基礎架構重新啟動或更新時終止並替換。如果應用程式會重複使用長期連線,建議將應用程式設為重新建立連線,避免重複使用失效的連線。
對函式進行負載測試
如要測量函式平均執行的連線數,請將函式部署為 HTTP 函式,並使用效能測試架構,以特定的每秒查詢數 (QPS) 叫用這個函式。其中一個可能的選擇是 Artillery,您可以使用單行叫用:
$ artillery quick -d 300 -r 30 URL
這個指令會以 30 QPS 的頻率擷取指定網址 300 秒。
執行測試後,請前往 Cloud 控制台的 Cloud Functions API 配額頁面,查看連線配額的使用情況。如果用量持續約為 30 或其倍數,表示每次叫用時都會建立一或多個連線。最佳化程式碼之後,應該只在測試開始時建立了一些連線 (10 至 30 個)。
您也可以透過同一頁面的 CPU 配額圖,比較最佳化前後的 CPU 費用。