為 LLM 回覆和其他流量設定串流

本文說明如何在 API Gateway 中設定串流。

API Gateway 支援串流。串流功能可讓閘道提供長期連線服務,並以區塊形式傳輸要求和回應串流的資料。

串流的常見用途是提供大型語言模型 (LLM)。模型會一次傳送一個權杖的答案,因此用戶端可以在模型仍在生成答案時顯示文字。如需完整範例,瞭解如何從 vLLM 在 Cloud Run 上提供的 Gemma 模型串流回應,請參閱「從 LLM 串流回應」。

支援的串流通訊協定

啟用後,API Gateway 支援下列串流方法:

  • 遞增式回應傳送:視用戶端協商結果而定,使用 HTTP/2 DATA 框架或 HTTP/1.1 分塊傳輸編碼。
  • 伺服器傳送事件 (SSE):從伺服器到用戶端的單向串流。
  • WebSockets:透過單一 TCP 連線進行全雙工通訊的管道。
  • gRPC 雙向串流:使用 gRPC 的全雙工串流。

必要條件

如要使用串流功能,請先確認後端服務支援必要通訊協定 (例如 HTTP/2 或 WebSocket),且 API 設定正確無誤。

設定後端通訊協定

如要支援串流流量,請根據串流類型設定後端的通訊協定:

  • gRPC:您必須將後端設定為使用 HTTP/2 (h2)。
  • WebSockets:您必須使用 http/1.1。WebSocket 需要 HTTP/1.1 Connection: Upgrade 握手。
  • 伺服器傳送事件 (SSE) 和增量回應傳送:後端可以使用 HTTP/1.1 或 HTTP/2 (h2)。建議使用 HTTP/2 (h2) 提升效能。

在 OpenAPI 規格中,按照下列方式設定後端通訊協定:

範例 (OpenAPI 3.x)

在 x-google-api-management.backends 物件中,於具名後端定義中設定 protocol 欄位。您也必須在根層級或作業層級使用 x-google-backend 參照這個後端。

x-google-api-management:
  backends:
    gemma:
      address: https://my-gemma-service.run.app
      protocol: h2 # Use 'http/1.1' for WebSockets
x-google-backend: gemma

範例 (OpenAPI 2.0)

在 x-google-backend 擴充功能中設定 protocol 欄位。

x-google-backend:
  address: https://my-gemma-service.run.app
  protocol: h2 # Use 'http/1.1' for WebSockets

設定串流截止時間

deadline 欄位會控管要求 (一元或串流) 的執行時間長度。

下表說明逾時如何套用至各類要求:

方法 閒置逾時時間
(訊息間隔時間上限)
要求逾時
(要求總時間長度上限)
非串流 不適用:閒置逾時僅適用於串流 預設為 15 秒;如要變更,請設定 deadline,啟用串流的閘道最多可設為 3,600 秒
透過 HTTP 串流
(SSE、分塊傳輸)
不適用:實際上是無限期,只有要求逾時會結束串流 預設為 15 秒;如要變更,請設定 deadline,啟用串流的閘道最多可設為 3,600 秒
透過 gRPC 或 WebSocket 串流 預設為 300 秒;如要變更,請設定 deadline,啟用串流的閘道最多可設為 3,600 秒。如果是 WebSockets,系統會忽略小於 300 秒的 deadline,並套用 300 秒的最小值 啟用串流的閘道一律為 3,600 秒,無法設定

範例 (OpenAPI 3.x)

在具名後端定義中設定 deadline 欄位。

x-google-api-management:
  backends:
    gemma:
      address: https://my-gemma-service.run.app
      protocol: h2
      deadline: 3600.0
x-google-backend: gemma

範例 (OpenAPI 2.0)

在 x-google-backend 擴充功能中設定 deadline 欄位。

x-google-backend:
  address: https://my-gemma-service.run.app
  protocol: h2
  deadline: 3600.0

如要瞭解串流連線的其他限制,請參閱「限制」一節。

在閘道上啟用串流

串流會在建立閘道時指定。請注意下列行為:

  • 沒有明確停用:沒有可明確停用串流的旗標。如果省略 --enable-streaming 旗標,API Gateway 會在建立時,根據 API 設定和平台預設值解析模式:設定模型路由器的 API 設定一律會產生串流閘道。讀取閘道的唯讀 effectiveStreamingMode 欄位,即可查看建立閘道時使用的模式。
  • 不可變動:串流模式在建立後即無法變更。

如要在閘道上指定串流,請使用 gcloud api-gateway gateways create 指令搭配 --enable-streaming 旗標:

gcloud api-gateway gateways create GATEWAY_ID \
    --api=API_ID \
    --api-config=CONFIG_ID \
    --location=GCP_REGION \
    --enable-streaming

如要進一步瞭解閘道部署選項,請參閱「將 API 部署至閘道」。

閘道串流屬性

Gateway 資源的下列欄位可控制串流行為:

欄位 屬性 值
streamingMode 字串 (IMMUTABLE,OPTIONAL)
  • STREAMING_MODE_UNSPECIFIED (預設:服務會選取模式)
  • STREAMING_MODE_ENABLED
effectiveStreamingMode 字串 (OUTPUT_ONLY)
  • EFFECTIVE_STREAMING_MODE_DISABLED
  • EFFECTIVE_STREAMING_MODE_ENABLED

使用 REST API 建立閘道時,可以在要求本文中指定串流:

{
  "apiConfig": "projects/...",
  "streamingMode": "STREAMING_MODE_ENABLED"
}

確認已啟用串流功能

如要確認閘道是否已啟用串流功能,請使用 gcloud CLI 說明閘道:

gcloud api-gateway gateways describe GATEWAY_ID \
    --location=GCP_REGION

在輸出內容中尋找 effectiveStreamingMode 欄位。如果已啟用串流功能,輸出內容會包含:

effectiveStreamingMode: EFFECTIVE_STREAMING_MODE_ENABLED

逐句顯示 LLM 回覆

這個範例會在 Gemma 模型前面放置串流閘道,該模型由 Cloud Run 上的 vLLM 提供服務,並透過閘道串流聊天完成作業。vLLM 提供與 OpenAI 相容的 API,可將回覆內容串流為伺服器傳送事件 (SSE)。

開始前,請先完成「設定開發環境」,包括「設定用於建立 API 設定的服務帳戶」。閘道會使用該服務帳戶呼叫 Cloud Run 服務。

部署模型

按照「透過 vLLM 容器部署 Gemma 4 模型」一文的說明,部署 Gemma 模型。請記下服務名稱、服務網址、區域,以及您部署的模型名稱,例如 google/gemma-4-E4B-it。

授予閘道服務存取權

本指南會使用「--no-allow-unauthenticated」部署服務。閘道會使用服務帳戶的 ID 權杖呼叫服務,您在建立 API 設定時,會將該權杖做為 --backend-auth-service-account 傳遞。將 Cloud Run 叫用者角色 (roles/run.invoker) 授予該服務帳戶:

gcloud run services add-iam-policy-binding SERVICE_NAME \
    --region=REGION \
    --member=serviceAccount:SERVICE_ACCOUNT_EMAIL \
    --role=roles/run.invoker

更改下列內容:

  • SERVICE_NAME:Cloud Run 服務名稱
  • REGION:部署服務的區域
  • SERVICE_ACCOUNT_EMAIL:閘道服務帳戶的電子郵件地址

建立 API 設定

將下列 OpenAPI 規格儲存為 gemma-api.yaml,並將 https://my-gemma-service.run.app 替換為您的服務網址:

openapi: 3.0.3
info:
  title: Gemma API
  version: 1.0.0
x-google-api-management:
  backends:
    gemma:
      address: https://my-gemma-service.run.app
      protocol: h2
      deadline: 570.0
x-google-backend: gemma
components:
  securitySchemes:
    google_id_token:
      type: oauth2
      flows:
        implicit:
          authorizationUrl: ""
          scopes: {}
      x-google-auth:
        issuer: https://accounts.google.com
        jwksUri: https://www.googleapis.com/oauth2/v3/certs
        audiences:
          - gemma-api
security:
  - google_id_token: []
paths:
  /v1/chat/completions:
    post:
      operationId: createChatCompletion
      responses:
        '200':
          description: A chat completion, streamed as SSE when the request sets "stream" to true.

570 秒的 deadline比 Gemma 指南在服務中設定的 --timeout 600短 30 秒。因此,如果串流執行時間過長,閘道的 deadline (而非服務逾時) 會終止串流。頂層 x-google-backend 預設為 pathTranslation: APPEND_PATH_TO_ADDRESS。閘道會將要求路徑附加至後端位址,因此對 /v1/chat/completions 的要求會抵達 vLLM 對話完成端點。

security 規定會導致閘道拒絕任何未攜帶 Google 簽署的 ID 權杖 (對象為 gemma-api) 的要求。只要呼叫者在鑄造權杖時要求相同的目標對象字串,您就可以選擇其他目標對象字串。詳情請參閱「使用 Google ID 權杖驗證使用者身分」。

建立 API 設定:

gcloud api-gateway api-configs create CONFIG_ID \
    --api=API_ID \
    --openapi-spec=gemma-api.yaml \
    --backend-auth-service-account=SERVICE_ACCOUNT_EMAIL

更改下列內容:

  • CONFIG_ID:API 設定的 ID
  • API_ID:API 的 ID。如果 API 不存在,這項指令會建立 API。

建立閘道

從 API 設定建立串流閘道:

gcloud api-gateway gateways create GATEWAY_ID \
    --api=API_ID \
    --api-config=CONFIG_ID \
    --location=GCP_REGION \
    --enable-streaming

更改下列內容:

  • GATEWAY_ID:閘道的 ID
  • GCP_REGION:閘道的區域,可能與 REGION 不同。如需允許的值,請參閱「將 API 部署至閘道」。

閘道準備就緒後,請取得其主機名稱:

gcloud api-gateway gateways describe GATEWAY_ID \
    --location=GCP_REGION \
    --format="value(defaultHostname)"

取得呼叫者的 ID 權杖

使用者帳戶無法選擇 ID 權杖的目標對象,因此範例會為您模擬的服務帳戶產生權杖。對於呼叫端,請使用現有服務帳戶或建立服務帳戶。詳情請參閱「建立服務帳戶」。將該服務帳戶的服務帳戶權杖建立者角色 (roles/iam.serviceAccountTokenCreator) 授予自己,gcloud CLI 必須模擬該角色:

gcloud iam service-accounts add-iam-policy-binding CALLER_SERVICE_ACCOUNT_EMAIL \
    --member=user:USER_EMAIL \
    --role=roles/iam.serviceAccountTokenCreator

更改下列內容:

  • CALLER_SERVICE_ACCOUNT_EMAIL:呼叫閘道的服務帳戶電子郵件地址
  • USER_EMAIL:您的電子郵件地址

傳送串流要求

傳送對話完成要求,並在 Authorization 標頭中設定 "stream": true,以及呼叫者服務帳戶的 ID 權杖。-N 旗標會關閉 curl 中的輸出緩衝區,因此每個事件都會在抵達時列印:

curl -N https://DEFAULT_HOSTNAME/v1/chat/completions \
    -H "Authorization: Bearer $(gcloud auth print-identity-token \
        --impersonate-service-account=CALLER_SERVICE_ACCOUNT_EMAIL \
        --audiences=gemma-api)" \
    -H "Content-Type: application/json" \
    -d '{
      "model": "MODEL_NAME",
      "messages": [{"role": "user", "content": "Why is the sky blue?"}],
      "stream": true
    }'

更改下列內容:

  • DEFAULT_HOSTNAME:閘道的主機名稱
  • CALLER_SERVICE_ACCOUNT_EMAIL:上一個步驟中的服務帳戶
  • MODEL_NAME:您部署的模型,例如 google/gemma-4-E4B-it

回應是 SSE 串流。第一個事件會帶有 assistant 角色,後續每個事件會帶有答案的下一部分,而 data: [DONE] 前的最後一個事件會設定 finish_reason。輸出結果會與下列內容相似:

data: {"id":"chatcmpl-7bcd57ad-1c3c-4779-91be-2973b875e517","object":"chat.completion.chunk","created":1790099706,"model":"google/gemma-4-E4B-it","choices":[{"index":0,"delta":{"role":"assistant","content":""},"logprobs":null,"finish_reason":null}],"prompt_token_ids":null}

data: {"id":"chatcmpl-7bcd57ad-1c3c-4779-91be-2973b875e517","object":"chat.completion.chunk","created":1790099706,"model":"google/gemma-4-E4B-it","choices":[{"index":0,"delta":{"content":"The"},"logprobs":null,"finish_reason":null,"token_ids":null}]}

...

data: {"id":"chatcmpl-7bcd57ad-1c3c-4779-91be-2973b875e517","object":"chat.completion.chunk","created":1790099706,"model":"google/gemma-4-E4B-it","choices":[{"index":0,"delta":{"content":""},"logprobs":null,"finish_reason":"stop","stop_reason":106,"token_ids":null}]}

data: [DONE]

清除所用資源

如要避免系統向您的 Google Cloud 帳戶收取本範例所用資源的費用,請刪除閘道和 API 設定:

gcloud api-gateway gateways delete GATEWAY_ID \
    --location=GCP_REGION
gcloud api-gateway api-configs delete CONFIG_ID \
    --api=API_ID

如果您是為這個範例建立 API,請刪除該 API:

gcloud api-gateway apis delete API_ID

刪除 Cloud Run 服務:

gcloud run services delete SERVICE_NAME \
    --region=REGION

定價

在串流的公開預先發布期間,啟用串流的閘道不會向客戶收取網路輸出費用。不過,無論發布階段為何,Service Control 仍會以 API 級別計費。

限制

公開預先發布版 API Gateway 的串流功能有以下限制:

  • 不可變動性:您無法更新現有閘道來啟用或停用串流。你必須建立新的閘道。請注意,啟用串流功能的閘道會收到不同的主機名稱形狀,因此您必須更新用戶端或 DNS 記錄。如要請我們更新閘道記錄以使用新格式,請與支援團隊聯絡。API Gateway 使用下列主機名稱模式:

    • 非串流:例如 {gateway_id}-{base36_project_number}.{shard_hash}.gateway.dev、test-gateway-4jcaz8x.uc.gateway.dev
    • 串流:{gateway_id}-{project_number}.{region}.gateway.dev,例如 test-gateway-9876654321.us-central1.gateway.dev
    • 串流 (舊版):例如 {service}-{tenant_project_number}.{region}.run.apptest-gateway-834512064953.us-central1.run.app。在區域 *.gateway.dev 主機名稱推出前建立的閘道會永久保留這個主機名稱,不會遷移至新模式。

    支援串流的新閘道會收到 Streaming 模式。前兩個範例是同一專案中的相同閘道:在「串流」模式中,專案編號會以十進位而非 base36 顯示,因此第一個標籤的空間比非串流閘道小。第一個標籤是合併的 {gateway_id}-{project_number} 字串,必須符合 63 個半形字元的 DNS 標籤限制。閘道 ID 長度上限為 49 個字元,因此專案編號最多只能有 13 位數。如果專案編號超過 13 位數,閘道 ID 就必須縮短。

  • Terraform:不支援使用 Terraform 啟用串流 (預計在日後版本中推出)。

  • 負載平衡和自訂網域:具有 effectiveStreamingMode EFFECTIVE_STREAMING_MODE_ENABLED 的閘道不適用於 API Gateway 或無伺服器 NEG 的 HTTP(S) 負載平衡。您無法將這類閘道放在無伺服器 NEG 或外部應用程式負載平衡器後方。因此,在公開預先發布期間,這些閘道不支援自訂網域 (自訂網域依賴負載平衡)。

  • 截止期限行為:在閘道上啟用串流功能,不會改變 SSE 或分塊傳輸路徑上 deadline 欄位的行為。完整回覆的截止時間仍以實際時間為準,因此無論串流傳送多少資料,一旦超過截止時間就會中斷。預設值為 15 秒,最長為 3,600 秒。在 WebSocket 上,deadline 會限制訊息間隔,並在 3,600 秒後終止連線。請參閱「設定直播截止時間」。

  • Model Context Protocol (MCP):使用 --enable-streaming 建立閘道時,不會建立 MCP 端點串流。無論閘道的串流模式為何,MCP 回應仍為單一 application/json 主體。詳情請參閱「MCP 限制」。