Este post é um dos quatro tutoriais que ajudam você a colocar em prática os conceitos do Microservices March 2023: comece a disponibilizar microsserviços:
- Como implantar e configurar microsserviços
- Como gerenciar segredos em contêineres com segurança
- Como usar o GitHub Actions para automatizar implantações canário de microsserviços
- Como usar o rastreamento do OpenTelemetry para entender seus microsserviços (este post)
Uma arquitetura de microsserviços oferece muitos benefícios, incluindo maior autonomia para as equipes e mais flexibilidade no dimensionamento e na implantação. Por outro lado, quanto mais serviços houver em um sistema (e um aplicativo de microsserviços pode ter dezenas ou até centenas), mais difícil será manter uma visão clara do funcionamento geral do sistema. Como desenvolvedores e responsáveis pela manutenção de sistemas de software complexos, sabemos como é essencial ter essa visão clara. Observabilidade As ferramentas de observabilidade nos permitem construir essa visão abrangendo diversos serviços e a infraestrutura de suporte.
Neste tutorial, destacamos um tipo muito importante de observabilidade para aplicações de microsserviços: o rastreamento. Antes de começar, vamos definir alguns termos comumente usados ao falar sobre observabilidade:
- Observabilidade – A capacidade de compreender o estado ou a condição interna de um sistema complexo (como uma aplicação de microsserviços) com base apenas no conhecimento de suas saídas externas (como rastreamentos, logs e métricas).
- Monitoramento – A capacidade de observar e verificar o progresso ou o status de um objeto ao longo de um período. Por exemplo, você pode monitorar o tráfego que chega ao seu aplicativo durante os horários de pico e usar essas informações para dimensioná-lo adequadamente em resposta.
- Telemetria – O ato de coletar métricas, rastreamentos e logs e transferi-los do ponto de origem para outro sistema para armazenamento e análise. Também se refere aos próprios dados.
- Rastreamento/rastros – Um registro da jornada de uma solicitação ou ação à medida que ela percorre todos os nós de um sistema distribuído.
- Span – Um registro, dentro de um trace, de uma operação e dos metadados associados a ela. Os traces são compostos por muitos spans aninhados.
- Registro de eventos/logs – Um registro de texto com carimbo de data e hora e metadados.
- Métrica – Uma medição capturada durante a execução. Por exemplo, a quantidade de memória usada por um aplicativo em um determinado momento.
Podemos usar todos esses conceitos para obter insights sobre o desempenho dos nossos microsserviços. O rastreamento é uma parte particularmente útil de uma estratégia de observabilidade, pois os rastros oferecem uma “visão geral” do que acontece em vários componentes, muitas vezes fracamente acoplados, quando uma solicitação é feita. Também é uma maneira particularmente eficaz de identificar gargalos de desempenho.
Este tutorial usa o kit de ferramentas de rastreamento do OpenTelemetry (OTel), um padrão de código aberto e independente de fornecedor para coletar, processar e exportar dados de telemetria, que vem ganhando popularidade rapidamente. Na concepção do OTel, um rastreamento divide um fluxo de dados, que pode envolver vários serviços, em uma série de “blocos” organizados cronologicamente que ajudam você a entender facilmente:
- Todas as etapas que ocorreram em um “bloco”
- Quanto tempo todas essas etapas levaram
- Metadados sobre cada etapa
Se você não conhece o OTel, consulte O que é OpenTelemetry? para obter uma introdução detalhada ao padrão e aos aspectos a serem considerados em sua implementação.
Visão geral do tutorial
Este tutorial se concentra no rastreamento das operações de uma aplicação de microsserviços com o OTel. Nos quatro desafios deste tutorial, você aprenderá a acompanhar uma solicitação pelo seu sistema e a responder a perguntas sobre seus microsserviços:
- Configure a instrumentação básica do OTel
- Configure a instrumentação do OTel e a visualização de traces para todos os serviços
- Aprenda a interpretar traces do OTel
- Otimize a instrumentação com base na análise dos traces
Esses desafios ilustram o processo que recomendamos ao configurar o rastreamento pela primeira vez. As etapas são:
- Entenda o sistema, bem como a operação específica que você está instrumentando.
- Decida o que você precisa saber sobre o sistema em execução.
- Instrumente o sistema de forma “ingênua” – ou seja, use uma configuração padrão sem tentar eliminar informações desnecessárias nem coletar pontos de dados personalizados – e avalie se a instrumentação ajuda você a responder às suas perguntas.
- Ajuste as informações apresentadas para responder a essas perguntas mais rapidamente.
Observação: Nossa intenção neste tutorial é ilustrar alguns conceitos fundamentais sobre telemetria, e não mostrar a maneira correta de implantar microsserviços em produção. Embora ele use uma arquitetura real de “microsserviços”, há algumas ressalvas importantes:
- O tutorial não usa um framework de orquestração de contêineres, como Kubernetes ou Nomad. Isso permite que você aprenda os conceitos de microsserviços sem se prender aos detalhes específicos de um determinado framework. Os padrões apresentados aqui podem ser aplicados a um sistema que execute um desses frameworks.
- Os serviços são otimizados para facilitar a compreensão, e não para seguir práticas rigorosas de engenharia de software. O objetivo é analisar a função de um serviço no sistema e seus padrões de comunicação, não os detalhes específicos do código. Para obter mais informações, consulte os arquivos README de cada serviço.
Arquitetura do tutorial e objetivos de telemetria
Arquitetura e fluxo do usuário
Este diagrama ilustra a arquitetura geral e o fluxo de dados entre os microsserviços e outros elementos usados no tutorial.

Os dois microsserviços são:
- O serviço messenger service – Uma API de chat simples com recursos de armazenamento de mensagens
- O serviço notifier service – Um listener que dispara eventos para alertar os usuários com base em suas preferências
Três componentes da infraestrutura de suporte são:
- NGINX Open Source – Um ponto de entrada para o serviço messenger e para o sistema como um todo
- RabbitMQ – Um popular agente de mensagens de código aberto que permite que os serviços se comuniquem de forma assíncrona
- Jaeger – Um sistema de rastreamento distribuído de ponta a ponta e código aberto para coletar e visualizar a telemetria dos componentes do sistema que a produzem
Deixando o OTel de lado por um momento, podemos nos concentrar na sequência de eventos que estamos rastreando: o que acontece quando um usuário envia uma nova mensagem de chat e o destinatário é notificado sobre ela.

O fluxo funciona da seguinte forma:
- Um usuário envia uma mensagem para o serviço messenger. O proxy reverso NGINX intercepta a mensagem e a encaminha para uma das várias instâncias do serviço messenger.
- O serviço messenger grava a nova mensagem em seu banco de dados.
- O serviço messenger produz um evento em uma fila de mensagens do RabbitMQ chamada chat_queue para indicar que uma mensagem foi enviada. O evento é genérico e não tem um destino específico.
- Ao mesmo tempo:
- 4a. O serviço messenger retorna uma resposta ao remetente informando que a mensagem foi enviada com sucesso.
- 4b. O serviço notifier detecta o novo evento na chat_queue e o consome.
- O serviço notifier verifica em seu banco de dados as preferências de notificação do destinatário da nova mensagem.
- O serviço notifier usa o método preferido do destinatário para enviar uma ou mais notificações (neste tutorial, as opções de método são SMS e e-mail).
Objetivos de telemetria
Ao configurar a instrumentação de telemetria, é melhor começar com um conjunto de objetivos mais bem definidos do que simplesmente “enviar tudo e esperar obter insights”. Neste tutorial, temos três objetivos principais de telemetria:
- Entender todas as etapas pelas quais uma solicitação passa durante o fluxo de uma nova mensagem
- Tenha confiança de que o fluxo está sendo executado de ponta a ponta em até cinco segundos em condições normais
- Veja quanto tempo o serviço notifier leva para começar a processar o evento enviado pelo serviço messenger (uma demora excessiva pode indicar que o serviço notifier está com dificuldades para ler a fila de eventos e que os eventos estão se acumulando)
Observe que esses objetivos estão relacionados tanto à operação técnica do sistema quanto à experiência do usuário.
Pré-requisitos e configuração do tutorial
Pré-requisitos
Para concluir o tutorial em seu próprio ambiente, você precisa de:
- Um ambiente compatível com Linux/Unix Observação: As atividades deste tutorial que envolvem o rastreamento do NGINX não funcionam em processadores baseados em ARM, pois o módulo OpenTelemetry para NGINX não é compatível. (Isso inclui arquiteturas Linux aarch64 e computadores Apple com chip M1 ou M2.) As atividades que envolvem os serviços messenger e notifier funcionam em todas as arquiteturas.
- Familiaridade básica com a linha de comando do Linux, JavaScript e
bash(mas todo o código e todos os comandos são fornecidos e explicados, portanto, você pode concluir as atividades mesmo com conhecimento limitado) - Docker e Docker Compose
- Node.js 19.x ou posterior
- Testamos a versão 19.x, mas esperamos que as versões mais recentes do Node.js também funcionem.
- Para obter informações detalhadas sobre a instalação do Node.js, consulte o README no repositório do serviço messenger. Você também pode instalar o
asdfpara usar exatamente a mesma versão do Node.js utilizada no tutorial.
curl(já instalado na maioria dos sistemas)- As tecnologias listadas em Arquitetura e fluxo do usuário: messenger e notifier (você fará o download delas na próxima seção), NGINX Open Source, Jaeger e RabbitMQ.
Observação: O tutorial usa o SDK JavaScript porque os serviços messenger e notifier são escritos em Node.js. Você também configura o recurso de instrumentação automática do OTel (também chamado de autoinstrumentação) para ter uma ideia do tipo de informação disponibilizada pelo OTel. O tutorial explica tudo o que você precisa saber sobre o SDK do OTel para Node.js, mas, para obter mais detalhes, consulte a documentação do OTel.
Configuração
- Inicie uma sessão de terminal.
- No seu diretório pessoal, crie o diretório microservices-march e clone nele os repositórios do GitHub usados neste tutorial. (Você também pode usar outro nome de diretório e adaptar as instruções conforme necessário.) Observação: ao longo do tutorial, o prompt da linha de comando do Linux é omitido para facilitar a cópia e a colagem dos comandos no terminal. O til (
~) representa seu diretório pessoal.
mkdir ~/microservices-marchcd ~/microservices-march git clone https://github.com/microservices-march/messenger --branch mm23-metrics-start git clone https://github.com/microservices-march/notifier --branch mm23-metrics-start git clone https://github.com/microservices-march/platform --branch mm23-metrics-startDesafio 1: configure a instrumentação básica do OTel
Neste desafio, você vai iniciar o serviço messenger service e configurar a instrumentação automática do OTel para enviar a telemetria ao console.
Inicie o serviço messenger
- Acesse o repositório platform e inicie o Docker Compose:
cd ~/microservices-march/platformdocker compose up -d --build- Isso inicia o RabbitMQ e o Jaeger, que serão usados nos desafios seguintes.
- A opção
‑dinstrui o Docker Compose a se desvincular dos contêineres após eles serem iniciados (caso contrário, os contêineres permanecerão vinculados ao seu terminal). - A opção
--buildinstrui o Docker Compose a recriar todas as imagens na inicialização. Isso garante que as imagens em execução permaneçam atualizadas caso haja alterações nos arquivos.
- A opção
- Acesse o diretório app no repositório messenger e instale o Node.js (você pode usar outro método, se preferir):
cd ~/microservices-march/messenger/appasdf install- Instale as dependências:
npm install- Inicie o banco de dados PostgreSQL para o serviço messenger:
docker compose up -d- Crie o esquema e as tabelas do banco de dados e insira alguns dados iniciais:
npm run refresh-dbConfigure a instrumentação automática do OTel enviada ao console
Com a instrumentação automática do OTel, você não precisa modificar nada na base de código do messenger para configurar o rastreamento. Em vez de ser importada diretamente no código da aplicação, toda a configuração de rastreamento é definida em um script importado para o processo do Node.js em tempo de execução.
Aqui, você configura a instrumentação automática do serviço messenger usando o destino mais básico para os traces: o console. No Desafio 2, você alterará a configuração para enviar os traces ao Jaeger como um coletor externo.
- Ainda no diretório app do repositório messenger, instale os principais pacotes do OTel para Node.js:
npm install @opentelemetry/sdk-node@0.36.0 \ @opentelemetry/auto-instrumentations-node@0.36.4- Estas bibliotecas oferecem as seguintes funcionalidades: Observação: Uma peculiaridade do OTel é que seus SDKs JavaScript são divididos em partes muito, muito pequenas. Portanto, você instalará alguns pacotes adicionais apenas para o exemplo básico deste tutorial. Para entender quais pacotes podem ser necessários para realizar tarefas de instrumentação além das abordadas neste tutorial, consulte os excelentes guias de introdução do OTel e explore o repositório do GitHub do OTel.
@opentelemetry/sdk-node– Geração e exportação de dados do OTel@opentelemetry/auto-instrumentations-node– Configuração automática com as definições padrão de todas as instrumentações mais comuns do Node.js
- Crie um novo arquivo chamado tracing.mjs para incluir o código de instalação e configuração do rastreamento do OTel:
touch tracing.mjs- No editor de texto de sua preferência, abra tracing.mjs e adicione este código:
//1
import opentelemetry from "@opentelemetry/sdk-node";
import { getNodeAutoInstrumentations } from "@opentelemetry/auto-instrumentations-node";
//2
const sdk = new opentelemetry.NodeSDK({
traceExporter: new opentelemetry.tracing.ConsoleSpanExporter(),
instrumentations: [getNodeAutoInstrumentations()],
});
//3
sdk.start();- O código faz o seguinte:
- Importa as funções e os objetos necessários do SDK do OTel.
- Cria uma nova instância do NodeSDK e a configura para:
- Enviar spans para o console (
ConsoleSpanExporter). - Use o autoinstrumentador como o conjunto básico de instrumentação. Essa instrumentação carrega todas as bibliotecas de autoinstrumentação mais comuns. Neste tutorial, as relevantes são:
@opentelemetry/instrumentation-pgpara a biblioteca do banco de dados Postgres (pg)@opentelemetry/instrumentation-expresspara o framework Express do Node.js@opentelemetry/instrumentation-amqplibpara a biblioteca RabbitMQ (amqplib)
- Enviar spans para o console (
- Inicia o SDK.
- Inicie o serviço messenger, importando o script de autoinstrumentação que você criou na Etapa 3.
node --import ./tracing.mjs index.mjs- Após alguns instantes, muitas informações relacionadas ao rastreamento começam a aparecer no console (seu terminal):
...
{
traceId: '9c1801593a9d3b773e5cbd314a8ea89c',
parentId: undefined,
traceState: undefined,
name: 'fs statSync',
id: '2ddf082c1d609fbe',
kind: 0,
timestamp: 1676076410782000,
duration: 3,
attributes: {},
status: { code: 0 },
events: [],
links: []
}
...Observação: Deixe a sessão do terminal aberta para reutilizá-la no Desafio 2.
Desafio 2: configure a instrumentação do OTel e a visualização de traces para todos os serviços
Há muitas ferramentas que você pode usar para visualizar e analisar traces, mas este tutorial usa o Jaeger. O Jaeger é um framework simples e de código aberto para rastreamento distribuído de ponta a ponta, com uma interface de usuário integrada baseada na Web para visualizar spans e outros dados de rastreamento. A infraestrutura fornecida no repositório platform inclui o Jaeger (que você iniciou na Etapa 1 do Desafio 1), para que possa se concentrar na análise dos dados em vez de lidar com ferramentas complexas.
O Jaeger pode ser acessado pelo endpoint http://localhost:16686 no seu navegador, mas, se você acessar o endpoint agora, não haverá nada para ver sobre o seu sistema. Isso acontece porque os rastros que você está coletando no momento estão sendo enviados para o console! Para visualizar os dados de rastreamento no Jaeger, você precisa exportar os rastros usando o formato do protocolo OpenTelemetry (OTLP).
Neste desafio, você instrumentará o fluxo principal do usuário configurando a instrumentação para:
- O serviço messenger service, alterando o destino dos rastreamentos do console para o Jaeger
- O serviço notifier service
- NGINX
Configurar a instrumentação automática do OTel enviada a um coletor externo
Vale lembrar que usar a autoinstrumentação do OTel significa que você não precisa modificar nada na base de código do messenger para configurar o rastreamento. Em vez disso, toda a configuração de rastreamento fica em um script importado para o processo do Node.js em tempo de execução. Aqui, você altera o destino dos rastros gerados pelo serviço messenger, que deixam de ser enviados ao console e passam a ser enviados a um coletor externo (o Jaeger, neste tutorial).
- Ainda no mesmo terminal usado no Desafio 1 e no diretório app do repositório messenger, instale o pacote Node.js do exportador OTLP:
npm install @opentelemetry/exporter-trace-otlp-http@0.36.0- A biblioteca
@opentelemetry/exporter-trace-otlp-httpexporta informações de rastreamento no formato OTLP via HTTP. Ela é usada ao enviar telemetria para um coletor externo do OTel. - Abra tracing.mjs (que você criou e editou no Desafio 1) e faça estas alterações: Observação: Para simplificar, o tutorial pressupõe que o coletor esteja no local padrão, http://localhost:4318/v1/traces. Em um sistema real, é recomendável definir o local explicitamente.
- Adicione esta linha ao conjunto de instruções
importno início do arquivo:
- Adicione esta linha ao conjunto de instruções
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";- Altere o “exporter” fornecido ao SDK do OTel, substituindo o exporter de console usado no Desafio 1 por um que possa enviar dados OTLP via HTTP para um coletor compatível com OTLP. Substitua:
traceExporter:new opentelemetry.tracing.ConsoleSpanExporter(),- com:
traceExporter: new OTLPTraceExporter({ headers: {} }),- Pressione
Ctrl+cpara interromper o serviço messenger, que você iniciou neste terminal na Etapa 4 de Configurar o envio da autoinstrumentação do OTel para o console. Em seguida, reinicie-o para usar o novo exportador configurado na Etapa 2:
^cnode --import ./tracing.mjs index.mjs- Inicie uma segunda sessão de terminal separada. (Nas instruções a seguir, ela será chamada de terminal do cliente e o terminal original – usado nas etapas 1 e 3 – de terminal do messenger.) Aguarde cerca de dez segundos e envie uma solicitação de verificação de integridade ao serviço messenger (você pode executar esse comando algumas vezes se quiser ver vários rastreamentos):
curl -X GET http://localhost:4000/health- Aguardar dez segundos antes de enviar a solicitação facilita a localização do seu trace, pois ele aparece depois dos vários traces gerados pela instrumentação automática durante a inicialização do serviço.
- Em um navegador, acesse a interface do Jaeger em http://localhost:16686 e verifique se o exportador OTLP está funcionando conforme o esperado. Clique em Search na barra de título e, no menu suspenso do campo Service, selecione o serviço cujo nome começa com unknown_service. Clique no botão Find Traces:

- Clique em um trace no lado direito da janela para exibir uma lista dos spans contidos nele. Cada span descreve as operações, que às vezes envolvem vários serviços, executadas como parte do trace. O span jsonParser na captura de tela mostra quanto tempo levou para executar a parte
jsonParserdo código de tratamento de solicitações do serviço messenger.
- Como observado na Etapa 5, o nome do serviço exportado pelo SDK do OTel (unknown_service) não é significativo. Para corrigir isso, no terminal do messenger, pressione
Ctrl+cpara interromper o serviço messenger. Em seguida, instale mais alguns pacotes do Node.js:
^c npm install @opentelemetry/semantic-conventions@1.10.0 \ @opentelemetry/resources@1.10.0- Essas duas bibliotecas oferecem as seguintes funcionalidades:
@opentelemetry/semantic-conventions– Define os atributos padrão para rastreamentos, conforme estabelecido na especificação do OTel.@opentelemetry/resources– Define um objeto (recurso) que representa a origem que gera os dados do OTel (neste tutorial, o serviço messenger).
- Abra tracing.mjs em um editor de texto e faça estas alterações:
- Adicione estas linhas ao conjunto de instruções
importno início do arquivo:
- Adicione estas linhas ao conjunto de instruções
import { Resource } from "@opentelemetry/resources";import { SemanticResourceAttributes } from "@opentelemetry/semantic-conventions";- Crie um
resourcechamadomessengerna chave correta da especificação do OTel, adicionando a seguinte linha após a última instruçãoimport:
const resource = new Resource({ [SemanticResourceAttributes.SERVICE_NAME]: "messenger",
});- Passe o objeto
resourcepara o construtor do NodeSDK adicionando a linha destacada em laranja entre as linhas em preto:
const sdk = new opentelemetry.NodeSDK({ resource,
traceExporter: new OTLPTraceExporter({ headers: {} }),
instrumentations: [getNodeAutoInstrumentations()],
});- Reinicie o serviço messenger:
node --import ./tracing.mjs index.mjs- Aguarde cerca de dez segundos e, no terminal do cliente (que você abriu na Etapa 4), envie outra solicitação de verificação de integridade ao servidor (você pode executar o comando algumas vezes se quiser ver vários rastreamentos):
curl -X GET http://localhost:4000/health- Observação: Deixe o terminal do cliente aberto para reutilizá-lo na próxima seção e o terminal do mensageiro aberto para reutilizá-lo no Desafio 3.
- Confirme se um novo serviço chamado messenger aparece na interface do Jaeger no navegador (isso pode levar alguns segundos e talvez seja necessário atualizar a interface do Jaeger):

- Selecione messenger no menu suspenso Service e clique no botão Find Traces para ver todos os rastreamentos recentes originados pelo serviço messenger (a captura de tela mostra os 2 mais recentes de um total de 20):

- Clique em um trace para exibir os spans contidos nele. Cada span está devidamente identificado como originário do serviço messenger:

Configurar a instrumentação automática do OTel para o serviço notifier
Agora, inicie e configure a autoinstrumentação para o serviço notifier, executando basicamente os mesmos comandos usados nas duas seções anteriores para o serviço messenger.
- Abra uma nova sessão de terminal (chamada de terminal do notifier nas etapas seguintes). Acesse o diretório app no repositório notifier e instale o Node.js (você pode usar outro método, se preferir):
cd ~/microservices-march/notifier/appasdf install- Instale as dependências:
npm install- Inicie o banco de dados PostgreSQL para o serviço notifier:
docker compose up -d- Crie o esquema e as tabelas do banco de dados e insira alguns dados iniciais:
npm run refresh-db- Instale os pacotes do OTel para Node.js (para ver uma descrição da função dos pacotes, consulte as etapas 1 e 3 em Configurar a autoinstrumentação do OTel enviada ao Console):
npm install @opentelemetry/auto-instrumentations-node@0.36.4 \ @opentelemetry/exporter-trace-otlp-http@0.36.0 \ @opentelemetry/resources@1.10.0 \ @opentelemetry/sdk-node@0.36.0 \ @opentelemetry/semantic-conventions@1.10.0- Crie um novo arquivo chamado tracing.mjs:
touch tracing.mjs- No seu editor de texto preferido, abra tracing.mjs e adicione o script a seguir para colocar o SDK do OTel em funcionamento:
import opentelemetry from "@opentelemetry/sdk-node";
import { getNodeAutoInstrumentations } from "@opentelemetry/auto-instrumentations-node";
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
import { Resource } from "@opentelemetry/resources";
import { SemanticResourceAttributes } from "@opentelemetry/semantic-conventions";
const resource = new Resource({
[SemanticResourceAttributes.SERVICE_NAME]: "notifier",
});
const sdk = new opentelemetry.NodeSDK({
resource,
traceExporter: new OTLPTraceExporter({ headers: {} }),
instrumentations: [getNodeAutoInstrumentations()],
});
sdk.start();- Observação: Este script é exatamente igual ao usado no serviço messenger, exceto pelo valor do campo
SemanticResourceAttributes.SERVICE_NAME, que énotifier. - Inicie o serviço notifier com a instrumentação automática do OTel:
node --import ./tracing.mjs index.mjs- Aguarde cerca de dez segundos e, em seguida, no terminal do cliente, envie uma solicitação de verificação de integridade para o serviço notifier. Esse serviço está escutando na porta 5000 para evitar conflito com o serviço messenger, que está escutando na porta 4000:
curl http://localhost:5000/health- Observação: Deixe os terminais do cliente e do notificador abertos para reutilizá-los no Desafio 3.
- Confirme se um novo serviço chamado notifier aparece na interface do Jaeger no navegador:

Configurar a instrumentação do OTel no NGINX
No NGINX, você configura o rastreamento manualmente em vez de usar o método de autoinstrumentação do OTel. Atualmente, a maneira mais comum de instrumentar o NGINX usando o OTel é utilizar um módulo escrito em C. Os módulos de terceiros são uma parte importante do ecossistema do NGINX, mas exigem algum trabalho de configuração. Este tutorial faz essa configuração para você. Para obter informações adicionais, consulte Compilação de módulos dinâmicos de terceiros para NGINX e NGINX Plus em nosso blog.
- Inicie uma nova sessão de terminal (o terminal do NGINX), acesse o diretório raiz do repositório messenger e crie um novo diretório chamado load-balancer, além de novos arquivos chamados Dockerfile, nginx.conf e opentelemetry_module.conf:
cd ~/microservices-march/messenger/mkdir load-balancer cd load-balancer touch Dockerfile touch nginx.conf touch opentelemetry_module.conf- No seu editor de texto preferido, abra o arquivo Dockerfile e adicione o seguinte (os comentários explicam o que cada linha faz, mas você pode criar e executar o contêiner Docker sem entender tudo):
FROM --platform=amd64 nginx:1.23.1
# Replace the nginx.conf file with our own
COPY nginx.conf /etc/nginx/nginx.conf
# Define the version of the NGINX OTel module
ARG OPENTELEMETRY_CPP_VERSION=1.0.3
# Define the search path for shared libraries used when compiling and running NGINX
ENV LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/opt/opentelemetry-webserver-sdk/sdk_lib/lib
# 1. Download the latest version of Consul template and the OTel C++ web server module, otel-webserver-module
ADD https://github.com/open-telemetry/opentelemetry-cpp-contrib/releases/download/webserver%2Fv${OPENTELEMETRY_CPP_VERSION}/opentelemetry-webserver-sdk-x64-linux.tgz /tmp
RUN apt-get update \
&& apt-get install -y --no-install-recommends dumb-init unzip \
# 2. Extract the module files
&& tar xvfz /tmp/opentelemetry-webserver-sdk-x64-linux.tgz -C /opt \
&& rm -rf /tmp/opentelemetry-webserver-sdk-x64-linux.tgz \
# 3. Install and add the 'load_module' directive at the top of the main NGINX configuration file
&& /opt/opentelemetry-webserver-sdk/install.sh \
&& echo "load_module /opt/opentelemetry-webserver-sdk/WebServerModule/Nginx/1.23.1/ngx_http_opentelemetry_module.so;\n$(cat /etc/nginx/nginx.conf)" > /etc/nginx/nginx.conf
# 4. Copy in the configuration file for the NGINX OTel module
COPY opentelemetry_module.conf /etc/nginx/conf.d/opentelemetry_module.conf
EXPOSE 8085
STOPSIGNAL SIGQUIT- Abra o arquivo nginx.conf e adicione o seguinte:
events {}
http {
include /etc/nginx/conf.d/opentelemetry_module.conf;
upstream messenger {
server localhost:4000;
}
server {
listen 8085;
location / {
proxy_pass http://messenger;
}
}
}- Este arquivo extremamente básico de configuração do NGINX instrui o NGINX a: Observação: Esta configuração é bastante semelhante à configuração real do NGINX como proxy reverso e balanceador de carga em um ambiente de produção. A única diferença significativa é que o argumento da diretiva
serverno blocoupstreamgeralmente é um nome de domínio ou endereço IP, em vez delocalhost.- Configure um grupo upstream chamado messenger que represente o grupo de instâncias do serviço messenger service instances
- Escute solicitações HTTP na porta 8085
- Encaminhe todas as solicitações recebidas para caminhos que começam com / (ou seja, todas as solicitações recebidas) para o upstream messenger upstream
- Abra o arquivo opentelemetry_module.conf e adicione o seguinte:
NginxModuleEnabled ON;NginxModuleOtelSpanExporter otlp;
NginxModuleOtelExporterEndpoint localhost:4317;
NginxModuleServiceName messenger-lb;
NginxModuleServiceNamespace MicroservicesMarchDemoArchitecture;
NginxModuleServiceInstanceId DemoInstanceId;
NginxModuleResolveBackends ON;
NginxModuleTraceAsError ON;- Crie uma imagem Docker contendo o NGINX e o módulo OTel do NGINX:
docker build -t messenger-lb .- Inicie o contêiner Docker para o proxy reverso e balanceador de carga NGINX:
docker run --rm --name messenger-lb -p 8085:8085 --network="host" messenger-lb- No terminal do cliente, envie uma solicitação de verificação de integridade para o serviço messenger por meio do proxy reverso e balanceador de carga NGINX (não é necessário aguardar antes de enviar esta solicitação):
curl http://localhost:8085/health- Observação: Deixe os terminais do NGINX e do cliente abertos para reutilizá-los no Desafio 3.
- No navegador, confirme se o novo serviço messenger-lb está listado na interface do Jaeger junto com os serviços que você iniciou anteriormente. Talvez seja necessário recarregar a interface do Jaeger no navegador.

Desafio 3: Aprenda a interpretar traces do OTel
Em Arquitetura e fluxo do usuário, descrevemos as etapas do fluxo do usuário, mas, para recapitular:
- Um usuário inicia uma conversa enviando uma mensagem para outro usuário.
- O proxy reverso NGINX intercepta a mensagem e a encaminha para o serviço messenger.
- O serviço messenger grava a mensagem em seu banco de dados e, em seguida, dispara um evento por meio do RabbitMQ.
- O serviço notifier consome esse evento, consulta as preferências de notificação do destinatário (segundo usuário) e envia uma notificação a ele pelo método de sua preferência.
E os objetivos da implementação da telemetria são:
- Entender todas as etapas pelas quais uma solicitação passa para concluir o novo fluxo de mensagens.
- Tenha a certeza de que o fluxo é executado de ponta a ponta em até cinco segundos em condições normais.
- Veja quanto tempo o serviço notifier leva para começar a processar o evento enviado pelo serviço messenger.
Neste desafio, você aprenderá a avaliar se os rastros gerados pela instrumentação do OTel atendem aos objetivos mencionados anteriormente. Primeiro, você testa o sistema e cria alguns rastros. Em seguida, você inspeciona o rastro de um fluxo de mensagens e as seções dele geradas pelo NGINX, pelo serviço messenger service e pelo serviço notifier service.
Criar dados de rastreamento
No terminal do cliente, inicie uma conversa e envie algumas mensagens entre dois usuários:
curl -X POST \ -H "Content-Type: application/json" \ -d '{"participant_ids": [1, 2]}' \ 'http://localhost:8085/conversations' curl -X POST \ -H "User-Id: 1" \ -H "Content-Type: application/json" \ -d '{"content": "This is the first message"}' \ 'http://localhost:8085/conversations/1/messages' curl -X POST \ -H "User-Id: 2" \ -H "Content-Type: application/json" \ -d '{"content": "This is the second message"}' \ 'http://localhost:8085/conversations/1/messages'Uma saída como a seguinte é gerada pelo serviço notifier e aparece no terminal do notifier:
Received new_message: {"type":"new_message","channel_id":1,"user_id":1,"index":1,"participant_ids":[1,2]}Sending notification of new message via sms to 12027621401
Received new_message: {"type":"new_message","channel_id":1,"user_id":2,"index":2,"participant_ids":[1,2]}
Sending notification of new message via email to the_hotstepper@kamo.ze
Sending notification of new message via sms to 19147379938Prepare-se para ler os traces
Abra a interface do Jaeger no navegador, selecione messenger-lb no menu suspenso Serviço e clique no botão Localizar traces. Uma lista de traces será exibida, começando pelo início do fluxo. Clique em qualquer trace para exibir seus detalhes, como nesta captura de tela:

Clique nos elementos e explore um pouco. Depois, antes de prosseguir, considere como as informações nos rastreamentos ajudam a alcançar seus objetivos de instrumentação, conforme descrito na introdução ao Desafio 3. Algumas perguntas relevantes são:
- Quais informações ajudam a atingir os objetivos?
- Quais informações estão faltando?
- Quais informações não são relevantes?
Examine a seção do NGINX (messenger-lb) no rastreamento
Objetivo 1: visualizar todas as etapas pelas quais uma solicitação passa no novo fluxo de mensagens
Comece pelo span do NGINX, que contém 11 spans filhos dentro do span pai. Como a configuração atual do NGINX é muito simples, os spans filhos não são muito interessantes e apenas mostram o tempo gasto em cada etapa do ciclo de vida do processamento de solicitações do NGINX. No entanto, o span pai (o primeiro de todos) contém algumas informações interessantes:

- Em Tags você vê os seguintes atributos: juntas, essas três informações indicam que: “Uma solicitação
POSTfoi enviada para/conversations/1/messagese a resposta foi201(criada com sucesso)”. Isso corresponde às etapas 1 e 4a em Arquitetura e fluxo do usuário).http.methodcampo –POST(em termos de REST, isso significa criação)http.status_codecampo –201(indicando que a criação foi bem-sucedida)http.targetcampo –conversations/1/messages(o endpoint de mensagens)
- Em Process, o campo
webengine.namemostra que esta é a parte da solicitação processada pelo NGINX.
Além disso, como os spans de messenger e notifier estão aninhados no span messenger-lb conversations/1 (conforme mostrado na captura de tela em Prepare-se para ler os traces), é possível concluir que a solicitação enviada ao serviço messenger por meio do proxy reverso NGINX passou por todos os componentes esperados no fluxo.
Essas informações atendem ao objetivo, pois permitem ver que o proxy reverso NGINX fez parte do fluxo.
Meta 2: verificar se o fluxo é executado em até cinco segundos
Na lista de spans identificados como messenger-lb, observe o span mais recente (ele está no final da lista) para ver quanto tempo levou a parte da solicitação processada pelo NGINX. Na captura de tela, o span começou em 589 microssegundos (µs) e durou 24 µs, o que significa que a operação completa do proxy reverso levou apenas 613 µs — cerca de 0,6 milissegundo (ms). (Naturalmente, os valores exatos serão diferentes quando você executar o tutorial.)

Em uma configuração como esta, na maioria das vezes os valores só são úteis quando comparados a outras medições e variam entre os sistemas. Neste caso, porém, está claro que esta operação não corre o risco de chegar perto de cinco segundos de duração.
Essas informações atendem ao objetivo, pois é possível ver que as operações do NGINX não levaram nem perto de cinco segundos. Se houver uma operação muito lenta no fluxo, ela deve estar ocorrendo mais adiante.
Objetivo 3: verificar quanto tempo o serviço notifier leva para ler o evento enviado pelo serviço messenger
A camada de proxy reverso do NGINX não inclui nenhuma informação sobre isso, então você pode passar para os spans do messenger.
Examine a seção messenger do rastreamento
Objetivo 1: visualizar todas as etapas pelas quais uma solicitação passa no novo fluxo de mensagens
A seção do serviço messenger no rastreamento contém mais 11 spans. Novamente, a maioria dos spans filhos diz respeito às etapas básicas que o framework Express executa ao processar uma solicitação e não é muito interessante. No entanto, o span pai (o primeiro de todos) mais uma vez traz algumas informações interessantes:

Em Tags você vê os seguintes atributos:
http.methodcampo –POST(novamente, em termos de REST, isso significa criação)http.routecampo –/conversations/:conversationId/messages(a rota de mensagens)http.targetcampo –/conversations/1/messages(o endpoint da mensagem)
Essas informações atendem ao objetivo porque mostram que o serviço messenger fez parte do fluxo e que o endpoint acessado foi o endpoint de nova mensagem.
Meta 2: verificar se o fluxo é executado em até cinco segundos
Conforme indicado na captura de tela a seguir, a parte messenger do rastreamento começou em 1,28 ms e terminou em 36,28 ms, totalizando 35 ms. A maior parte desse tempo foi gasta analisando o JSON (middleware - jsonParser) e, em uma proporção muito maior, conectando-se ao banco de dados (pg-pool.connect e tcp.connect).
Isso faz sentido, já que várias consultas SQL também são realizadas durante o processo de gravação da mensagem. Isso, por sua vez, sugere que talvez seja interessante ampliar a configuração da instrumentação automática para registrar o tempo de execução dessas consultas. (O tutorial não mostra essa instrumentação adicional, mas, no Desafio 4, você cria spans manualmente, que podem ser usados para encapsular consultas ao banco de dados.)

Essas informações atendem ao objetivo porque mostram que as operações do messenger não levam nem perto de cinco segundos. Se houver uma operação muito lenta no fluxo, ela deve estar ocorrendo mais adiante.
Objetivo 3: verificar quanto tempo o serviço notifier leva para ler o evento enviado pelo serviço messenger
Assim como os spans do NGINX, os spans do messenger não incluem essas informações, então você pode passar para os spans do notifier.
Examine a seção notifier do rastreamento
Objetivo 1: visualizar todas as etapas pelas quais uma solicitação passa no novo fluxo de mensagens
A seção notifier do rastreamento contém apenas dois spans:

- O intervalo
chat_queueprocessconfirma que o serviço notifier processou um evento da fila de mensagens chat_queue message queue - O span
pg-pool.connect– Mostra que, após processar o evento, o serviço notifier estabeleceu algum tipo de conexão com seu banco de dados
As informações disponíveis nesses spans atendem apenas parcialmente ao objetivo de compreender cada etapa. É possível ver que o serviço notifier chegou ao ponto de consumir o evento da fila, mas não é possível saber se:
- A notificação de mensagem enviada por este serviço corresponde ao evento disparado pelo serviço messenger service
- As notificações relevantes da mensagem foram enviadas corretamente ao destinatário da mensagem
Isso indica que você precisa fazer o seguinte para entender completamente o fluxo do serviço notifier:
- Instrumente manualmente os spans que mostram o envio de uma notificação
- Garanta que haja uma conexão explícita entre o evento enviado pelo serviço messenger e o evento consumido pelo serviço notifier, na forma de um ID de rastreamento
Objetivo 2: verificar se o fluxo é executado em até cinco segundos
Ao analisar o tempo total dos spans do serviço notifier, você observa que a solicitação levou 30,77 ms na seção notifier do fluxo. No entanto, como não há spans que indiquem o “fim” de todo o fluxo (o envio de notificações ao destinatário), não é possível determinar o tempo total dessa seção do fluxo nem o tempo total de conclusão da operação.
Objetivo 3: veja quanto tempo o serviço notifier leva para ler o evento enviado pelo serviço messenger
No entanto, você pode ver que um intervalo de chat_queue process do serviço notifier começou em 6,12 ms, 2 ms depois que um intervalo de chat_queue send do serviço messenger começou em 4,12 ms.

Esse objetivo é alcançado porque você sabe que o notifier consumiu um evento 2 ms após ele ter sido enviado pelo serviço messenger. Ao contrário do objetivo 2, para alcançar esse objetivo, você não precisa saber se o evento foi processado por completo nem quanto tempo isso levou.
Conclusões
Com base em nossa análise dos traces produzidos pela atual instrumentação automática do OTel, fica claro que:
- Muitos desses spans não são úteis em sua forma atual:
- O NGINX está produzindo spans relacionados a funções — como verificação de autorização e disponibilização de arquivos — que não são relevantes para a função de seu interesse: o proxy reverso. No entanto, atualmente, a instrumentação OTel para NGINX não permite omitir spans irrelevantes, portanto, não há nada que possa ser feito.
- Entre os spans dos serviços Node.js (os serviços messenger e notifier), alguns parecem relevantes para os objetivos: os spans da análise de JSON,
requesthandlere de todas as operações de banco de dados. Alguns spans de middleware (comoexpressInitecorsMiddleware) não parecem relevantes e podem ser removidos.
- Estão faltando spans críticos para os seguintes itens:
- Notificações enviadas pelo serviço notifier service
- Um mapeamento claro entre o evento do RabbitMQ enviado pelo serviço messenger e aquele processado pelo serviço notifier service
Isso significa que a instrumentação básica cumpre o último objetivo:
- Veja quanto tempo o serviço notifier leva para começar a processar o evento enviado pelo serviço messenger service
No entanto, não há informações suficientes para atingir os dois primeiros objetivos:
- Entender todas as etapas pelas quais uma solicitação passa durante o novo fluxo de mensagens
- Tenha confiança de que o fluxo é executado de ponta a ponta em menos de cinco segundos em circunstâncias normais
Desafio 4: otimize a instrumentação com base nas leituras de rastreamento
Neste desafio, você otimiza a instrumentação do OTel com base nas análises de rastreamento realizadas no Desafio 3. Isso inclui tanto remover spans desnecessários, quanto criar novos spans personalizados e confirmar que o evento consumido pelo serviço de notificação é o mesmo gerado pelo serviço de mensagens.
Remover spans desnecessários
- No editor de texto de sua preferência, abra o arquivo tracing.mjs no diretório app do repositório messenger e adicione o seguinte ao final da lista de instruções de importação no início do arquivo:
const IGNORED_EXPRESS_SPANS = new Set([ "middleware - expressInit",
"middleware - corsMiddleware",
]);- Isso define um conjunto de nomes de spans, com base na lista de spans exibida na captura de tela a seguir da interface do Jaeger, que devem ser omitidos do trace porque não fornecem informações úteis para esse fluxo. Você pode decidir que outros spans listados na captura de tela também não são necessários e adicioná-los à lista de
IGNORED_EXPRESS_SPANS.
- Adicione filtros à configuração de instrumentação automática para omitir os spans indesejados, alterando a linha destacada em laranja:
const sdk = new opentelemetry.NodeSDK({ resource,
traceExporter: new OTLPTraceExporter({ headers: {} }),
instrumentations: [getNodeAutoInstrumentations()],
});- para isto:
const sdk = new opentelemetry.NodeSDK({ resource,
traceExporter: new OTLPTraceExporter({ headers: {} }),
instrumentations: [ getNodeAutoInstrumentations({ "@opentelemetry/instrumentation-express": { ignoreLayers: [ (name) => { return IGNORED_EXPRESS_SPANS.has(name); }, ], }, }), ],
});- A função
getNodeAutoInstrumentationsfaz referência ao conjunto de spans definido na Etapa 1 para filtrá-los do rastreamento gerado por@opentelemetry/instrumentation-express. Em outras palavras, a instruçãoreturnresulta emtruepara um span que pertence aIGNORED_EXPRESS_SPANS, e a instruçãoignoreLayersremove esse span do rastreamento. - No terminal do messenger, pressione
Ctrl+cpara interromper o serviço messenger. Em seguida, reinicie-o:
^cnode --import ./tracing.mjs index.mjs- Aguarde cerca de dez segundos e, em seguida, envie uma nova mensagem no terminal do cliente:
curl -X POST \ -H "User-Id: 2" \ -H "Content-Type: application/json" \ -d '{"content": "This is the second message"}' \ 'http://localhost:8085/conversations/1/messages'- Verifique novamente os spans do messenger na interface do Jaeger. Os dois spans de
middleware,expressInitecorsMiddleware, não aparecem mais (você pode comparar com a captura de tela da Meta 2 de Examinar a seção messenger do trace no Desafio 3.
Configure spans personalizados
Nesta seção, você terá contato com o código da aplicação pela primeira vez. A instrumentação automática gera uma quantidade considerável de informações sem exigir alterações na aplicação, mas alguns insights só são possíveis ao instrumentar partes específicas da lógica de negócios.
Para o novo fluxo de mensagens que você está instrumentando, um exemplo disso é rastrear o envio de notificações ao destinatário da mensagem.
- Abra o arquivo index.mjs no diretório app do repositório notifier. Esse arquivo contém toda a lógica de negócios do serviço. Adicione a linha a seguir ao final da lista de instruções
importno início do arquivo:
import { trace } from "@opentelemetry/api";- Substitua este código (aproximadamente na linha 91 do arquivo):
for (let pref of preferences) {
console.log(
`Sending notification of new message via ${pref.address_type} to ${pref.address}`
);
}- com:
const tracer = trace.getTracer("notifier"); // 1tracer.startActiveSpan( // 2
"notification.send_all",
{
attributes: {
user_id: msg.user_id,
},
},
(parentSpan) => {
for (let pref of preferences) {
tracer.startActiveSpan( // 3
"notification.send",
{
attributes: { // 4
notification_type: pref.address_type,
user_id: pref.user_id,
},
},
(span) => {
console.log(
`Sending notification of new message via ${pref.address_type} to ${pref.address}`
);
span.end(); // 5
}
);
}
parentSpan.end(); // 6
}
);- O novo código faz o seguinte: ter um span pai garante que cada operação de “envio de notificação” seja registrada, mesmo que nenhuma preferência de notificação seja encontrada para o usuário.
- Obtém o
tracer, que é um objeto global usado para interagir com traces do OTel. - Inicia um novo span pai chamado
notification.send_alle define o atributouser_idpara identificar o remetente da mensagem. - Entra em um loop no qual as preferências de notificação do destinatário são enumeradas e um novo span filho chamado
notification.sendé criado sobnotification.send_all. Cada notificação gera um novo span. - Define mais atributos para o span filho:
notification_type– Um dos seguintes:smsouemailuser_id– O ID do usuário que recebe a notificação
- Fecha cada span filho
notification.sendpor vez. - Encerra o span pai
notification.send_all.
- Obtém o
- No terminal do notifier, pressione
Ctrl+cpara interromper o serviço notifier. Em seguida, reinicie-o:
^cnode --import ./tracing.mjs index.mjs- Aguarde cerca de dez segundos e, em seguida, envie uma nova mensagem no terminal do cliente:
curl -X POST \ -H "User-Id: 2" \ -H "Content-Type: application/json" \ -d '{"content": "This is the second message"}' \ 'http://localhost:8085/conversations/1/messages'- Verifique novamente os spans do notifier na interface do Jaeger. Você verá o span pai e dois spans filhos, cada um com uma operação “send notification”:

Agora você pode atingir plenamente o primeiro e o segundo objetivos, pois consegue visualizar todas as etapas pelas quais uma solicitação passa durante o novo fluxo de mensagens. As informações de tempo de cada span revelam qualquer atraso entre essas etapas.
Confirme se o messenger e o notifier estão processando o mesmo evento
Há mais uma coisa de que você precisa para ter uma visão completa do fluxo. O evento que está sendo processado pelo serviço notifier é de fato o mesmo que foi enviado pelo serviço messenger?
Você não precisa fazer nenhuma alteração explícita para conectar os dois traces, mas também não deve confiar cegamente na mágica da instrumentação automática.
Com isso em mente, adicione rapidamente um código de depuração para verificar se o rastreamento iniciado no serviço NGINX é realmente o mesmo (tem o mesmo ID de rastreamento) que aquele consumido pelo serviço notifier.
- Abra o arquivo index.mjs no diretório app do repositório messenger e faça estas alterações:
- Adicione a linha a seguir ao final da lista de instruções de importação no início do arquivo:
import { trace } from "@opentelemetry/api";- Adicione as linhas destacadas em laranja abaixo da linha existente em preto:
async function createMessageInConversation(req, res) {
const tracer = trace.getActiveSpan(); console.log("TRACE_ID: ", tracer.spanContext().traceId);- As novas linhas exibem o
TRACE_IDde dentro da função no messenger que processa a criação de uma nova mensagem.
- Abra o arquivo index.mjs no diretório app do repositório notifier e adicione a linha destacada em laranja abaixo da linha existente em preto:
export async function handleMessageConsume(channel, msg, handlers) { console.log("RABBIT_MQ_MESSAGE: ", msg);- A nova linha exibe todo o conteúdo do evento AMQP recebido pelo serviço notifier.
- Pare e reinicie os serviços messenger e notifier executando estes comandos nos terminais do messenger e do notifier:
^cnode --import ./tracing.mjs index.mjs- Aguarde cerca de dez segundos e, em seguida, envie uma mensagem novamente no terminal do cliente:
curl -X POST \ -H "User-Id: 2" \ -H "Content-Type: application/json" \ -d '{"content": "This is the second message"}' \ 'http://localhost:8085/conversations/1/messages'- Consulte os logs dos serviços messenger e notifier. O log do serviço messenger inclui uma linha como esta, que informa o ID de rastreamento de uma mensagem (o ID real será diferente quando você executar o tutorial):
TRACE_ID: 29377a9b546c50be629c8e64409bbfb5- Da mesma forma, o log do serviço notifier apresenta um ID de rastreamento em uma saída como esta:
_spanContext: {
traceId: '29377a9b546c50be629c8e64409bbfb5',
spanId: 'a94e9462a39e6dbf',
traceFlags: 1,
traceState: undefined
},- Os IDs de rastreamento correspondem no console, mas, como etapa final, você pode compará-los ao ID de rastreamento na interface do Jaeger. Abra a interface no endpoint do ID de rastreamento relevante (o seu será diferente, mas, neste exemplo, é http://localhost:16686/trace/29377a9b546c50be629c8e64409bbfb5) para visualizar o rastreamento completo. O rastreamento do Jaeger confirma que:
- A instrumentação automática de AMQP no serviço messenger adiciona esse ID de rastreamento aos metadados quando o evento é enviado.
- A instrumentação automática de AMQP no serviço notifier espera esses metadados e define o contexto de rastreamento adequadamente.
Observação: Em um sistema de produção real, você removeria o código adicionado nesta seção após confirmar que o fluxo está funcionando conforme o esperado.
Limpeza de recursos
Você criou alguns contêineres e imagens ao longo deste tutorial! Siga estas instruções para removê-los.
- Para remover todos os contêineres do Docker em execução:
docker rm $(docker stop messenger-lb)- Para remover o serviço platform e os serviços de banco de dados messenger e notifier:
cd ~/microservices-march/platform && docker compose down cd ~/microservices-march/notifier && docker compose down cd ~/microservices-march/messenger && docker compose downPróximos passos
Parabéns, você concluiu o tutorial!
- Você configurou a instrumentação do OTel em um proxy reverso NGINX e em dois serviços Node.js.
- Você analisou criticamente os dados fornecidos pela instrumentação automática do OTel e adicionou alguns dados de telemetria que estavam faltando para atingir os objetivos do laboratório de OTel:
- Você obteve uma visão razoável do fluxo de uma solicitação específica por um sistema de mensageria sem alterar diretamente nenhum código da aplicação.
- Você confirmou que o fluxo era executado de ponta a ponta em menos de cinco segundos em circunstâncias normais.
E, ainda assim, você mal começou a explorar como seria uma configuração de rastreamento ideal! Em um ambiente de produção, talvez seja interessante adicionar recursos como spans personalizados para cada consulta ao banco de dados e metadados adicionais em todos os spans, descrevendo detalhes do ambiente de execução, como o ID do contêiner de cada serviço. Você também poderia implementar os outros dois tipos de dados do OTel (métricas e logs) para ter uma visão completa da integridade do seu sistema.
Para continuar aprendendo sobre microsserviços, confira o Microservices March 2023. Na Unidade 4: Gerencie o caos e a complexidade dos microsserviços com observabilidade, você aprenderá sobre as três principais classes de dados de observabilidade, a importância do alinhamento entre a infraestrutura e a aplicação e maneiras de começar a analisar dados aprofundados.

Sobre o autor
Publicações relacionadas no blog

Como o F5 NGINX One aprimora o gerenciamento e a observabilidade
Descubra como o F5 NGINX One aprimora o gerenciamento e a observabilidade de ambientes híbridos e multicloud ao oferecer um console web centralizado baseado em SaaS, com insights em tempo real, conformidade automatizada e gerenciamento simplificado de configurações.

Do OpenAPI ao NGINX como gateway de API usando uma API declarativa
Descubra como transformar uma definição de esquema OpenAPI em uma configuração NGINX totalmente funcional, operando como um API Gateway com a segurança de um Web Application Firewall e um Portal do Desenvolvedor, usando uma abordagem declarativa de API.

Como gerenciar picos repentinos de tráfego e sobrecarga do servidor
Picos de tráfego e sobrecarga de servidores são preocupações sérias para varejistas online em qualquer época, mas especialmente durante a “Cyber Season” de compras de fim de ano. Detalhamos como você pode aproveitar as soluções de entrega de aplicações de nível de produção da NGINX para se preparar para aumentos repentinos de tráfego.

Distribuição segura de chaves privadas SSL com o NGINX
Descrevemos três maneiras progressivamente mais seguras de proteger chaves privadas SSL ao configurar o NGINX para processar tráfego HTTPS: permitir acesso de leitura apenas ao usuário root, criptografar as chaves com senhas armazenadas separadamente e distribuir as senhas a partir de um repositório central.
Agrupando solicitações de API em lotes com NGINX Plus e o módulo JavaScript do NGINX
O módulo JavaScript do NGINX lançado com o NGINX Plus R15 oferece suporte a subsolicitações, possibilitando uma classe totalmente nova de casos de uso para o NGINX Plus. Este exemplo completo também usa a API do NGINX Plus e os módulos de chave-valor para converter solicitações de API dos clientes em solicitações separadas para as APIs dos microsserviços que compõem um aplicativo.
Como superar o esgotamento de portas efêmeras no NGINX e no NGINX Plus
Confira dicas para evitar o esgotamento de portas efêmeras com ajustes no kernel do Linux, conexões keepalive e conexões vinculadas dinamicamente a endereços IP locais.