Configura lo streaming per le risposte LLM e altro traffico

Questo documento descrive come configurare lo streaming in API Gateway.

API Gateway supporta lo streaming. Lo streaming consente ai gateway di gestire connessioni a lunga esecuzione e trasmettere dati in blocchi sia per lo streaming di richieste che di risposte.

Un utilizzo comune dello streaming è la gestione di un modello linguistico di grandi dimensioni (LLM). Il modello invia la risposta un token alla volta, in modo che un client possa mostrare il testo mentre il modello lo sta ancora generando. Per un esempio completo che trasmette in streaming le risposte di un modello Gemma fornito da vLLM su Cloud Run, consulta Trasmetti in streaming le risposte da un LLM.

Protocolli di streaming supportati

Se abilitato, API Gateway supporta i seguenti metodi di streaming:

  • Invio incrementale della risposta: frame DATA HTTP/2 o codifica di trasferimento in chunk HTTP/1.1, a seconda di ciò che il client negozia.
  • Server-Sent Events (SSE): streaming unidirezionale dal server al client.
  • WebSockets: canali di comunicazione full-duplex su una singola connessione TCP.
  • Streaming bidirezionale gRPC: streaming full-duplex tramite gRPC.

Prerequisiti

Prima di poter utilizzare lo streaming, assicurati che il servizio di backend supporti il protocollo richiesto (ad esempio HTTP/2 o WebSocket) e che la configurazione dell'API sia impostata correttamente.

Configura il protocollo di backend

Per supportare il traffico di streaming, devi configurare il protocollo per il backend in base al tipo di streaming:

  • gRPC: devi configurare il backend in modo che utilizzi HTTP/2 (h2).
  • WebSockets: devi utilizzare http/1.1. I WebSocket richiedono l'handshake HTTP/1.1 Connection: Upgrade.
  • Server-Sent Events (SSE) e distribuzione incrementale delle risposte: il tuo backend può utilizzare HTTP/1.1 o HTTP/2 (h2). Consigliamo HTTP/2 (h2) per migliorare le prestazioni.

Nella specifica OpenAPI, configura il protocollo di backend come segue:

Esempio (OpenAPI 3.x)

Imposta il campo protocol nella definizione del backend denominato all'interno dell'oggetto x-google-api-management.backends. Devi anche fare riferimento a questo backend utilizzando x-google-backend a livello di root o di operazione.

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

Esempio (OpenAPI 2.0)

Imposta il campo protocol nell'estensione x-google-backend.

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

Imposta la scadenza dello stream

Il campo deadline regola la durata di una richiesta (unaria o in streaming).

La tabella seguente mostra come i timeout si applicano a ogni tipo di richiesta:

Metodo Timeout per inattività
(intervallo massimo tra i messaggi)
Timeout della richiesta
(durata totale massima della richiesta)
Non in streaming N/A: il timeout di inattività si applica solo agli stream Valore predefinito: 15 secondi; imposta deadline per modificarlo, fino a 3600 secondi per i gateway abilitati per lo streaming
Streaming su HTTP
(SSE, trasferimento in blocchi)
N/A: effettivamente infinito; solo il timeout della richiesta termina lo stream Valore predefinito: 15 secondi; imposta deadline per modificarlo, fino a 3600 secondi per i gateway abilitati per lo streaming
Streaming su gRPC o WebSocket Il valore predefinito è 300 secondi; imposta deadline per modificarlo, fino a 3600 secondi per i gateway abilitati per lo streaming. Su WebSockets, un valore deadline inferiore a 300 secondi viene ignorato e viene applicato un minimo di 300 secondi Sempre 3600 secondi per i gateway abilitati per lo streaming, non configurabile

Esempio (OpenAPI 3.x)

Imposta il campo deadline nella definizione del backend denominato.

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

Esempio (OpenAPI 2.0)

Imposta il campo deadline nell'estensione x-google-backend.

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

Per gli altri limiti che si applicano alle connessioni in streaming, consulta Limiti.

Abilita lo streaming su un gateway

Lo streaming viene specificato al momento della creazione del gateway. Tieni presente il seguente comportamento:

  • Nessuna disattivazione esplicita: non esiste un flag per disattivare esplicitamente lo streaming. Se ometti il flag --enable-streaming, API Gateway risolve la modalità al momento della creazione dalla configurazione API e dal valore predefinito della piattaforma: una configurazione API che configura un router del modello produce sempre un gateway di streaming. Leggi il campo effectiveStreamingMode di sola uscita del gateway per visualizzare la modalità con cui è stato creato.
  • Immutabilità: la modalità di streaming viene impostata al momento della creazione e non può essere modificata in un secondo momento.

Per specificare lo streaming su un gateway, utilizza il flag --enable-streaming con il comando gcloud api-gateway gateways create:

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

Per saperne di più sulle opzioni di deployment del gateway, consulta Esegui il deployment di un'API in un gateway.

Proprietà di streaming del gateway

I seguenti campi della risorsa Gateway controllano il comportamento di streaming:

Campo Attributi Valori
streamingMode Stringa (IMMUTABILE, FACOLTATIVA)
  • STREAMING_MODE_UNSPECIFIED (valore predefinito: il servizio seleziona la modalità)
  • STREAMING_MODE_ENABLED
effectiveStreamingMode Stringa (OUTPUT_ONLY)
  • EFFECTIVE_STREAMING_MODE_DISABLED
  • EFFECTIVE_STREAMING_MODE_ENABLED

Quando utilizzi l'API REST per creare un gateway, puoi specificare lo streaming nel corpo della richiesta:

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

Verifica che lo streaming sia abilitato

Per verificare se lo streaming è attivo sul tuo gateway, descrivi il gateway utilizzando gcloud CLI:

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

Cerca il campo effectiveStreamingMode nell'output. Se lo streaming è abilitato, l'output include:

effectiveStreamingMode: EFFECTIVE_STREAMING_MODE_ENABLED

Chiama le API Google Cloud

Un gateway di streaming può chiamare API Google Cloud come aiplatform.googleapis.com, in modo da poter trasmettere in streaming le risposte di un modello Gemini su Agent Platform tramite il gateway. Il gateway si autentica su questi backend con un token di accesso anziché con un token ID. Per maggiori dettagli, consulta Protezione dei servizi di backend.

Risposte in streaming da un LLM

Questo esempio posiziona un gateway di streaming davanti a un modello Gemma gestito da vLLM su Cloud Run e trasmette in streaming un completamento della chat tramite il gateway. vLLM fornisce un'API compatibile con OpenAI che trasmette in streaming le risposte come eventi inviati dal server (SSE).

Prima di iniziare, completa la sezione Configura l'ambiente di sviluppo, inclusa la sezione Configura il account di servizio utilizzato per creare le configurazioni API. Il gateway utilizza questo account di servizio per chiamare il servizio Cloud Run.

Esegui il deployment del modello

Esegui il deployment di un modello Gemma seguendo le istruzioni riportate in Esegui il deployment di un modello Gemma 4 con un container vLLM. Prendi nota del nome del servizio, dell'URL del servizio, della regione e del nome del modello di cui esegui il deployment, ad esempio google/gemma-4-E4B-it.

Concedi al gateway l'accesso al servizio

La guida esegue il deployment del servizio con --no-allow-unauthenticated. Il gateway chiama il servizio con un token ID per il proprio account di servizio, che passi come --backend-auth-service-account quando crei la configurazione API. Concedi a questo account di servizio il ruolo Cloud Run Invoker (roles/run.invoker) sul servizio:

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

Sostituisci quanto segue:

  • SERVICE_NAME: il nome del servizio Cloud Run
  • REGION: la regione in cui hai eseguito il deployment del servizio
  • SERVICE_ACCOUNT_EMAIL: l'indirizzo email del account di servizio del gateway

Crea la configurazione API

Salva la seguente specifica OpenAPI come gemma-api.yaml, sostituendo https://my-gemma-service.run.app con l'URL del tuo servizio:

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.

Il valore deadline di 570 secondi è inferiore di 30 secondi rispetto al valore --timeout 600 impostato dalla guida di Gemma sul servizio. Di conseguenza, è il valore deadline del gateway, non il timeout del servizio, a terminare uno stream che viene eseguito troppo a lungo. Un x-google-backend di primo livello viene impostato per impostazione predefinita su pathTranslation: APPEND_PATH_TO_ADDRESS. Il gateway aggiunge il percorso della richiesta all'indirizzo del backend, quindi una richiesta a /v1/chat/completions raggiunge l'endpoint dei completamenti della chat vLLM.

Il requisito security fa sì che il gateway rifiuti qualsiasi richiesta che non contenga un token ID firmato da Google con il segmento di pubblico gemma-api. Puoi scegliere una stringa di pubblico diversa, purché i chiamanti richiedano la stessa stringa quando coniano un token. Per saperne di più, consulta Utilizzo dei token ID Google per autenticare gli utenti.

Crea la configurazione API:

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

Sostituisci quanto segue:

  • CONFIG_ID: un ID per la configurazione API
  • API_ID: l'ID dell'API. Se l'API non esiste, il comando la crea.

Crea il gateway

Crea un gateway di streaming dalla configurazione API:

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

Sostituisci quanto segue:

Quando il gateway è pronto, recupera il relativo nome host:

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

Ottieni un token ID per il chiamante

Un account utente non può scegliere il pubblico del proprio token ID, quindi l'esempio genera il token per un account di servizio di cui impersoni l'identità. Per il chiamante, utilizza un account di servizio esistente o creane uno. Per ulteriori informazioni, consulta Crea service account. Concediti il ruolo Creatore token account di servizio (roles/iam.serviceAccountTokenCreator) su quel service account, che gcloud CLI deve impersonare:

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

Sostituisci quanto segue:

  • CALLER_SERVICE_ACCOUNT_EMAIL: l'indirizzo email del account di servizio che chiama il gateway
  • USER_EMAIL: il tuo indirizzo email

Invia una richiesta di streaming

Invia una richiesta di completamento della chat che imposta "stream": true, con un token ID per l'account di servizio del chiamante nell'intestazione Authorization. Il flag -N disattiva il buffering dell'output in curl, in modo che ogni evento venga stampato quando arriva:

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
    }'

Sostituisci quanto segue:

  • DEFAULT_HOSTNAME: il nome host del gateway
  • CALLER_SERVICE_ACCOUNT_EMAIL: il account di servizio del passaggio precedente
  • MODEL_NAME: il modello di cui hai eseguito il deployment, ad esempio google/gemma-4-E4B-it

La risposta è uno stream SSE. Il primo evento ha il ruolo assistant, ogni evento successivo contiene la parte successiva della risposta e l'ultimo evento prima di data: [DONE] imposta finish_reason. L'output è simile al seguente:

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]

Esegui la pulizia

Per evitare che al tuo account Google Cloud vengano addebitati costi relativi alle risorse utilizzate in questo esempio, elimina il gateway e la configurazione API:

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

Se hai creato l'API per questo esempio, eliminala:

gcloud api-gateway apis delete API_ID

Elimina il servizio Cloud Run:

gcloud run services delete SERVICE_NAME \
    --region=REGION

Prezzi

Durante l'anteprima pubblica dello streaming, ai clienti non vengono addebitati costi per il traffico in uscita dalla rete sui gateway abilitati per lo streaming. Tuttavia, la fatturazione di Service Control viene comunque applicata a livello di API, indipendentemente dalla fase di rilascio.

Limitazioni

Durante l'Anteprima pubblica, allo streaming in API Gateway si applicano le seguenti limitazioni:

  • Immutabilità: non puoi aggiornare un gateway esistente per attivare o disattivare lo streaming. Devi creare un nuovo gateway. Tieni presente che un gateway abilitato per lo streaming riceve una forma del nome host diversa, che richiede l'aggiornamento dei client o dei record DNS. Se vuoi che aggiorniamo il record del gateway per utilizzare il nuovo formato, contatta l'assistenza. API Gateway utilizza i seguenti pattern di nome host:

    • Non in streaming: {gateway_id}-{base36_project_number}.{shard_hash}.gateway.dev, ad esempio test-gateway-4jcaz8x.uc.gateway.dev
    • Streaming: {gateway_id}-{project_number}.{region}.gateway.dev, ad esempio test-gateway-9876654321.us-central1.gateway.dev
    • Streaming (legacy): {service}-{tenant_project_number}.{region}.run.app, ad esempio test-gateway-834512064953.us-central1.run.app. I gateway creati prima che fossero disponibili i nomi host *.gateway.dev regionali mantengono questo nome host in modo permanente e non viene eseguita la migrazione al nuovo pattern.

    Un nuovo gateway abilitato per lo streaming riceve il pattern Streaming. I primi due esempi mostrano lo stesso gateway nello stesso progetto: nel pattern Streaming, il numero di progetto viene visualizzato in formato decimale anziché in base36, quindi la prima etichetta ha meno spazio rispetto a un gateway non in streaming. La prima etichetta è la stringa {gateway_id}-{project_number} combinata, che deve rientrare nel limite di 63 caratteri dell'etichetta DNS. Il limite di 49 caratteri per l'ID gateway lo mantiene entro questo limite per i numeri di progetto fino a 13 cifre; un numero di progetto più lungo richiede un ID gateway più breve.

  • Terraform: l'attivazione dello streaming tramite Terraform non è supportata (prevista per una release futura).

  • Bilanciamento del carico e domini personalizzati: i gateway con un effectiveStreamingMode di EFFECTIVE_STREAMING_MODE_ENABLED non sono compatibili con il bilanciamento del carico HTTP(S) per API Gateway o i NEG serverless. Non puoi posizionare un gateway di questo tipo dietro un NEG serverless o un bilanciatore del carico delle applicazioni esterno. Di conseguenza, i domini personalizzati (che si basano sul bilanciamento del carico) non sono supportati per questi gateway durante l'anteprima pubblica.

  • Comportamento della scadenza: l'attivazione dello streaming su un gateway non modifica il comportamento del campo deadline su un percorso SSE o di trasferimento in blocchi. La scadenza rimane un limite di tempo per la risposta completa, quindi uno stream viene interrotto una volta trascorsa la scadenza, indipendentemente dalla quantità di dati che sta inviando. Il valore predefinito è 15 secondi e il valore massimo è 3600 secondi. Su un WebSocket, deadline limita invece l'intervallo tra i messaggi e la connessione termina dopo 3600 secondi. Consulta Imposta la scadenza dello stream.

  • Model Context Protocol (MCP): la creazione del gateway con --enable-streaming non genera uno stream di endpoint MCP. Le risposte MCP rimangono un unico corpo application/json, indipendentemente dalla modalità di streaming del gateway. Per maggiori dettagli, consulta Limitazioni di MCP.