Configurar o streaming para respostas de LLM e outros tráfegos

Neste documento, descrevemos como configurar o streaming no gateway de API.

O gateway de API é compatível com streaming. O streaming permite que os gateways atendam conexões de longa duração e transmitam dados em partes para streaming de solicitação e resposta.

Um uso comum do streaming é a veiculação de um modelo de linguagem grande (LLM). O modelo envia a resposta um token por vez, para que um cliente possa mostrar o texto enquanto o modelo ainda está gerando. Para um exemplo completo que transmite respostas de um modelo do Gemma que o vLLM disponibiliza no Cloud Run, consulte Transmitir respostas de um LLM.

Protocolos de streaming compatíveis

Quando ativado, o gateway de API é compatível com os seguintes métodos de streaming:

  • Entrega incremental de respostas: quadros DATA HTTP/2 ou codificação de transferência em blocos HTTP/1.1, dependendo do que o cliente negocia.
  • Eventos enviados pelo servidor (SSE): streaming unidirecional do servidor para o cliente.
  • WebSockets: canais de comunicação full-duplex em uma única conexão TCP.
  • Streaming bidirecional gRPC: streaming full-duplex usando gRPC.

Pré-requisitos

Antes de usar o streaming, verifique se o serviço de back-end é compatível com o protocolo necessário (por exemplo, HTTP/2 ou WebSockets) e se a configuração da API está definida corretamente.

Configurar o protocolo de back-end

Para oferecer suporte ao tráfego de streaming, configure o protocolo do back-end com base no tipo de streaming:

  • gRPC: configure seu back-end para usar HTTP/2 (h2).
  • WebSockets: use http/1.1. Os WebSockets exigem o handshake Connection: Upgrade do HTTP/1.1.
  • Eventos enviados pelo servidor (SSE) e entrega incremental de respostas: seu back-end pode usar HTTP/1.1 ou HTTP/2 (h2). Recomendamos o HTTP/2 (h2) para melhorar o desempenho.

Na especificação OpenAPI, configure o protocolo de back-end da seguinte maneira:

Exemplo (OpenAPI 3.x)

Defina o campo protocol na definição de back-end nomeada dentro do objeto x-google-api-management.backends. Você também precisa fazer referência a esse back-end usando x-google-backend na raiz ou no nível da operação.

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

Exemplo (OpenAPI 2.0)

Defina o campo protocol na extensão x-google-backend.

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

Definir o prazo do stream

O campo deadline controla por quanto tempo uma solicitação (unária ou de streaming) pode ser executada.

A tabela a seguir mostra como os tempos limite se aplicam a cada tipo de solicitação:

Método Tempo limite de inatividade
(intervalo máximo entre mensagens)
Tempo limite da solicitação
(duração total máxima da solicitação)
Não streaming N/A: o tempo limite de inatividade se aplica apenas a streams O padrão é 15 segundos. Defina deadline para mudar esse valor, até 3.600 segundos para gateways compatíveis com streaming.
Streaming por HTTP
(SSE, transferência em partes)
N/A aplicável: efetivamente infinito. Somente o tempo limite da solicitação encerra o fluxo. O padrão é 15 segundos. Defina deadline para mudar esse valor, até 3.600 segundos para gateways compatíveis com streaming.
Streaming por gRPC ou WebSockets O padrão é 300 segundos. Defina deadline para mudar esse valor, até 3.600 segundos para gateways compatíveis com streaming. Em WebSockets, um deadline de menos de 300 segundos é ignorado, e um mínimo de 300 segundos é aplicado. Sempre 3.600 segundos para gateways habilitados para streaming, não configurável

Exemplo (OpenAPI 3.x)

Defina o campo deadline na definição do back-end nomeado.

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

Exemplo (OpenAPI 2.0)

Defina o campo deadline na extensão x-google-backend.

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

Para os outros limites que se aplicam a conexões de streaming, consulte Limitações.

Ativar o streaming em um gateway

O streaming é especificado no momento da criação do gateway. Observe o seguinte comportamento:

  • Nenhuma desativação explícita: não há uma flag para desativar explicitamente o streaming. Se você omitir a flag --enable-streaming, o gateway de API vai resolver o modo na criação com base na configuração da API e no padrão da plataforma. Uma configuração de API que configura um roteador de modelo sempre produz um gateway de streaming. Leia o campo effectiveStreamingMode somente de saída do gateway para conferir o modo em que ele foi criado.
  • Imutabilidade: o modo de streaming é fixado na criação e não pode ser modificado depois.

Para especificar o streaming em um gateway, use a flag --enable-streaming com o 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

Para mais informações sobre as opções de implantação de gateway, consulte Implantar uma API em um gateway.

Propriedades de streaming do gateway

Os campos a seguir no recurso Gateway controlam o comportamento de streaming:

Campo Atributos Valores
streamingMode String (IMMUTABLE, OPTIONAL)
  • STREAMING_MODE_UNSPECIFIED (padrão: o serviço seleciona o modo)
  • STREAMING_MODE_ENABLED
effectiveStreamingMode String (OUTPUT_ONLY)
  • EFFECTIVE_STREAMING_MODE_DISABLED
  • EFFECTIVE_STREAMING_MODE_ENABLED

Ao usar a API REST para criar um gateway, é possível especificar o streaming no corpo da solicitação:

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

Verificar se o streaming está ativado

Para confirmar se o streaming está ativo no gateway, descreva-o usando a CLI gcloud:

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

Procure o campo effectiveStreamingMode na saída. Se o streaming estiver ativado, a saída vai incluir:

effectiveStreamingMode: EFFECTIVE_STREAMING_MODE_ENABLED

Transmitir respostas de um LLM

Este exemplo coloca um gateway de streaming na frente de um modelo do Gemma que o vLLM disponibiliza no Cloud Run e transmite uma conclusão de chat pelo gateway. O vLLM disponibiliza uma API compatível com a OpenAI que transmite respostas como eventos enviados pelo servidor (SSE, na sigla em inglês).

Antes de começar, conclua Configurar o ambiente de desenvolvimento, incluindo Configurar a conta de serviço usada para criar configurações de API. O gateway usa essa conta de serviço para chamar o serviço do Cloud Run.

Implantar o modelo

Implante um modelo Gemma seguindo as instruções em Implantar um modelo Gemma 4 com um contêiner vLLM. Anote o nome do serviço, o URL do serviço, a região e o nome do modelo que você implanta, como google/gemma-4-E4B-it.

Conceder ao gateway acesso ao serviço

O guia implanta o serviço com --no-allow-unauthenticated. O gateway chama o serviço com um token de ID para a conta de serviço, que você transmite como --backend-auth-service-account ao criar a configuração da API. Conceda a essa conta de serviço o papel de invocador do Cloud Run (roles/run.invoker) no serviço:

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

Substitua:

  • SERVICE_NAME: o nome do serviço do Cloud Run
  • REGION: a região em que você implantou o serviço
  • SERVICE_ACCOUNT_EMAIL: o endereço de e-mail da conta de serviço do gateway

Criar a configuração de API

Salve a especificação OpenAPI a seguir como gemma-api.yaml, substituindo https://my-gemma-service.run.app pelo URL do seu serviço:

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.

O deadline de 570 segundos é 30 segundos menor que o --timeout 600 definido pelo guia da Gemma no serviço. Como resultado, o deadline do gateway, e não o tempo limite do serviço, encerra um fluxo que dura muito tempo. Um x-google-backend de nível superior é definido como pathTranslation: APPEND_PATH_TO_ADDRESS por padrão. O gateway anexa o caminho da solicitação ao endereço do back-end. Assim, uma solicitação para /v1/chat/completions chega ao endpoint de conclusão de chat do vLLM.

O requisito security faz com que o gateway rejeite qualquer solicitação que não tenha um token de ID assinado pelo Google com o público-alvo gemma-api. Você pode escolher uma string de público-alvo diferente, desde que os autores da chamada peçam a mesma quando gerarem um token. Para mais informações, consulte Usar tokens de ID do Google para autenticar usuários.

Crie a configuração da API:

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

Substitua:

  • CONFIG_ID: um ID para a configuração da API.
  • API_ID: o ID da API. Se a API não existir, o comando vai criá-la.

Criar o gateway

Crie um gateway de streaming com a configuração de API:

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

Substitua:

  • GATEWAY_ID: um ID para o gateway
  • GCP_REGION: a região do gateway, que pode ser diferente de REGION. Para valores permitidos, consulte Implantar uma API em um gateway.

Quando o gateway estiver pronto, extraia o nome do host:

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

Receber um token de ID para o autor da chamada

Uma conta de usuário não pode escolher o público-alvo do token de ID. Por isso, o exemplo cria o token para uma conta de serviço que você representa. Para o autor da chamada, use uma conta de serviço ou crie uma. Para mais informações, consulte Criar contas de serviço. Conceda a si mesmo o papel Criador de token da conta de serviço (roles/iam.serviceAccountTokenCreator) nessa conta de serviço, que a CLI gcloud precisa representar:

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

Substitua:

  • CALLER_SERVICE_ACCOUNT_EMAIL: o endereço de e-mail da conta de serviço que chama o gateway.
  • USER_EMAIL: seu endereço de email

Enviar uma solicitação de streaming

Envie uma solicitação de conclusão de chat que defina "stream": true, com um token de ID para a conta de serviço do autor da chamada no cabeçalho Authorization. A flag -N desativa o buffer de saída em curl, para que cada evento seja impresso quando chegar:

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

Substitua:

  • DEFAULT_HOSTNAME: o nome do host do gateway
  • CALLER_SERVICE_ACCOUNT_EMAIL: a conta de serviço da etapa anterior.
  • MODEL_NAME: o modelo que você implantou, como google/gemma-4-E4B-it

A resposta é um fluxo de SSE. O primeiro evento tem a função assistant, cada evento posterior tem a próxima parte da resposta, e o último evento antes de data: [DONE] define finish_reason. O resultado será o seguinte:

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]

Limpar

Para evitar cobranças na sua conta do Google Cloud pelos recursos usados neste exemplo, exclua o gateway e a configuração da API:

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

Se você criou a API para este exemplo, exclua-a:

gcloud api-gateway apis delete API_ID

Exclua o serviço do Cloud Run:

gcloud run services delete SERVICE_NAME \
    --region=REGION

Preços

Durante o pré-lançamento público do streaming, os clientes não recebem cobranças pela saída de rede em gateways habilitados para streaming. No entanto, o faturamento do Service Control ainda se aplica no nível da API, independente da fase de lançamento.

Limitações

As seguintes limitações se aplicam ao streaming no gateway de API durante o pré-lançamento público:

  • Imutabilidade: não é possível atualizar um gateway para ativar ou desativar o streaming. Você precisa criar um novo gateway. Um gateway habilitado para streaming recebe um formato de nome de host diferente, exigindo que você atualize seus clientes ou registros DNS. Se quiser que atualizemos seu registro de gateway para usar o novo formato, entre em contato com o suporte. O gateway de API usa os seguintes padrões de nome de host:

    • Sem streaming: {gateway_id}-{base36_project_number}.{shard_hash}.gateway.dev, por exemplo, test-gateway-4jcaz8x.uc.gateway.dev
    • Streaming: {gateway_id}-{project_number}.{region}.gateway.dev, por exemplo, test-gateway-9876654321.us-central1.gateway.dev
    • Streaming (legado): {service}-{tenant_project_number}.{region}.run.app, por exemplo, test-gateway-834512064953.us-central1.run.app. Os gateways criados antes da disponibilidade dos nomes de host regionais *.gateway.dev mantêm esse nome de host permanentemente e não são migrados para o novo padrão.

    Um novo gateway habilitado para streaming recebe o padrão Streaming. Os dois primeiros exemplos são o mesmo gateway no mesmo projeto: no padrão Streaming, o número do projeto aparece em decimal em vez de base36. Portanto, o primeiro rótulo tem menos espaço do que em um gateway não streaming. O primeiro rótulo é a string {gateway_id}-{project_number} combinada, que precisa se adequar ao limite de 63 caracteres do rótulo DNS. O limite de 49 caracteres para o ID do gateway mantém o ID dentro desse limite para números de projeto de até 13 dígitos. Um número de projeto mais longo precisa de um ID do gateway mais curto.

  • Terraform: não é possível ativar o streaming usando o Terraform. Isso está previsto para uma versão futura.

  • Balanceamento de carga e domínios personalizados: gateways com um effectiveStreamingMode de EFFECTIVE_STREAMING_MODE_ENABLED não são compatíveis com o balanceamento de carga HTTP(S) para o gateway de API ou NEGs sem servidor. Não é possível colocar um gateway desse tipo atrás de um NEG sem servidor ou de um balanceador de carga de aplicativo externo. Consequentemente, os domínios personalizados (que dependem do balanceamento de carga) não são compatíveis com esses gateways durante o pré-lançamento público.

  • Comportamento de prazo: ativar o streaming em um gateway não muda o comportamento do campo deadline em um caminho de SSE ou transferência em partes. O prazo continua sendo um limite de tempo real para a resposta completa. Portanto, um fluxo é interrompido quando o prazo expira, independentemente da quantidade de dados que ele está enviando. O padrão é 15 segundos e o máximo é 3.600 segundos. Em um WebSocket, deadline limita a lacuna entre as mensagens, e a conexão é encerrada após 3.600 segundos. Consulte Definir o prazo da transmissão.

  • Protocolo de Contexto de Modelo (MCP): criar o gateway com --enable-streaming não faz um fluxo de endpoint do MCP. As respostas da MCP permanecem um único corpo application/json, independentemente do modo de streaming do gateway. Para mais detalhes, consulte Limitações do MCP.