ネットワークの最適化
コレクションでコンテンツを整理
必要に応じて、コンテンツの保存と分類を行います。
Cloud Functions は平易なので、サーバーレス環境でコードをすばやく開発して実行できます。中程度の規模では、ファンクションのランニング コストが低いため、コードの最適化の重要性が見過ごされがちです。しかし、デプロイが拡大するにつれて、コードの最適化の重要性が高まります。
このドキュメントでは、ファンクションのネットワークを最適化する方法について説明します。ネットワークの最適化には次のようなメリットがあります。
- 各関数呼び出しで新しいアウトバウンド接続を確立するために要する CPU 時間を短縮する。
- 接続や DNS 割り当てが不足する可能性を減らす。
持続的な接続を維持する
このセクションでは、ファンクション内で持続的な接続を維持する方法の例を示して説明します。持続的な接続を維持できないと、接続割り当てがすぐに使い果たされてしまう場合があります。
このセクションでは、次のシナリオを取り上げます。
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 クライアント オブジェクトを作成すると、呼び出しごとに 1 つの接続と 2 つの 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
オブジェクトに変換できる値のセットを返します。
GCP_PROJECT
環境変数は、Python 3.7 ランタイムで自動的に設定されます。以降のランタイムでは、関数デプロイで指定してください。環境変数を構成するをご覧ください。
送信接続
アウトバウンド リクエストのタイムアウト
関数から VPC ネットワークへのリクエストでは、10 分間アイドル状態が継続するとタイムアウトが発生します。関数からインターネットへのリクエストの場合は、20 分間のアイドル時間の後にタイムアウトが発生します。
アウトバウンド接続のリセット
関数から VPC とインターネットの両方への接続ストリームは、基盤となるインフラストラクチャの再起動や更新が発生すると、停止して置き替えられる場合があります。アプリケーションで長期間の接続を再利用する場合は、切断された接続の再利用を避けるため、接続を再確立してアプリケーションを構成することをおすすめします。
関数の負荷テスト
関数で実行する接続の平均数を測定するには、HTTP 関数としてデプロイしてから、パフォーマンス テスト フレームワークを使用して特定の QPS で呼び出します。1 つの選択肢として Artillery があります。これは次のように 1 行で呼び出すことができます。
$ artillery quick -d 300 -r 30 URL
このコマンドは、指定された URL を 30 QPS で 300 秒間フェッチします。
テストを実行した後、Cloud コンソールの Cloud Functions API 割り当てページで接続割り当ての使用状況を確認します。使用状況が常に 30(またはその倍数)前後の場合、すべての呼び出しで 1 つ(または複数)の接続が確立されています。コードを最適化した後は、いくつかの接続(10〜30)がテストの開始時にのみ発生していることがわかります。
同じページの CPU 割り当てプロットで、最適化前後の CPU コストを比較することもできます。
特に記載のない限り、このページのコンテンツはクリエイティブ・コモンズの表示 4.0 ライセンスにより使用許諾されます。コードサンプルは Apache 2.0 ライセンスにより使用許諾されます。詳しくは、Google Developers サイトのポリシーをご覧ください。Java は Oracle および関連会社の登録商標です。
最終更新日 2025-08-17 UTC。
[null,null,["最終更新日 2025-08-17 UTC。"],[],[],null,["\u003cbr /\u003e\n\nThe simplicity of Cloud Functions lets you quickly develop code and run it in\na serverless environment. At moderate scale, the cost of running functions is\nlow, and optimizing your code might not seem like a high priority. As your\ndeployment scales up, however, optimizing your code becomes increasingly\nimportant.\n\nThis document describes how to optimize networking for your functions. Some of\nthe benefits of optimizing networking are as follows:\n\n- Reduce CPU time spent in establishing new outbound connections at each function call.\n- Reduce the likelihood of running out of connection or DNS [quotas](https://cloud.google.com/functions/quotas).\n\nMaintaining Persistent Connections\n\nThis section gives examples of how to maintain persistent connections in a\nfunction. Failure to do so can result in quickly exhausting connection quotas.\n\nThe following scenarios are covered in this section:\n\n- HTTP/S\n- Google APIs\n\nHTTP/S Requests\n\nThe optimized code snippet below shows how to maintain persistent connections\ninstead of creating a new connection upon every function invocation: \n\nNode.js \n\n```javascript\nconst http = require('http');\nconst functions = require('firebase-functions');\n\n// Setting the `keepAlive` option to `true` keeps\n// connections open between function invocations\nconst agent = new http.Agent({keepAlive: true});\n\nexports.function = functions.https.onRequest((request, response) =\u003e {\n req = http.request({\n host: '',\n port: 80,\n path: '',\n method: 'GET',\n agent: agent, // Holds the connection open after the first invocation\n }, res =\u003e {\n let rawData = '';\n res.setEncoding('utf8');\n res.on('data', chunk =\u003e { rawData += chunk; });\n res.on('end', () =\u003e {\n response.status(200).send(`Data: ${rawData}`);\n });\n });\n req.on('error', e =\u003e {\n response.status(500).send(`Error: ${e.message}`);\n });\n req.end();\n});\n```\n\nPython \n\n```python\nfrom firebase_functions import https_fn\nimport requests\n\n# Create a global HTTP session (which provides connection pooling)\nsession = requests.Session()\n\n@https_fn.on_request()\ndef connection_pooling(request):\n\n # The URL to send the request to\n url = \"http://example.com\"\n\n # Process the request\n response = session.get(url)\n response.raise_for_status()\n return https_fn.Response(\"Success!\")\n \n```\n\nThis HTTP function uses a connection pool to make HTTP requests. It takes a\nrequest object (`flask.Request`) and returns the response text, or any set\nof values that can be turned into a `Response` object using\n[`make_response`](https://flask.palletsprojects.com/en/3.0.x/api/#flask.make_response).\n\nAccessing Google APIs\n\nThe example below uses [Cloud\nPub/Sub](//cloud.google.com/pubsub/docs/reference/libraries), but this approach\nalso works for other client libraries---for example, [Cloud Natural\nLanguage](//cloud.google.com/natural-language/docs/reference/libraries) or\n[Cloud Spanner](//cloud.google.com/spanner/docs/reference/libraries). Note that\nperformance improvements may depend on the current implementation of particular\nclient libraries.\n\nCreating a Pub/Sub client object results in one connection and two DNS queries\nper invocation. To avoid unnecessary connections and DNS queries, create the\nPub/Sub client object in global scope as shown in the sample below: \n\nnode.js \n\n```javascript\nconst PubSub = require('@google-cloud/pubsub');\nconst functions = require('firebase-functions');\nconst pubsub = PubSub();\n\nexports.function = functions.https.onRequest((req, res) =\u003e {\n const topic = pubsub.topic('');\n\n topic.publish('Test message', err =\u003e {\n if (err) {\n res.status(500).send(`Error publishing the message: ${err}`);\n } else {\n res.status(200).send('1 message published');\n }\n });\n});\n```\n\nPython \n\n```python\nimport os\n\nfrom firebase_functions import https_fn\nfrom google.cloud import pubsub_v1\n\n# from firebase_functions import https_fn\n# Create a global Pub/Sub client to avoid unneeded network activity\npubsub = pubsub_v1.PublisherClient()\n\n@https_fn.on_request()\ndef gcp_api_call(request):\n\n project = os.getenv(\"GCP_PROJECT\")\n request_json = request.get_json()\n\n topic_name = request_json[\"topic\"]\n topic_path = pubsub.topic_path(project, topic_name)\n\n # Process the request\n data = b\"Test message\"\n pubsub.publish(topic_path, data=data)\n\n return https_fn.Response(\"1 message published\")\n \n```\n\nThis HTTP function uses a cached client library instance to reduce the\nnumber of connections required per function invocation. It takes a request\nobject (`flask.Request`) and returns the response text, or any set of values\nthat can be turned into a `Response` object using\n[`make_response`](https://flask.palletsprojects.com/en/3.0.x/api/#flask.make_response).\n\nThe `GCP_PROJECT` environment variable is set automatically in the Python\n3.7 runtime. In later runtimes, make sure to specify it on function\ndeployment. See [Configure environment\nvariables](https://cloud.google.com/run/docs/configuring/services/environment-variables).\n\nOutbound connections\n\nOutbound request timeouts\n\nThere is a timeout after 10 minutes of idle time for requests from your function\nto the VPC network. For requests from your function to the internet, there is a\ntimeout after 20 minutes of idle time.\n\nOutbound connection resets\n\nConnection streams from your function to both the [VPC\nnetwork](https://cloud.google.com/run/docs/configuring/connecting-vpc) and\ninternet can be occasionally terminated and replaced when underlying\ninfrastructure is restarted or updated. If your application reuses long-lived\nconnections, we recommend that you configure your application to re-establish\nconnections to avoid the reuse of a dead connection.\n\nLoad-testing Your Function\n\nTo measure how many connections your function performs on average, deploy\nit as a HTTP function and use a performance-testing framework to invoke it at\ncertain QPS. One possible choice is [Artillery](https://artillery.io/), which\nyou can invoke with a single line: \n\n```\n$ artillery quick -d 300 -r 30 URL\n```\n\nThis command fetches the given URL at 30 QPS for 300 seconds.\n\nAfter performing the test, check the usage of your connection quota on the [Cloud Functions API quota\npage](https://console.cloud.google.com/apis/api/cloudfunctions.googleapis.com/quotas) in Cloud\nConsole. If the usage is consistently around 30 (or its multiple), you are\nestablishing one (or several) connections in every invocation. After you\noptimize your code, you should see a few (10-30) connections occur only at the\nbeginning of the test.\n\nYou can also compare the CPU cost before and after the optimization on the CPU\nquota plot on the same page."]]