Configurare 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 esecuzione prolungata e trasmettere i dati in blocchi sia per lo streaming di richieste che di risposte.

Un utilizzo comune dello streaming è la pubblicazione 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 che vLLM gestisce su Cloud Run, vedi Trasmettere in streaming le risposte di un LLM.

Protocolli di streaming supportati

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

  • Invio incrementale delle risposte: frame DATA HTTP/2 o codifica di trasferimento in blocchi HTTP/1.1, a seconda di ciò che negozia il client.
  • 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 utilizzando 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. WebSocket richiede l'handshake HTTP/1.1 Connection: Upgrade.
  • Eventi inviati dal server (SSE) e distribuzione incrementale delle risposte: il backend può utilizzare HTTP/1.1 o HTTP/2 (h2). Per migliorare le prestazioni, consigliamo HTTP/2 (h2).

Nella specifica OpenAPI, configura il protocollo di backend nel seguente modo:

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 radice o 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

Impostare la scadenza dello stream

Il campo deadline determina la durata di esecuzione di una richiesta (unaria o di streaming).

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

Metodo Timeout per inattività
(intervallo massimo tra i messaggi)
Timeout 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 allo streaming
Streaming over 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 allo streaming
Streaming su gRPC o WebSocket Valore predefinito 300 secondi; imposta deadline per modificarlo, fino a 3600 secondi per i gateway abilitati allo streaming. Su WebSocket, un deadline inferiore a 300 secondi viene ignorato e viene applicato un minimo di 300 secondi Sempre 3600 secondi per i gateway abilitati allo streaming, non configurabili

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 applicabili alle connessioni di streaming, vedi Limitazioni.

Abilitare lo streaming su un gateway

Lo streaming viene specificato al momento della creazione del gateway. Tieni presente quanto segue:

  • Nessuna disattivazione esplicita: non esiste alcun 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 di modelli produce sempre un gateway di streaming. Leggi il campo effectiveStreamingMode di sola uscita del gateway per vedere la modalità con cui è stato creato.
  • Immutabilità: la modalità di streaming è fissa 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 ulteriori informazioni sulle opzioni di deployment del gateway, consulta Esegui il deployment di un'API su un gateway.

Proprietà di streaming del gateway

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

Campo Attributi Valori
streamingMode Stringa (IMMUTABILE, FACOLTATIVO)
  • STREAMING_MODE_UNSPECIFIED (impostazione predefinita: 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 gateway, descrivilo 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

Mostrare gradualmente le risposte di un LLM

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

Prima di iniziare, completa la procedura Configurare l'ambiente di sviluppo, inclusa la Configurazione del 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 la procedura descritta in Eseguire 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 che implementi, 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 suo 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 è 30 secondi più breve del valore --timeout 600 impostato dalla guida di Gemma sul servizio. Di conseguenza, è il deadline del gateway, non il timeout del servizio, a interrompere uno stream che viene eseguito troppo a lungo. Un x-google-backend di primo livello ha come valore predefinito pathTranslation: APPEND_PATH_TO_ADDRESS. L'app gateway aggiunge il percorso della richiesta all'indirizzo backend, quindi una richiesta a /v1/chat/completions raggiunge l'endpoint di completamento della chat vLLM.

Il requisito security fa sì che il gateway rifiuti qualsiasi richiesta che non includa un token ID firmato da Google con il pubblico gemma-api. Puoi scegliere una stringa del segmento di pubblico diversa, a condizione che i chiamanti richiedano la stessa quando generano un token. Per saperne di più, consulta Utilizzare i 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 suo nome host:

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

Recuperare un token ID per il chiamante

Un account utente non può scegliere il pubblico del proprio token ID, quindi l'esempio crea il token per un account di servizio di cui simuli l'identità. Per il chiamante, utilizza un account di servizio esistente o creane uno. Per saperne di più, vedi Creare service account. Concediti il ruolo Service Account Token Creator (roles/iam.serviceAccountTokenCreator) per questo account di servizio, che gcloud CLI deve rappresentare:

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

Inviare una richiesta di streaming

Invia una richiesta di completamento della chat che imposta "stream": true, con un token ID per il account di servizio del chiamante nell'intestazione Authorization. Il flag -N disattiva il buffering dell'output in curl, quindi ogni evento viene 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 che hai implementato, ad esempio google/gemma-4-E4B-it

La risposta è un flusso 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 viene addebitato l'output di rete sui gateway abilitati allo 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 allo streaming riceve un nome host di forma diversa, il che richiede l'aggiornamento dei client o dei record DNS. Se vuoi che aggiorniamo il record del gateway in modo che utilizzi il nuovo formato, contatta l'assistenza. API Gateway utilizza i seguenti pattern di nome host:

    • Non 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 regionali *.gateway.dev mantengono questo nome host in modo permanente e non vengono migrati al nuovo pattern.

    Un nuovo gateway abilitato allo streaming riceve il pattern Streaming. I primi due esempi sono lo stesso gateway nello stesso progetto: nel pattern Streaming il numero di progetto viene visualizzato in formato decimale anziché in base 36, quindi la prima etichetta ha meno spazio rispetto a un gateway non di streaming. La prima etichetta è la stringa {gateway_id}-{project_number} combinata, che deve rispettare il limite di 63 caratteri dell'etichetta DNS. Il limite di 49 caratteri per l'ID gateway consente di rispettare 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 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 delimita invece l'intervallo tra i messaggi e la connessione termina dopo 3600 secondi. Vedi Impostare la scadenza dello stream.

  • Model Context Protocol (MCP): la creazione del gateway con --enable-streaming non crea un flusso 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.