Este é o quarto de uma série de quatro partes sobre como projetar, criar e implantar microsserviços. Esta série descreve os vários elementos de uma arquitetura de microsserviços. A série inclui informações sobre os benefícios e as desvantagens do padrão de arquitetura de microsserviços e como aplicá-lo.
- Introdução a microsserviços
- Refatorar um monolítico em microsserviços
- Comunicação entre serviços em uma configuração de microsserviços
- Rastreamento distribuído em um aplicativo de microsserviços (este documento)
Esta série é destinada a desenvolvedores e arquitetos de aplicativos que projetam e implementam a migração para refatorar um aplicativo monolítico em um aplicativo de microsserviços.
Em um sistema distribuído, é importante saber como uma solicitação flui de um serviço para outro e quanto tempo leva para executar uma tarefa em cada serviço. Pense no aplicativo Online Boutique baseado em microsserviços que você implantou no documento anterior, Como refatorar um monolítico em microsserviços. O aplicativo é composto por vários serviços. Por exemplo, a captura de tela a seguir mostra a página de detalhes do produto, que busca informações dos serviços de front-end, de recomendação e de anúncios.
Para renderizar a página de detalhes do produto, o serviço de front-end se comunica com os serviços de recomendação e de anúncios, conforme mostrado no diagrama a seguir:
Figura 1. Serviços escritos em idiomas diferentes.
Na figura 1, o serviço de front-end é escrito em Go. O serviço de recomendação, escrito em Python, usa o gRPC para se comunicar com o serviço de front-end. O serviço de anúncios, escrito em Java, também usa o gRPC para se comunicar com o serviço de front-end. Além do gRPC, o método de comunicação entre serviços também pode ser usado em HTTP REST.
Ao criar esse sistema distribuído, você quer que suas ferramentas de observabilidade forneçam os seguintes insights:
- Os serviços que uma solicitação passou.
- Onde ocorreram atrasos se uma solicitação era lenta.
- Onde ocorreu um erro se a solicitação falhar.
- As diferenças entre a execução da solicitação e o comportamento normal do sistema
- Se as diferenças na execução da solicitação estão relacionadas ao desempenho (se algumas chamadas de serviço demoraram mais ou menos que o normal).
Objetivos
- Use os arquivos de manifesto personalizados para configurar a infraestrutura.
- Implante o aplicativo de exemplo do Online Boutique no Google Kubernetes Engine (GKE).
- Use o Cloud Trace para analisar a jornada de um usuário no aplicativo de exemplo.
Custos
Neste documento, você usará os seguintes componentes faturáveis do Google Cloud:
Para gerar uma estimativa de custo baseada na projeção de uso deste tutorial, use a calculadora de preços.
Ao concluir este documento, você evitará o faturamento contínuo excluindo os recursos criados. Para mais informações, consulte Como fazer a limpeza.
Antes de começar
Se você já configurou um projeto concluindo o documento anterior desta série, comunique a comunicação entre serviços em uma configuração de microsserviços, poderá reutilizá-lo. Conclua as etapas a seguir para ativar outras APIs e definir variáveis de ambiente.
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
-
Make sure that billing is enabled for your Google Cloud project.
-
In the Google Cloud console, activate Cloud Shell.
Ative as APIs do Compute Engine, GKE, Cloud SQL, Artifact Analysis, Trace e Container Registry:
gcloud services enable \ compute.googleapis.com \ sql-component.googleapis.com \ servicenetworking.googleapis.com\ container.googleapis.com \ containeranalysis.googleapis.com \ containerregistry.googleapis.com \ sqladmin.googleapis.com
Rastreamento distribuído
O rastreamento distribuído anexa metadados contextuais a cada solicitação e garante que os metadados sejam compartilhados entre as solicitações. Você usa pontos de rastreamento para instrumentar o rastreamento distribuído. Por exemplo, é possível instrumentar seus serviços (front-end, recomendação e anúncios) com dois pontos de rastreamento para processar uma solicitação de cliente e visualizar os detalhes de um produto: um ponto de rastreamento para enviar a solicitação e outro para ponto de recebimento para receber a resposta. O diagrama a seguir mostra como essa instrumentação de ponto de trace funciona:
Figura 2. Cada chamada entre serviços tem dois pontos de rastreamento que consistem em um par de solicitação-resposta.
Para que os pontos de rastreamento entendam qual solicitação executar quando o serviço é invocado, o serviço de origem transmite um ID de trace ao longo do fluxo de execução. O processo que transmite o ID de trace é chamado de propagação de metadados ou propagação de contexto distribuído. A propagação de contexto transfere metadados por meio de chamadas de rede quando os serviços de um aplicativo distribuído se comunicam durante a execução de uma determinada solicitação. O diagrama a seguir mostra a propagação de metadados:
Figura 3. Os metadados de trace são transmitidos entre serviços. Os metadados incluem informações como quais serviços chamam quais e seus carimbos de data/hora.
No exemplo do Online Boutique, um trace começa quando um usuário envia uma solicitação inicial para buscar detalhes do produto. Um novo ID de trace é gerado, e cada solicitação sucessiva é decorada com cabeçalhos que contêm metadados contextuais de volta para a solicitação original.
Cada operação individual que é invocada como parte do preenchimento da solicitação do usuário final é chamada de período. Cada tag de serviço de origem inclui cada período com o próprio ID exclusivo e o código de trace do período pai. O diagrama a seguir mostra uma visualização de um gráfico de Gantt de um trace:
Figura 4. Um período pai inclui o tempo de resposta dos períodos filhos.
A Figura 4 mostra uma árvore de rastreamento em que o serviço de front-end chama o serviço de recomendação e o serviço de anúncios. O serviço de front-end é o período pai, que descreve o tempo de resposta observado pelo usuário final. Os períodos filhos descrevem como o serviço de recomendação e o serviço de anúncios foram chamados e respondidos, incluindo as informações do tempo de resposta.
Uma malha de serviço como o Istio permite o rastreamento distribuído do tráfego de serviço a serviço sem a necessidade de qualquer instrumentação dedicada. No entanto, pode haver situações em que se queira ter mais controle sobre os traces ou que seja necessário rastrear o código que não esteja sendo executado em uma malha de serviço.
Neste documento, usamos o OpenTelemetry para permitir a instrumentação de aplicativos de microsserviço distribuídos para coletar traces e métricas. Com o OpenCensus, é possível coletar métricas e rastreamentos e exportá-los para backends, como o Prometheus, o Cloud Monitoring, o Datadog, o Graphite, o Zipkin e o Jaeger.
Instrumentação com o OpenTelemetry
As seções a seguir mostram como usar a propagação de contexto para permitir que períodos de várias solicitações sejam anexados a um único rastreamento pai.
Este exemplo usa as bibliotecas JavaScript, Python e Go do OpenTelemetry para instrumentar e trace a implementação dos serviços de pagamento, recomendação e front-end. Dependendo do nível de detalhes da instrumentação, os dados de rastreamento podem afetar o custo do projeto (faturamento do Cloud Trace). Para reduzir a latência, a maioria dos sistemas de rastreamento usa várias formas de amostragem para capturar apenas uma determinada porcentagem dos traces observados. Nos ambientes de produção, é possível que sua organização tenha motivos para fazer as amostras e por quê. Talvez você queira personalizar sua estratégia de amostragem com base no gerenciamento de custos, concentrando-se em rastros interessantes ou filtrando ruídos. Para saber mais sobre amostragem, consulte Amostragem do OpenTelemetry.
Neste documento, usamos o Trace para visualizar traces distribuídos. Use um exportador do OpenTelemetry para enviar traces ao Trace.
Registrar exportadores de rastreamento
Nesta seção, mostramos como registrar o exportador de rastreamento em cada serviço adicionando linhas ao código do microsserviço.
Para o serviço de front-end (escrito em Go), o exemplo de código a seguir registra o exportador:
[...] exporter, err := otlptracegrpc.New( ctx, otlptracegrpc.WithGRPCConn(svc.collectorConn)) if err != nil { log.Warnf("warn: Failed to create trace exporter: %v", err) } tp := sdktrace.NewTracerProvider( sdktrace.WithBatcher(exporter), sdktrace.WithSampler(sdktrace.AlwaysSample())) otel.SetTracerProvider(tp)
Para o serviço de recomendação (escrito em Python), o exemplo de código a seguir registra o exportador:
if os.environ["ENABLE_TRACING"] == "1": trace.set_tracer_provider(TracerProvider()) otel_endpoint = os.getenv("COLLECTOR_SERVICE_ADDR", "localhost:4317") trace.get_tracer_provider().add_span_processor( BatchSpanProcessor( OTLPSpanExporter( endpoint = otel_endpoint, insecure = True ) ) )
Para o serviço de pagamento (escrito em JavaScript), o exemplo de código a seguir registra o exportador:
provider.addSpanProcessor(new SimpleSpanProcessor(new OTLPTraceExporter({url: collectorUrl}))); provider.register();
Configurar a propagação de contexto
O sistema de rastreamento precisa seguir uma especificação de contexto de rastreamento que defina o formato para propagar o contexto de rastreamento entre os serviços. Os exemplos de formato de propagação incluem o formato B3 do Zipkin e o X-Google-Cloud-Trace.
O OpenTelemetry propaga o contexto usando o TextMapPropagator
global. Este exemplo usa o propagador do contexto de trace, que usa o formato traceparent do W3C. As bibliotecas de instrumentação, como as bibliotecas HTTP e gRPC do OpenTelemetry, usam o propagador global para adicionar contexto de trace como metadados a solicitações HTTP ou gRPC. Para que a propagação de contexto seja bem-sucedida, o cliente e o servidor precisam usar o mesmo formato de propagação.
Propagação de contexto sobre HTTP
O serviço de front-end injeta um contexto de trace nos cabeçalhos de solicitação HTTP. Os serviços de back-end extraem o contexto do trace. O exemplo de código a seguir mostra como o serviço de front-end está instrumentado para configurar o contexto de rastreamento:
otel.SetTextMapPropagator( propagation.NewCompositeTextMapPropagator( propagation.TraceContext{}, propagation.Baggage{})) if os.Getenv("ENABLE_TRACING") == "1" { log.Info("Tracing enabled.") initTracing(log, ctx, svc) } else { log.Info("Tracing disabled.") } ... var handler http.Handler = r handler = &logHandler{log: log, next: handler} // add logging handler = ensureSessionID(handler) // add session ID handler = otelhttp.NewHandler(handler, "frontend") // add OpenTelemetry tracing
Propagação de contexto sobre gRPC
Considere o fluxo em que o serviço de finalização de compra faz o pedido com base no produto selecionado pelo usuário. Esses serviços se comunicam por meio do gRPC.
O exemplo de código a seguir usa um interceptador de chamadas gRPC que intercepta as chamadas enviadas e injeta o contexto de rastreamento:
var srv *grpc.Server // Propagate trace context always otel.SetTextMapPropagator( propagation.NewCompositeTextMapPropagator( propagation.TraceContext{}, propagation.Baggage{})) srv = grpc.NewServer( grpc.UnaryInterceptor(otelgrpc.UnaryServerInterceptor()), grpc.StreamInterceptor(otelgrpc.StreamServerInterceptor()), )
Depois de receber a solicitação, o serviço de pagamento ou de catálogo de produtos (ListProducts
) extrai o contexto
dos cabeçalhos da solicitação e usa os metadados de trace pai para gerar um período filho.
As seções a seguir fornecem detalhes sobre como configurar e revisar a distribuição distribuída para o exemplo de aplicativo Online Boutique.
Implantar o aplicativo
Se você já tiver um aplicativo em execução para concluir o documento anterior desta série, Comunicação entre serviços em uma configuração de microsserviços, pule para a próxima seção. Como revisar traces. Caso contrário, conclua as seguintes etapas para implantar o exemplo do exemplo Online Boutique:
Para configurar a infraestrutura, clone o repositório do GitHub no Cloud Shell:
git clone https://github.com/GoogleCloudPlatform/microservices-demo.git
Para a nova implantação, redefina as variáveis de ambiente:
PROJECT_ID=PROJECT_ID REGION=us-central1 GSA_NAME=microservices-sa GSA_EMAIL=$GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
Substitua
PROJECT_ID
pelo ID do projeto do Google Cloud que você quer usar.Opcional: crie um cluster novo ou reutilize um cluster atual, se houver:
gcloud container clusters create-auto online-boutique --project=${PROJECT_ID} --region=${REGION}
Crie uma conta de serviço do Google:
gcloud iam service-accounts create $GSA_NAME \ --project=$PROJECT_ID
Ative as APIs:
gcloud services enable \ monitoring.googleapis.com \ cloudtrace.googleapis.com \ cloudprofiler.googleapis.com \ --project ${PROJECT_ID}
Conceda os papéis necessários para o Cloud Trace à conta de serviço:
gcloud projects add-iam-policy-binding ${PROJECT_ID} \ --member "serviceAccount:${GSA_NAME}@${PROJECT_ID}.iam.gserviceaccount.com" \ --role roles/cloudtrace.agent gcloud projects add-iam-policy-binding ${PROJECT_ID} \ --member "serviceAccount:${GSA_NAME}@${PROJECT_ID}.iam.gserviceaccount.com" \ --role roles/monitoring.metricWriter gcloud projects add-iam-policy-binding ${PROJECT_ID} \ --member "serviceAccount:${GSA_NAME}@${PROJECT_ID}.iam.gserviceaccount.com" \ --role roles/cloudprofiler.agent gcloud iam service-accounts add-iam-policy-binding ${GSA_EMAIL} \ --role roles/iam.workloadIdentityUser \ --member "serviceAccount:${PROJECT_ID}.svc.id.goog[default/default]"
Anote sua conta de serviço do Kubernetes (
default
/default
para o namespace padrão) para usar a conta de serviço do Identity and Access Management (IAM):kubectl annotate serviceaccount default \ iam.gke.io/gcp-service-account=${GSA_EMAIL}
Ative o Google Cloud Observability para a configuração do GKE, que permite tracing:
cd ~/microservices-demo/kustomize && \ kustomize edit add component components/google-cloud-operations
O comando anterior atualiza o arquivo
kustomize
/kustomization.yaml
, que é semelhante a este:apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - base components: - components/google-cloud-operations [...]
Implantar os microsserviços:
kubectl apply -k .
Verifique o status da implantação:
kubectl rollout status deployment/frontend kubectl rollout status deployment/paymentservice kubectl rollout status deployment/recommendationservice kubectl rollout status deployment/adservice
A saída de cada comando é semelhante a esta:
Waiting for deployment "
" rollout to finish: 0 of 1 updated replicas are available... deployment " " successfully rolled out Consiga o endereço IP do aplicativo implantado:
kubectl get service frontend-external | awk '{print $4}'
Aguarde o endereço IP do balanceador de carga ser publicado. Para sair do comando, pressione
Ctrl+C
. Anote o endereço IP do balanceador de carga e acesse o aplicativo no URLhttp://IP_ADDRESS
. Pode levar algum tempo para o balanceador de carga se tornar íntegro e começar a transmitir tráfego.
Revisar traces usando o Cloud Trace
A jornada de compra de um usuário no aplicativo Online Boutique tem o seguinte fluxo:
- O usuário vê um catálogo de produtos na página de destino.
- Para fazer uma compra, o usuário clica em Comprar.
- O usuário é redirecionado para uma página de detalhes do produto onde adiciona o item ao carrinho.
- O usuário é redirecionado para uma página de finalização de compra, onde pode fazer um pagamento para concluir o pedido.
Considere um cenário em que você precisa solucionar problemas de tempos de resposta altos ao carregar a página de detalhes do produto. Conforme descrito anteriormente, a página de detalhes do produto é composta de vários microsserviços. Para determinar onde e porque a alta latência está ocorrendo, você pode ver gráficos de rastreamento distribuídos para analisar o desempenho de toda a solicitação nos diferentes serviços.
Para revisar os gráficos de rastreamento distribuídos, faça o seguinte:
- Acesse o aplicativo e clique em qualquer produto. A página de detalhes do produto é exibida.
- No console do Google Cloud, acesse a página Lista de traces e revise a linha do tempo.
- Para ver os resultados do trace distribuído, clique em Front-end na coluna do URI.
A Visualização da hierarquia do Trace exibe os períodos associados ao URI:
Na captura de tela, o trace de um produto contém os seguintes períodos:
- O período de front-end captura a latência de ponta a ponta (150,349 ms) que o cliente observa ao carregar a página de detalhes do produto.
- O período do Serviço de recomendação captura a latência das chamadas de back-end na busca de recomendações (4,246 ms) relacionadas ao produto.
- O período Serviço de anúncios captura a latência das chamadas de back-end ao buscar anúncios (4,511 ms) relevantes para a página do produto.
Para solucionar problemas de tempos de resposta altos, você recebe insights centrados nos serviços que incluem gráficos de distribuição de latência de todas as solicitações de outliers quando as dependências do serviço não atendem aos respectivosobjetivos de nível de serviço (SLOs). Também é possível usar o Cloud Trace para ver insights de desempenho e criar relatórios de análise com base nos dados de amostra.
Solução de problemas
Se os traces no Gerenciamento do desempenho de aplicativos não aparecerem, verifique se há um erro de permissão negada na Análise de registros. A permissão negada ocorre quando a conta de serviço
não tem acesso para exportar os traces. Revise as etapas sobre
como conceder os papéis
necessários para o Cloud Trace e anote a conta de serviço
com o namespace correto. Depois disso, reinicie o opentelemetrycollector
:
kubectl rollout restart deployment opentelemetrycollector
Limpar
Para evitar cobranças na sua conta do Google Cloud pelos recursos usados no tutorial, exclua o projeto que os contém ou mantenha o projeto e exclua os recursos individuais.
Exclua o projeto
- In the Google Cloud console, go to the Manage resources page.
- In the project list, select the project that you want to delete, and then click Delete.
- In the dialog, type the project ID, and then click Shut down to delete the project.
Excluir os recursos
Se você quiser manter o projeto do Google Cloud usado neste documento, exclua os recursos individuais:
No Cloud Shell, exclua os recursos:
gcloud container clusters delete online-boutique --project=${PROJECT_ID} --region=${REGION}
A seguir
- Leia o primeiro documento desta série para saber mais sobre microsserviços, benefícios, desafios e casos de uso.
- Leia o segundo documento desta série para saber mais sobre as estratégias de refatoração de aplicativos para decompor microsserviços.
- Leia o terceiro documento desta série para saber mais sobre a comunicação entre serviços em uma configuração de microsserviços.
- Para mais arquiteturas de referência, diagramas e práticas recomendadas, confira a Central de arquitetura do Cloud.