Configura la transmisión para las respuestas de LLM y otro tráfico
En este documento, se describe cómo configurar la transmisión en API Gateway.
API Gateway admite transmisiones. La transmisión permite que las puertas de enlace atiendan conexiones de larga duración y transmitan datos en fragmentos para la transmisión de solicitudes y respuestas.
Un uso común de la transmisión es la publicación de un modelo de lenguaje grande (LLM). El modelo envía su respuesta de a un token por vez, por lo que un cliente puede mostrar el texto mientras el modelo aún lo está generando. Para ver un ejemplo completo que transmita respuestas de un modelo de Gemma que vLLM entrega en Cloud Run, consulta Transmite respuestas desde un LLM.
Protocolos de transmisión compatibles
Cuando está habilitado, API Gateway admite los siguientes métodos de transmisión:
- Entrega de respuestas incrementales: Se utilizan tramas DATA de HTTP/2 o codificación de transferencia fragmentada de HTTP/1.1, según lo que negocie el cliente.
- Eventos enviados por el servidor (SSE): Transmisión unidireccional del servidor al cliente.
- WebSockets: Canales de comunicación dúplex completos a través de una sola conexión TCP.
- Transmisión bidireccional de gRPC: Transmisión dúplex completa con gRPC.
Requisitos previos
Antes de usar la transmisión, asegúrate de que tu servicio de backend admita el protocolo requerido (por ejemplo, HTTP/2 o WebSockets) y de que la configuración de la API esté configurada correctamente.
Configura el protocolo de backend
Para admitir el tráfico de transmisión, debes configurar el protocolo de tu backend según el tipo de transmisión:
- gRPC: Debes configurar tu backend para que use HTTP/2 (
h2). - WebSockets: Debes usar
http/1.1. WebSockets requiere el protocolo de enlaceConnection: UpgradeHTTP/1.1. - Eventos enviados por el servidor (SSE) y entrega de respuestas incrementales: Tu backend puede usar HTTP/1.1 o HTTP/2 (
h2). Recomendamos HTTP/2 (h2) para mejorar el rendimiento.
En tu especificación de OpenAPI, configura el protocolo de backend de la siguiente manera:
Ejemplo (OpenAPI 3.x)
Configura el campo protocol en la definición del backend con nombre dentro del objeto x-google-api-management.backends. También debes hacer referencia a este backend con x-google-backend a nivel de la raíz o de la operación.
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
Ejemplo (OpenAPI 2.0)
Configura el campo protocol en la extensión x-google-backend.
x-google-backend:
address: https://my-gemma-service.run.app
protocol: h2 # Use 'http/1.1' for WebSockets
Cómo establecer la fecha límite de la transmisión
El campo deadline rige la duración de una solicitud (unaria o de transmisión).
En la siguiente tabla, se muestra cómo se aplican los tiempos de espera a cada tipo de solicitud:
| Método | Tiempo de espera de inactividad (intervalo máximo entre mensajes) |
Tiempo de espera de la solicitud (duración total máxima de la solicitud) |
|---|---|---|
| Sin transmisión | N/A: El tiempo de espera por inactividad solo se aplica a las transmisiones. | El valor predeterminado es de 15 segundos. Establece deadline para cambiarlo (hasta 3,600 segundos para las puertas de enlace habilitadas para la transmisión). |
| Transmisión por HTTP (SSE, transferencia fragmentada) |
N/A: Efectivamente infinito; solo el tiempo de espera de la solicitud finaliza la transmisión | El valor predeterminado es de 15 segundos. Establece deadline para cambiarlo (hasta 3,600 segundos para las puertas de enlace habilitadas para la transmisión). |
| Transmisión a través de gRPC o WebSockets | El valor predeterminado es de 300 segundos. Establece deadline para cambiarlo hasta 3,600 segundos para las puertas de enlace habilitadas para la transmisión. En WebSockets, se ignora un deadline de menos de 300 segundos y se aplica un mínimo de 300 segundos. |
Siempre es de 3,600 segundos para las puertas de enlace habilitadas para la transmisión, no se puede configurar. |
Ejemplo (OpenAPI 3.x)
Establece el campo deadline en la definición del backend con nombre.
x-google-api-management:
backends:
gemma:
address: https://my-gemma-service.run.app
protocol: h2
deadline: 3600.0
x-google-backend: gemma
Ejemplo (OpenAPI 2.0)
Configura el campo deadline en la extensión x-google-backend.
x-google-backend:
address: https://my-gemma-service.run.app
protocol: h2
deadline: 3600.0
Para conocer los otros límites que se aplican a las conexiones de transmisión, consulta Limitaciones.
Habilita la transmisión en una puerta de enlace
La transmisión se especifica en el momento de la creación de la puerta de enlace. Ten en cuenta el siguiente comportamiento:
- No hay inhabilitación explícita: No hay una marca para inhabilitar explícitamente la transmisión. Si omites la marca
--enable-streaming, API Gateway resuelve el modo en la creación a partir de la configuración de la API y el valor predeterminado de la plataforma: una configuración de API que configura un Model Router siempre produce una puerta de enlace de transmisión. Lee el campoeffectiveStreamingModede solo salida de la puerta de enlace para ver el modo con el que se creó. - Inmutabilidad: El modo de transmisión se fija en el momento de la creación y no se puede modificar más adelante.
Para especificar la transmisión en una puerta de enlace, usa la marca --enable-streaming con el comando gcloud api-gateway gateways create:
gcloud api-gateway gateways create GATEWAY_ID \
--api=API_ID \
--api-config=CONFIG_ID \
--location=GCP_REGION \
--enable-streamingPara obtener más información sobre las opciones de implementación de la puerta de enlace, consulta Implementa una API en una puerta de enlace.
Propiedades de transmisión de la puerta de enlace
Los siguientes campos del recurso de Gateway controlan el comportamiento de transmisión:
| Campo | Atributos | Valores |
|---|---|---|
streamingMode |
Cadena (INMUTABLE, OPCIONAL) |
|
effectiveStreamingMode |
Cadena (solo salida) |
|
Cuando usas la API de REST para crear una puerta de enlace, puedes especificar la transmisión en el cuerpo de la solicitud:
{
"apiConfig": "projects/...",
"streamingMode": "STREAMING_MODE_ENABLED"
}
Verifica que la transmisión esté habilitada
Para confirmar si la transmisión está activa en tu puerta de enlace, descríbela con gcloud CLI:
gcloud api-gateway gateways describe GATEWAY_ID \
--location=GCP_REGIONBusca el campo effectiveStreamingMode en el resultado. Si la transmisión está habilitada, el resultado incluye lo siguiente:
effectiveStreamingMode: EFFECTIVE_STREAMING_MODE_ENABLED
Transmite respuestas desde un LLM
En este ejemplo, se coloca una puerta de enlace de transmisión frente a un modelo de Gemma que vLLM entrega en Cloud Run y transmite una finalización de chat a través de la puerta de enlace. vLLM entrega una API compatible con OpenAI que transmite respuestas como eventos enviados por el servidor (SSE).
Antes de comenzar, completa la sección Configura el entorno de desarrollo, incluida la sección Configura la cuenta de servicio que se usa para crear configuraciones de API. La puerta de enlace usa esa cuenta de servicio para llamar al servicio de Cloud Run.
Implementa el modelo
Implementa un modelo de Gemma siguiendo los pasos de Implementa un modelo de Gemma 4 con un contenedor de vLLM. Toma nota del nombre del servicio, la URL del servicio, la región y el nombre del modelo que implementas, como google/gemma-4-E4B-it.
Otorga acceso a la puerta de enlace al servicio
En la guía, se implementa el servicio con --no-allow-unauthenticated. La puerta de enlace llama al servicio con un token de ID para su cuenta de servicio, que pasas como --backend-auth-service-account cuando creas la configuración de la API. Otorga a esa cuenta de servicio el rol de Invocador de Cloud Run (roles/run.invoker) en el servicio:
gcloud run services add-iam-policy-binding SERVICE_NAME \
--region=REGION \
--member=serviceAccount:SERVICE_ACCOUNT_EMAIL \
--role=roles/run.invokerReemplaza lo siguiente:
SERVICE_NAME: Es el nombre del servicio de Cloud Run.REGION: Es la región en la que implementaste el servicio.SERVICE_ACCOUNT_EMAIL: La dirección de correo electrónico de la cuenta de servicio de la puerta de enlace
Crea la configuración de API
Guarda la siguiente especificación de OpenAPI como gemma-api.yaml y reemplaza https://my-gemma-service.run.app por la URL de tu servicio:
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.
El deadline de 570 segundos es 30 segundos más corto que el --timeout 600 que establece la guía de Gemma en el servicio. Como resultado, el deadline de la puerta de enlace, no el tiempo de espera del servicio, finaliza una transmisión que se ejecuta durante demasiado tiempo. Un x-google-backend de nivel superior tiene el valor predeterminado pathTranslation: APPEND_PATH_TO_ADDRESS. La puerta de enlace agrega la ruta de la solicitud a la dirección de backend, por lo que una solicitud a /v1/chat/completions llega al extremo de finalización de chat de vLLM.
El requisito security hace que la puerta de enlace rechace cualquier solicitud que no incluya un token de ID firmado por Google con el público gemma-api. Puedes elegir una cadena de público diferente, siempre y cuando los llamantes soliciten la misma cuando generen un token. Para obtener más información, consulta Cómo usar tokens de ID de Google para autenticar usuarios.
Crea la configuración de API:
gcloud api-gateway api-configs create CONFIG_ID \
--api=API_ID \
--openapi-spec=gemma-api.yaml \
--backend-auth-service-account=SERVICE_ACCOUNT_EMAILReemplaza lo siguiente:
CONFIG_ID: Es un ID para la configuración de la API.API_ID: Es el ID de la API. Si la API no existe, el comando la crea.
Crea la puerta de enlace
Crea una puerta de enlace de transmisión a partir de la configuración de la API:
gcloud api-gateway gateways create GATEWAY_ID \
--api=API_ID \
--api-config=CONFIG_ID \
--location=GCP_REGION \
--enable-streamingReemplaza lo siguiente:
GATEWAY_ID: Es un ID para la puerta de enlace.GCP_REGION: Es la región de la puerta de enlace, que puede diferir deREGION. Para obtener los valores permitidos, consulta Implementa una API en una puerta de enlace.
Cuando la puerta de enlace esté lista, obtén su nombre de host:
gcloud api-gateway gateways describe GATEWAY_ID \
--location=GCP_REGION \
--format="value(defaultHostname)"Obtén un token de ID para la persona que llama
Una cuenta de usuario no puede elegir el público de su token de ID, por lo que el ejemplo emite el token para una cuenta de servicio que suplantas. Para el llamador, usa una cuenta de servicio existente o crea una. Para obtener más información, consulta Crea cuentas de servicio. Otorga el rol de creador de tokens de cuenta de servicio (roles/iam.serviceAccountTokenCreator) en esa cuenta de servicio, que gcloud CLI necesita para suplantarla:
gcloud iam service-accounts add-iam-policy-binding CALLER_SERVICE_ACCOUNT_EMAIL \
--member=user:USER_EMAIL \
--role=roles/iam.serviceAccountTokenCreatorReemplaza lo siguiente:
CALLER_SERVICE_ACCOUNT_EMAIL: La dirección de correo electrónico de la cuenta de servicio que llama a la puerta de enlaceUSER_EMAIL: tu dirección de correo electrónico
Envía una solicitud de transmisión
Envía una solicitud de finalización de chat que establezca "stream": true, con un token de ID para la cuenta de servicio del llamador en el encabezado Authorization. La marca -N desactiva el almacenamiento en búfer de salida en curl, por lo que cada evento se imprime cuando llega:
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
}'Reemplaza lo siguiente:
DEFAULT_HOSTNAME: Es el nombre de host de la puerta de enlace.CALLER_SERVICE_ACCOUNT_EMAIL: La cuenta de servicio del paso anteriorMODEL_NAME: Es el modelo que implementaste, comogoogle/gemma-4-E4B-it.
La respuesta es una transmisión de SSE. El primer evento tiene el rol assistant, cada evento posterior contiene la siguiente parte de la respuesta y el último evento antes de data: [DONE] establece finish_reason. El resultado es similar a lo siguiente:
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]
Realiza una limpieza
Para evitar que se apliquen cargos a tu cuenta de Google Cloud por los recursos que usaste en este ejemplo, borra la puerta de enlace y la configuración de la API:
gcloud api-gateway gateways delete GATEWAY_ID \
--location=GCP_REGIONgcloud api-gateway api-configs delete CONFIG_ID \
--api=API_IDSi creaste la API para este ejemplo, bórrala:
gcloud api-gateway apis delete API_ID
Borra el servicio de Cloud Run:
gcloud run services delete SERVICE_NAME \
--region=REGIONPrecios
Durante la versión preliminar pública de la transmisión, a los clientes no se les cobra la salida de red en las puertas de enlace habilitadas para la transmisión. Sin embargo, la facturación de Control de servicios sigue aplicándose a nivel de API, independientemente de la fase de lanzamiento.
Limitaciones
Las siguientes limitaciones se aplican a la transmisión en API Gateway durante la versión preliminar pública:
Inmutabilidad: No puedes actualizar una puerta de enlace existente para habilitar o inhabilitar la transmisión. Debes crear una puerta de enlace nueva. Ten en cuenta que una puerta de enlace habilitada para la transmisión recibe una forma diferente de nombre de host, por lo que debes actualizar tus clientes o registros DNS. Si quieres que actualicemos tu registro de puerta de enlace para que use el nuevo formato, comunícate con el equipo de asistencia al cliente. API Gateway usa los siguientes patrones de nombres de host:
- Sin transmisión:
{gateway_id}-{base36_project_number}.{shard_hash}.gateway.dev, por ejemplo,test-gateway-4jcaz8x.uc.gateway.dev - Transmisión:
{gateway_id}-{project_number}.{region}.gateway.dev, por ejemplo,test-gateway-9876654321.us-central1.gateway.dev - Transmisión (heredada):
{service}-{tenant_project_number}.{region}.run.app, por ejemplo,test-gateway-834512064953.us-central1.run.app. Las puertas de enlace creadas antes de que estuvieran disponibles los nombres de host regionales de*.gateway.devconservan este nombre de host de forma permanente y no se migran al nuevo patrón.
Una nueva puerta de enlace compatible con la transmisión recibe el patrón Streaming. Los dos primeros ejemplos son la misma puerta de enlace en el mismo proyecto: en el patrón Streaming, el número de proyecto aparece en decimal en lugar de base36, por lo que la primera etiqueta tiene menos espacio que en una puerta de enlace que no es de transmisión. La primera etiqueta es la cadena
{gateway_id}-{project_number}combinada, que debe ajustarse al límite de 63 caracteres de la etiqueta de DNS. El límite de 49 caracteres para el ID de la puerta de enlace lo mantiene dentro de ese límite para los números de proyecto de hasta 13 dígitos. Un número de proyecto más largo requiere un ID de puerta de enlace más corto.- Sin transmisión:
Terraform: No se admite la habilitación de la transmisión con Terraform (se planea para una versión futura).
Balanceo de cargas y dominios personalizados: Las puertas de enlace con un
effectiveStreamingModedeEFFECTIVE_STREAMING_MODE_ENABLEDno son compatibles con el balanceo de cargas de HTTP(S) para API Gateway ni con los NEG sin servidores. No puedes colocar una puerta de enlace de este tipo detrás de un NEG sin servidores o un balanceador de cargas de aplicaciones externo. Por lo tanto, los dominios personalizados (que dependen del balanceo de cargas) no son compatibles con estas puertas de enlace durante la versión preliminar pública.Comportamiento de fecha límite: Habilitar la transmisión en una puerta de enlace no cambia el comportamiento del campo
deadlineen una ruta de transferencia fragmentada o de SSE. La fecha límite sigue siendo un límite de tiempo real para la respuesta completa, por lo que se corta una transmisión una vez que vence la fecha límite, independientemente de la cantidad de datos que esté enviando. El valor predeterminado es de 15 segundos y el máximo es de 3,600 segundos. En un WebSocket,deadlinelimita la brecha entre los mensajes, y la conexión finaliza después de 3,600 segundos. Consulta Cómo establecer la fecha límite de la transmisión.Protocolo de contexto del modelo (MCP): La creación de la puerta de enlace con
--enable-streamingno genera una transmisión de extremo de MCP. Las respuestas de MCP siguen siendo un solo cuerpo deapplication/json, independientemente del modo de transmisión de la puerta de enlace. Para obtener más información, consulta Limitaciones de MCP.