Configurer le streaming pour les réponses LLM et d'autres types de trafic
Ce document explique comment configurer le streaming dans API Gateway.
API Gateway est compatible avec le streaming. Le streaming permet aux passerelles de gérer les connexions de longue durée et de transmettre les données par blocs pour le streaming des requêtes et des réponses.
Le streaming est souvent utilisé pour diffuser un grand modèle de langage (LLM). Le modèle envoie sa réponse un jeton à la fois, ce qui permet à un client d'afficher le texte pendant que le modèle le génère. Pour obtenir un exemple complet de diffusion en flux continu des réponses d'un modèle Gemma que vLLM diffuse sur Cloud Run, consultez Diffuser les réponses d'un LLM en flux continu.
Protocoles de streaming compatibles
Lorsqu'il est activé, API Gateway est compatible avec les méthodes de streaming suivantes :
- Diffusion incrémentielle des réponses : trames DATA HTTP/2 ou encodage par transfert segmenté HTTP/1.1, selon ce que le client négocie.
- Événements envoyés par le serveur (SSE) : flux unidirectionnel du serveur vers le client.
- WebSockets : canaux de communication en duplex intégral sur une seule connexion TCP.
- Streaming bidirectionnel gRPC : streaming en duplex intégral à l'aide de gRPC.
Prérequis
Avant de pouvoir utiliser le streaming, assurez-vous que votre service de backend est compatible avec le protocole requis (par exemple, HTTP/2 ou WebSockets) et que la configuration de votre API est correcte.
Configurer le protocole de backend
Pour accepter le trafic de streaming, vous devez configurer le protocole de votre backend en fonction du type de streaming :
- gRPC : vous devez configurer votre backend pour qu'il utilise HTTP/2 (
h2). - WebSockets : vous devez utiliser
http/1.1. Les WebSockets nécessitent le handshake HTTP/1.1Connection: Upgrade. - Événements envoyés par le serveur (SSE) et diffusion incrémentielle des réponses : votre backend peut utiliser HTTP/1.1 ou HTTP/2 (
h2). Nous vous recommandons d'utiliser HTTP/2 (h2) pour améliorer les performances.
Dans votre spécification OpenAPI, configurez le protocole de backend comme suit :
Exemple (OpenAPI 3.x)
Définissez le champ protocol dans la définition du backend nommé au sein de l'objet x-google-api-management.backends. Vous devez également faire référence à ce backend à l'aide de x-google-backend au niveau racine ou de l'opération.
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
Exemple (OpenAPI 2.0)
Définissez le champ protocol dans l'extension x-google-backend.
x-google-backend:
address: https://my-gemma-service.run.app
protocol: h2 # Use 'http/1.1' for WebSockets
Définir le délai de diffusion
Le champ deadline régit la durée d'exécution d'une requête (unaire ou de streaming).
Le tableau suivant indique comment les délais s'appliquent à chaque type de requête :
| Méthode | Délai d'inactivité (écart maximal entre les messages) |
Délai avant expiration de la requête (durée totale maximale de la requête) |
|---|---|---|
| Sans streaming | N/A : le délai d'inactivité ne s'applique qu'aux flux. | La valeur par défaut est de 15 secondes. Définissez deadline pour la modifier (jusqu'à 3 600 secondes pour les passerelles compatibles avec le streaming). |
| Streaming sur HTTP (SSE, transfert par blocs) |
N/A : durée infinie. Seul le délai d'expiration de la requête met fin au flux. | 15 secondes par défaut. Définissez deadline pour le modifier (jusqu'à 3 600 secondes pour les passerelles compatibles avec le streaming). |
| Streaming sur gRPC ou WebSockets | La valeur par défaut est de 300 secondes. Définissez deadline pour la modifier (jusqu'à 3 600 secondes pour les passerelles compatibles avec le streaming). Sur WebSockets, un deadline inférieur à 300 secondes est ignoré et un minimum de 300 secondes s'applique. |
Toujours 3 600 secondes pour les passerelles compatibles avec le streaming, non configurable |
Exemple (OpenAPI 3.x)
Définissez le champ deadline dans la définition du backend nommé.
x-google-api-management:
backends:
gemma:
address: https://my-gemma-service.run.app
protocol: h2
deadline: 3600.0
x-google-backend: gemma
Exemple (OpenAPI 2.0)
Définissez le champ deadline dans l'extension x-google-backend.
x-google-backend:
address: https://my-gemma-service.run.app
protocol: h2
deadline: 3600.0
Pour connaître les autres limites qui s'appliquent aux connexions de streaming, consultez Limites.
Activer le streaming sur une passerelle
Le streaming est spécifié au moment de la création de la passerelle. Notez le comportement suivant :
- Aucune désactivation explicite : il n'existe aucun indicateur permettant de désactiver explicitement le streaming. Si vous omettez l'indicateur
--enable-streaming, API Gateway résout le mode lors de la création à partir de la configuration de l'API et de la plate-forme par défaut : une configuration d'API qui configure un routeur de modèle produit toujours une passerelle de streaming. Lisez le champeffectiveStreamingModede la passerelle (sortie uniquement) pour voir le mode avec lequel elle a été créée. - Immuabilité : le mode de streaming est fixe lors de la création et ne peut pas être modifié ultérieurement.
Pour spécifier le streaming sur une passerelle, utilisez le flag --enable-streaming avec la commande gcloud api-gateway gateways create :
gcloud api-gateway gateways create GATEWAY_ID \
--api=API_ID \
--api-config=CONFIG_ID \
--location=GCP_REGION \
--enable-streamingPour en savoir plus sur les options de déploiement de passerelle, consultez Déployer une API sur une passerelle.
Propriétés de streaming de la passerelle
Les champs suivants de la ressource Gateway contrôlent le comportement du streaming :
| Champ | Attributs | Valeurs |
|---|---|---|
streamingMode |
Chaîne (IMMUTABLE, FACULTATIF) |
|
effectiveStreamingMode |
Chaîne (OUTPUT_ONLY) |
|
Lorsque vous utilisez l'API REST pour créer une passerelle, vous pouvez spécifier le streaming dans le corps de la requête :
{
"apiConfig": "projects/...",
"streamingMode": "STREAMING_MODE_ENABLED"
}
Vérifier que le streaming est activé
Pour vérifier si le streaming est actif sur votre passerelle, décrivez-la à l'aide de gcloud CLI :
gcloud api-gateway gateways describe GATEWAY_ID \
--location=GCP_REGIONRecherchez le champ effectiveStreamingMode dans le résultat. Si le streaming est activé, le résultat inclut les éléments suivants :
effectiveStreamingMode: EFFECTIVE_STREAMING_MODE_ENABLED
Diffuser des réponses à partir d'un LLM
Cet exemple place une passerelle de streaming devant un modèle Gemma que vLLM diffuse sur Cloud Run, et diffuse une complétion de chat via la passerelle. vLLM diffuse une API compatible avec OpenAI qui diffuse les réponses sous forme d'événements envoyés par le serveur (SSE).
Avant de commencer, suivez la procédure Configurer l'environnement de développement, y compris Configurer le compte de service utilisé pour créer des configurations d'API. La passerelle utilise ce compte de service pour appeler le service Cloud Run.
Déployer le modèle
Déployez un modèle Gemma en suivant Déployer un modèle Gemma 4 avec un conteneur vLLM. Notez le nom du service, l'URL du service, la région et le nom du modèle que vous déployez, par exemple google/gemma-4-E4B-it.
Accorder à la passerelle l'accès au service
Le guide déploie le service avec --no-allow-unauthenticated. La passerelle appelle le service avec un jeton d'identité pour son compte de service, que vous transmettez en tant que --backend-auth-service-account lorsque vous créez la configuration de l'API. Accordez à ce compte de service le rôle Demandeur Cloud Run (roles/run.invoker) sur le service :
gcloud run services add-iam-policy-binding SERVICE_NAME \
--region=REGION \
--member=serviceAccount:SERVICE_ACCOUNT_EMAIL \
--role=roles/run.invokerRemplacez les éléments suivants :
SERVICE_NAME: nom du service Cloud Run.REGION: région dans laquelle vous avez déployé le serviceSERVICE_ACCOUNT_EMAIL: adresse e-mail du compte de service de la passerelle
Créer la configuration de l'API
Enregistrez la spécification OpenAPI suivante sous le nom gemma-api.yaml, en remplaçant https://my-gemma-service.run.app par l'URL de votre service :
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.
Le deadline de 570 secondes est 30 secondes plus court que le --timeout 600 défini par le guide Gemma sur le service. Par conséquent, c'est le deadline de la passerelle, et non le délai avant expiration du service, qui met fin à un flux trop long. Un x-google-backend de premier niveau est défini par défaut sur pathTranslation: APPEND_PATH_TO_ADDRESS. L'application de passerelle ajoute le chemin d'accès à la requête à l'adresse du backend. Par conséquent, une requête adressée à /v1/chat/completions atteint le point de terminaison de complétion de chat vLLM.
L'exigence security permet à la passerelle de refuser toute requête qui ne comporte pas de jeton d'ID signé par Google avec l'audience gemma-api. Vous pouvez choisir une autre chaîne d'audience, à condition que les appelants demandent la même lorsqu'ils génèrent un jeton. Pour en savoir plus, consultez Utiliser des jetons d'identité Google pour authentifier les utilisateurs.
Créez la configuration de l'API :
gcloud api-gateway api-configs create CONFIG_ID \
--api=API_ID \
--openapi-spec=gemma-api.yaml \
--backend-auth-service-account=SERVICE_ACCOUNT_EMAILRemplacez les éléments suivants :
CONFIG_ID: ID de la configuration de l'APIAPI_ID: ID de l'API. Si l'API n'existe pas, la commande la crée.
Créer la passerelle
Créez une passerelle de streaming à partir de la configuration de l'API :
gcloud api-gateway gateways create GATEWAY_ID \
--api=API_ID \
--api-config=CONFIG_ID \
--location=GCP_REGION \
--enable-streamingRemplacez les éléments suivants :
GATEWAY_ID: ID de la passerelleGCP_REGION: région de la passerelle, qui peut être différente deREGION. Pour connaître les valeurs autorisées, consultez Déployer une API sur une passerelle.
Lorsque la passerelle est prête, récupérez son nom d'hôte :
gcloud api-gateway gateways describe GATEWAY_ID \
--location=GCP_REGION \
--format="value(defaultHostname)"Obtenir un jeton d'identification pour l'appelant
Un compte utilisateur ne peut pas choisir l'audience de son jeton d'identité. L'exemple crée donc le jeton pour un compte de service dont vous empruntez l'identité. Pour l'appelant, utilisez un compte de service existant ou créez-en un. Pour en savoir plus, consultez la section Créer des comptes de service. Attribuez-vous le rôle Créateur de jetons du compte de service (roles/iam.serviceAccountTokenCreator) sur ce compte de service, dont la gcloud CLI a besoin pour l'emprunter :
gcloud iam service-accounts add-iam-policy-binding CALLER_SERVICE_ACCOUNT_EMAIL \
--member=user:USER_EMAIL \
--role=roles/iam.serviceAccountTokenCreatorRemplacez les éléments suivants :
CALLER_SERVICE_ACCOUNT_EMAIL: adresse e-mail du compte de service qui appelle la passerelleUSER_EMAIL: votre adresse e-mail.
Envoyer une demande de streaming
Envoyez une requête de complétion de conversation qui définit "stream": true, avec un jeton d'identité pour le compte de service de l'appelant dans l'en-tête Authorization. L'indicateur -N désactive la mise en mémoire tampon de la sortie dans curl. Chaque événement est donc imprimé à son arrivée :
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
}'Remplacez les éléments suivants :
DEFAULT_HOSTNAME: nom d'hôte de la passerelleCALLER_SERVICE_ACCOUNT_EMAIL: compte de service de l'étape précédenteMODEL_NAME: modèle que vous avez déployé, tel quegoogle/gemma-4-E4B-it
La réponse est un flux SSE. Le premier événement porte le rôle assistant, chaque événement ultérieur porte la partie suivante de la réponse, et le dernier événement avant data: [DONE] définit finish_reason. Le résultat ressemble à ce qui suit :
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]
Effectuer un nettoyage
Pour éviter que les ressources utilisées dans cet exemple ne soient facturées sur votre compte Google Cloud , supprimez la passerelle et la configuration de l'API :
gcloud api-gateway gateways delete GATEWAY_ID \
--location=GCP_REGIONgcloud api-gateway api-configs delete CONFIG_ID \
--api=API_IDSi vous avez créé l'API pour cet exemple, supprimez-la :
gcloud api-gateway apis delete API_ID
Supprimez le service Cloud Run :
gcloud run services delete SERVICE_NAME \
--region=REGIONTarifs
Pendant la version Preview publique du streaming, les clients ne sont pas facturés pour la sortie réseau sur les passerelles compatibles avec le streaming. Toutefois, la facturation Service Control s'applique toujours au niveau de l'API, quelle que soit la phase de publication.
Limites
Les limites suivantes s'appliquent au streaming dans API Gateway pendant la version Preview publique :
Immuabilité : vous ne pouvez pas mettre à jour une passerelle existante pour activer ou désactiver le streaming. Vous devez créer une passerelle. Notez qu'une passerelle compatible avec le streaming reçoit un nom d'hôte différent, ce qui vous oblige à mettre à jour vos clients ou vos enregistrements DNS. Si vous souhaitez que nous mettions à jour votre enregistrement de passerelle pour utiliser le nouveau format, contactez l'assistance. API Gateway utilise les modèles de noms d'hôte suivants :
- Non-streaming :
{gateway_id}-{base36_project_number}.{shard_hash}.gateway.dev, par exempletest-gateway-4jcaz8x.uc.gateway.dev - Streaming :
{gateway_id}-{project_number}.{region}.gateway.dev, par exempletest-gateway-9876654321.us-central1.gateway.dev - Streaming (ancienne) :
{service}-{tenant_project_number}.{region}.run.app, par exempletest-gateway-834512064953.us-central1.run.app. Les passerelles créées avant que les noms d'hôte*.gateway.devrégionaux ne soient disponibles conservent ce nom d'hôte de manière permanente et ne sont pas migrées vers le nouveau modèle.
Une nouvelle passerelle compatible avec le streaming reçoit le modèle Streaming. Les deux premiers exemples correspondent à la même passerelle dans le même projet. Dans le modèle Streaming, le numéro de projet apparaît en décimal plutôt qu'en base36. Le premier libellé dispose donc de moins d'espace que sur une passerelle non associée au streaming. Le premier libellé est la chaîne
{gateway_id}-{project_number}combinée, qui doit respecter la limite de 63 caractères pour les libellés DNS. La limite de 49 caractères pour l'ID de passerelle permet de respecter cette limite pour les numéros de projet comportant jusqu'à 13 chiffres. Si le numéro de projet est plus long, l'ID de passerelle doit être plus court.- Non-streaming :
Terraform : l'activation du streaming à l'aide de Terraform n'est pas prise en charge (prévue pour une prochaine version).
Équilibrage de charge et domaines personnalisés : les passerelles avec un
effectiveStreamingModedeEFFECTIVE_STREAMING_MODE_ENABLEDne sont pas compatibles avec l'équilibrage de charge HTTP(S) pour API Gateway ni avec les NEG sans serveur. Vous ne pouvez pas placer une telle passerelle derrière un NEG sans serveur ni un équilibreur de charge d'application externe. Par conséquent, les domaines personnalisés (qui reposent sur l'équilibrage de charge) ne sont pas compatibles avec ces passerelles pendant la version Preview publique.Comportement du délai : l'activation du streaming sur une passerelle ne modifie pas le comportement du champ
deadlinesur un chemin SSE ou de transfert segmenté. Le délai reste une limite de temps pour la réponse complète. Un flux est donc interrompu une fois le délai écoulé, quelle que soit la quantité de données qu'il envoie. La valeur par défaut est de 15 secondes et la valeur maximale est de 3 600 secondes. Sur un WebSocket,deadlinelimite plutôt l'écart entre les messages, et la connexion se termine après 3 600 secondes. Consultez Définir le délai de la diffusion.Protocole MCP (Model Context Protocol) : la création de la passerelle avec
--enable-streamingne crée pas de flux de point de terminaison MCP. Les réponses MCP restent un corpsapplication/jsonunique, quel que soit le mode de traitement en flux continu de la passerelle. Pour en savoir plus, consultez Limites du MCP.