As swimlanes em modo permissivo do Service Mesh (ASM) permitem implantar ambientes parciais que recorrem a uma versão de base quando há serviços ausentes. No entanto, o ASM não consegue rotear o tráfego de filas de mensagens pelo proxy da malha como faz com o tráfego HTTP. Quando um rastreamento inclui um salto por fila de mensagens, a tag da swimlane se perde, a menos que sua aplicação a preserve explicitamente.
O padrão de adaptação descrito aqui mantém as tags das swimlanes intactas ao atravessar os limites das filas de mensagens. Assim, o tráfego continua chegando à swimlane correta mesmo após um salto assíncrono.
Como funciona
Em uma cadeia de chamadas HTTP síncronas, o ASM roteia automaticamente as requisições para a swimlane correta com base no cabeçalho de requisição x-asm-prefer-tag. As filas de mensagens quebram essa cadeia porque os consumidores puxam as mensagens de forma independente — o proxy da malha não tem oportunidade de inspecioná-las ou roteá-las.
Para resolver essa limitação, sua aplicação deve assumir três responsabilidades:
Produtor: grave metadados da swimlane em cada mensagem. Incorpore duas informações: a swimlane à qual o produtor pertence (usada como chave de filtro) e a tag da swimlane da requisição de entrada (usada para roteamento downstream).
Consumidor: filtre mensagens por swimlane. Inscreva-se apenas em mensagens cuja chave de filtro corresponda à swimlane do próprio consumidor.
Consumidor: restaure a tag da swimlane nas requisições de saída. Após consumir uma mensagem, extraia a tag da swimlane dos metadados e defina-a como o cabeçalho
x-asm-prefer-tagnas requisições HTTP downstream. Isso permite que o proxy da malha retome o roteamento baseado em tags.
Pré-requisitos
Requisitos da fila de mensagens
A fila de mensagens precisa oferecer suporte a:
Metadados personalizados nas mensagens — os produtores anexam informações da swimlane a cada mensagem.
Filtragem no lado do consumidor — os consumidores se inscrevem seletivamente com base em uma chave de filtro (também conhecida como campo de condição de filtragem por tag) para receber apenas mensagens da própria swimlane.
Restrições de implantação
Em uma fila de mensagens baseada em pull, o consumidor não acessa informações de descoberta de serviço da swimlane. Por isso, implante produtores e consumidores juntos: ambos na swimlane ou nenhum deles.
|
Swimlane |
Produtor |
Consumidor |
Válido? |
|
v1 |
Implantado |
Implantado |
Sim |
|
v2 |
Implantado |
Implantado |
Sim |
|
v2 |
Implantado |
Não implantado |
Não |
|
v2 |
Não implantado |
Implantado |
Não |
|
v2 |
Não implantado |
Não implantado |
Sim — as requisições recorrem à v1 no modo permissivo |
Implantar apenas um produtor ou apenas um consumidor em uma swimlane constitui uma configuração inválida. Sempre implante-os como um par ou omita ambos e permita que o modo permissivo direcione o tráfego para a swimlane de base.
Etapa 1: Grave tags de swimlane nas mensagens (produtor)
Quando um produtor (por exemplo, APP-B) envia uma mensagem para a fila, ele deve incluir dois campos de metadados:
|
Campo de metadado |
source |
Finalidade |
|
Swimlane do produtor (chave de filtro) |
Variável de ambiente injetada na carga de trabalho |
Permite que os consumidores filtrem mensagens por swimlane |
|
Tag da swimlane da requisição de entrada |
Cabeçalho de requisição |
Preserva a tag de roteamento original para serviços downstream |
source de cada valor:
Swimlane do produtor — Definida pela tag da carga de trabalho. Exponha uma variável de ambiente (por exemplo,
ASM_SWIMLANE_TAG) na especificação do pod para que a aplicação leia sua atribuição de swimlane.Tag da swimlane da requisição de entrada — Após o tráfego passar pelo gateway de ingresso do ASM, o sistema repassa as tags para HTTPS ponta a ponta por meio do cabeçalho de requisição
x-asm-prefer-tag. Leia esse cabeçalho da requisição HTTP de entrada e grave seu valor nos metadados da mensagem.
Exemplo: produtor grava metadados da swimlane
O pseudocódigo abaixo mostra como o produtor lê as informações da swimlane e as anexa à mensagem:
import os
from flask import request
# Read the swimlane assignment from the environment variable
# that ASM injects into the workload pod.
producer_swimlane = os.environ.get("ASM_SWIMLANE_TAG", "default")
# Read the swimlane routing tag from the incoming HTTP request header.
routing_tag = request.headers.get("x-asm-prefer-tag", "")
# Attach both values to the message metadata before publishing.
message = {
"body": payload,
"metadata": {
"filter_key": producer_swimlane, # Consumer-side filtering
"x-asm-prefer-tag": routing_tag # Downstream routing
}
}
mq_client.publish(topic="order-events", message=message)
Exemplo de metadados de mensagem:
Message metadata:
filter_key: "v1" # Swimlane of the producer (APP-B is deployed in v1)
x-asm-prefer-tag: "v2" # Swimlane tag from the original request
Message body:
{ ... actual payload ... }
Etapa 2: Filtre mensagens por swimlane (consumidor)
Cada consumidor se inscreve nas mensagens usando a chave de filtro correspondente à sua própria swimlane. Isso garante que o consumidor processe apenas mensagens de produtores na mesma swimlane.
Exemplo: consumidor se inscreve com uma chave de filtro
import os
consumer_swimlane = os.environ.get("ASM_SWIMLANE_TAG", "default")
# Subscribe only to messages whose filter_key matches this consumer's swimlane.
mq_client.subscribe(
topic="order-events",
filter_expression=f"filter_key = '{consumer_swimlane}'"
)
Cenário 1: Produtor e consumidor implantados em cada swimlane
Quando ambas as swimlanes v1 e v2 possuem produtores e consumidores:
O APP-C(v1) se inscreve com a chave de filtro
v1e consome apenas mensagens do APP-B(v1).O APP-C(v2) se inscreve com a chave de filtro
v2e consome apenas mensagens do APP-B(v2).
O tráfego permanece isolado dentro de cada swimlane.
Cenário 2: Nem produtor nem consumidor implantados em uma swimlane
Quando a swimlane v2 tem apenas APP-A(v2) e APP-D(v2) — sem produtor ou consumidor:
O APP-A(v2) envia uma requisição. Como o APP-B(v2) não existe, o modo permissivo roteia a requisição para o APP-B(v1).
O APP-B(v1) grava a mensagem na fila com a chave de filtro
v1. O valor dex-asm-prefer-tagnos metadados da mensagem permanecev2(a tag da swimlane da requisição original).O APP-C(v1) consome a mensagem (a chave de filtro corresponde a
v1).O APP-C(v1) remove a tag da swimlane v1 transportada na mensagem, lê o valor de
x-asm-prefer-tag(v2) dos metadados e o define na requisição HTTP de saída.O proxy da malha roteia a requisição para o APP-D(v2) com base no cabeçalho
x-asm-prefer-tag: v2.
Esse processo preserva o roteamento de swimlane ponta a ponta, mesmo que a mensagem tenha passado pela swimlane de base.
Etapa 3: Restaure a tag da swimlane nas requisições downstream (consumidor)
Após consumir uma mensagem, propague a tag da swimlane para todas as requisições HTTP downstream. Sem essa etapa, o proxy da malha não consegue rotear as requisições subsequentes para a swimlane correta.
Para propagar a tag:
Extraia o valor de
x-asm-prefer-tagdos metadados da mensagem consumida.Defina o cabeçalho
x-asm-prefer-tagem todas as requisições HTTP de saída para serviços downstream.
Em seguida, o proxy da malha roteia essas requisições para a swimlane especificada pelo valor do cabeçalho.
Exemplo: consumidor restaura a tag da swimlane
import requests
def on_message(message):
# Extract the swimlane routing tag from the consumed message.
routing_tag = message.metadata.get("x-asm-prefer-tag", "")
# Set the tag as a request header on all downstream HTTP calls.
headers = {"x-asm-prefer-tag": routing_tag}
response = requests.post(
"http://app-d:8080/process",
json=message.body,
headers=headers
)
Referência rápida: campos a definir e propagar
|
Campo |
Onde defina |
source do valor |
Finalidade |
|
Chave de filtro da mensagem |
Metadados da mensagem (produtor) |
Variável de ambiente da carga de trabalho ( |
Filtragem de mensagens no lado do consumidor |
|
|
Metadados da mensagem (produtor) |
Cabeçalho da requisição HTTP de entrada |
Preserva a tag de roteamento da swimlane durante o salto pela fila de mensagens |
|
|
Cabeçalho da requisição HTTP de saída (consumidor) |
Metadados da mensagem consumida |
Restaura o roteamento baseado em tags para serviços downstream |