Configurar o streaming para respostas de LLM e outros tipos de tráfego

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 a conexões de longa duração e transmitam dados em blocos para streaming de solicitação e resposta.

Um uso comum do streaming é disponibilizar um modelo de linguagem grande (LLM). O modelo envia a resposta um token por vez, para que o cliente possa mostrar o texto enquanto o modelo ainda o gera. 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 de resposta incremental: frames de dados HTTP/2 ou codificação de transferência em blocos HTTP/1.1, dependendo do que o cliente negociar.
  • 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 do gRPC: streaming full-duplex usando o 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á correta.

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: é preciso configurar o back-end para usar HTTP/2 (h2).
  • WebSockets: use http/1.1. Os WebSockets exigem o handshake HTTP/1.1 Connection: Upgrade.
  • Eventos enviados pelo servidor (SSE) e entrega de resposta incremental: 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 no objeto x-google-api-management.backends. Você também precisa referenciar esse back-end usando x-google-backend no nível raiz ou de 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 determina 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 as 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 com streaming ativado.
Streaming por HTTP
(SSE, transferência em blocos)
N/A: efetivamente infinito; somente o tempo limite da solicitação encerra o stream O padrão é 15 segundos. Defina deadline para mudar esse valor, até 3.600 segundos para gateways com streaming ativado.
Streaming por gRPC ou WebSockets O padrão é 300 segundos. Defina deadline para mudar esse valor, até 3.600 segundos para gateways com streaming ativado. No WebSockets, um deadline de menos de 300 segundos é ignorado, e um mínimo de 300 segundos é aplicado. Sempre 3.600 segundos para gateways com streaming ativado, não configurável

Exemplo (OpenAPI 3.x)

Defina o campo deadline na definição de back-end nomeada.

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 ver os outros limites que se aplicam às 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:

  • Sem 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 ver o modo em que ele foi criado.
  • Imutabilidade: o modo de streaming é fixado na criação e não pode ser modificado posteriormente.

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 (IMUTÁVEL, OPCIONAL)
  • 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 gateway 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

Chamar APIs do Google Cloud

Um gateway de streaming pode chamar APIs do Google Cloud , como aiplatform.googleapis.com, para que você possa transmitir respostas de um modelo do Gemini na Agent Platform pelo gateway. O gateway se autentica nesses back-ends com um token de acesso em vez de um token de ID. Para mais detalhes, consulte Como proteger serviços de back-end.

Respostas de stream 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 faz o streaming de uma conclusão de chat pelo gateway. O vLLM disponibiliza uma API compatível com a OpenAI que faz o streaming de respostas como eventos enviados pelo servidor (SSE, na sigla em inglês).

Antes de começar, conclua as etapas em 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

Siga as instruções em Implantar um modelo do 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ê implantar, 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 é transmitido 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 da API

Salve a seguinte especificação OpenAPI como gemma-api.yaml, substituindo https://my-gemma-service.run.app pelo URL do 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 mais curto do que o --timeout 600 que o guia do Gemma define no serviço. Como resultado, o deadline do gateway, e não o tempo limite do serviço, encerra um stream que é executado por muito tempo. Um x-google-backend de nível superior tem como padrão pathTranslation: APPEND_PATH_TO_ADDRESS. O gateway anexa o caminho da solicitação ao endereço de back-end, de modo que uma solicitação para /v1/chat/completions chegue ao endpoint de conclusões 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. É possível escolher uma string de público-alvo diferente, desde que os autores da chamada solicitem a mesma ao gerar um token. Para mais informações, consulte Como 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 base na configuração da 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, acesse o nome do host dele:

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 gera o token para uma conta de serviço que você representa. Para o autor da chamada, use uma conta de serviço atual ou crie uma. Para mais informações, consulte Criar contas de serviço. Conceda a si mesmo o papel de Criador de token da conta de serviço (roles/iam.serviceAccountTokenCreator) nessa conta de serviço, que a CLI gcloud precisa para representá-la:

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 armazenamento em 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 stream SSE. O primeiro evento tem o papel 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 são cobrados pela saída de rede em gateways com streaming ativado. No entanto, o faturamento do Service Control ainda se aplica no nível da API, independentemente 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. É preciso criar um novo gateway. Um gateway com streaming ativado recebe um formato de nome de host diferente, o que exige que você atualize seus clientes ou registros DNS. Se você 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 disponibilização dos nomes de host regionais do *.gateway.dev mantêm esse nome de host permanentemente e não são migrados para o novo padrão.

    Um novo gateway com streaming ativado 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 que não é de streaming. O primeiro rótulo é a string {gateway_id}-{project_number} combinada, que precisa se ajustar ao limite de 63 caracteres do rótulo de DNS. O limite de 49 caracteres do ID do gateway o mantém dentro desse limite para números de projeto de até 13 dígitos. Um número de projeto mais longo precisa de um ID de gateway mais curto.

  • Terraform: não é possível ativar o streaming usando o Terraform (planejado 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 esse gateway 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 do prazo: ativar o streaming em um gateway não muda o comportamento do campo deadline em um caminho de SSE ou de transferência em blocos. O prazo continua sendo um limite de tempo real na resposta completa. Portanto, um stream é cortado 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 o intervalo entre as mensagens, e a conexão é encerrada após 3.600 segundos. Consulte Definir o prazo do stream.

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