As diretrizes conhecidas como aplicativo dos doze fatores foram publicadas pela primeira vez há mais de dez anos. Desde então, quase todas as suas práticas obrigatórias se tornaram o padrão de fato para escrever e implantar aplicativos web. E embora elas tenham permanecido aplicáveis diante de mudanças na maneira como os aplicativos são organizados e implantados, em alguns casos são necessárias nuances adicionais para entender como as práticas se aplicam aos padrões de microsserviços para desenvolver e implantar aplicativos.
Este blog se concentra no Fator 3, Configuração da loja no ambiente , que afirma:
À medida que você avança para microsserviços, você ainda pode honrar essas diretrizes, mas nem sempre de uma forma que mapeie exatamente para uma interpretação literal do aplicativo de doze fatores. Algumas diretrizes, como fornecer dados de configuração como variáveis de ambiente, são transferidas muito bem. Outras práticas comuns de microsserviços, embora respeitem os princípios básicos do aplicativo de doze fatores, são mais como extensões dele. Nesta postagem, veremos três conceitos principais de gerenciamento de configuração para microsserviços pela lente do Fator 3:
Antes de entrar na discussão sobre a adaptação do Fator 3 para microsserviços, é útil entender alguns termos e conceitos importantes.
Com um aplicativo monolítico, todas as equipes da organização trabalham no mesmo aplicativo e na infraestrutura ao redor. Embora aplicativos monolíticos geralmente pareçam mais simples do que microsserviços no papel, há vários motivos comuns pelos quais as organizações decidem migrar para microsserviços:
É claro que os microsserviços apresentam seus próprios desafios – incluindo maior complexidade, menos observabilidade e a necessidade de novos modelos de segurança – mas muitas organizações, especialmente as grandes ou de rápido crescimento, decidem que os desafios valem a pena para dar às suas equipes mais autonomia e flexibilidade na criação de bases confiáveis e estáveis para as experiências que fornecem aos seus clientes.
Ao refatorar um aplicativo monolítico em microsserviços, seus serviços devem:
Para um aplicativo monolítico, pequenas inconsistências nos processos e dependência de suposições compartilhadas não são críticas. No entanto, com muitos microsserviços separados, essas inconsistências e suposições podem gerar muita dor e caos. Muitas das mudanças que você precisa fazer com microsserviços são necessidades técnicas, mas um número surpreendente diz respeito à forma como as equipes trabalham internamente e interagem com outras equipes.
Mudanças organizacionais notáveis com uma arquitetura de microsserviços incluem:
Uma área da arquitetura de microsserviços onde precisamos estender o Fator 3 diz respeito à necessidade de definir claramente certas informações vitais sobre um serviço, incluindo sua configuração, e assumir um mínimo de contexto compartilhado com outros serviços. O fator 3 não aborda isso diretamente, mas é especialmente importante com um grande número de microsserviços separados contribuindo para a funcionalidade do aplicativo.
Como proprietário de serviço em uma arquitetura de microsserviços, sua equipe possui serviços que desempenham funções específicas no sistema como um todo. Outras equipes cujos serviços interagem com os seus precisam acessar o repositório do seu serviço para ler código e documentação, bem como fazer contribuições.
Além disso, é uma realidade infeliz no campo do desenvolvimento de software que a composição da equipe muda frequentemente, não apenas porque os desenvolvedores entram e saem da empresa, mas também por causa da reorganização interna. Além disso, a responsabilidade por um determinado serviço também é frequentemente transferida entre equipes.
Em vista dessas realidades, sua base de código e documentação precisam ser extremamente claras e consistentes, o que é alcançado por:
Muitas estruturas de aplicativos fornecem um meio para definir a configuração necessária. Por exemplo, o pacote NPM convict
para aplicativos Node.js usa um “esquema” de configuração completo armazenado em um único arquivo. Ele atua como a fonte da verdade para toda a configuração que um aplicativo Node.js precisa para ser executado.
Um esquema robusto e facilmente detectável facilita a interação confiante dos membros da sua equipe e de outras pessoas com seu serviço.
Depois de definir claramente quais valores de configuração seu aplicativo precisa, você também precisa honrar a importante distinção entre as duas fontes principais das quais um aplicativo de microsserviços implantado extrai sua configuração:
Scripts de implantação são um padrão comum de organização de código em arquiteturas de microsserviços. Como são novidades desde a publicação original do aplicativo dos doze fatores, eles necessariamente representam uma extensão dele.
Nos últimos anos, tornou-se comum ter uma pasta chamada infraestrutura (ou alguma variante desse nome) no mesmo repositório do código do seu aplicativo. Geralmente contém:
À primeira vista, isso pode parecer uma violação da prescrição do Fator 3 de que a configuração é estritamente separada do código.
Na verdade, sua colocação ao lado do seu aplicativo significa que uma pasta de infraestrutura realmente respeita a regra, ao mesmo tempo em que permite melhorias valiosas no processo, essenciais para equipes que trabalham em ambientes de microsserviços.
Os benefícios desse padrão incluem:
Observe que os benefícios fornecidos por esse padrão reforçam a autonomia individual da equipe, ao mesmo tempo em que garantem que rigor adicional seja aplicado ao processo de implantação e configuração.
Na prática, você usa os scripts de implantação armazenados na sua pasta de infraestrutura para gerenciar tanto a configuração definida explicitamente nos próprios scripts quanto a recuperação da configuração de fontes externas no momento da implantação, tendo o script de implantação para um serviço:
Valores de configuração que são específicos para uma determinada implantação do seu serviço e totalmente sob o controle da sua equipe podem ser especificados diretamente nos arquivos na pasta de infraestrutura. Um exemplo pode ser algo como um limite no tempo que uma consulta de banco de dados iniciada pelo aplicativo pode ser executada. Este valor pode ser alterado modificando o arquivo de implantação e reimplantando o aplicativo.
Um benefício desse esquema é que as alterações nessa configuração necessariamente passam por revisão de código e testes automatizados, diminuindo a probabilidade de que um valor mal configurado cause uma interrupção. Alterações nos valores que passam pela revisão de código e nos valores das chaves de configuração a qualquer momento podem ser descobertas no histórico das suas ferramentas de controle de origem.
Os valores necessários para a execução do aplicativo, mas que não estão sob o controle da sua equipe, devem ser fornecidos pelo ambiente no qual o aplicativo é implantado. Um exemplo é o nome do host e a porta na qual o serviço se conecta a outro microsserviço do qual depende.
Como esse serviço não é de propriedade da sua equipe, você não pode fazer suposições sobre valores como o número da porta. Esses valores podem mudar a qualquer momento e precisam ser registrados em algum armazenamento de configuração central quando são alterados, seja essa alteração feita manualmente ou por algum processo automático. Eles podem então ser consultados por aplicativos que dependem deles.
Podemos resumir essas diretrizes em duas práticas recomendadas para configuração de microsserviços.
Pode parecer mais simples codificar determinados valores em seus scripts de implantação, por exemplo, a localização de um serviço com o qual seu serviço interage. Na prática, a codificação desse tipo de configuração é perigosa, especialmente em ambientes modernos, onde os locais de serviço mudam com frequência. E é particularmente perigoso se você não possui o segundo serviço.
Você pode pensar que pode confiar em sua própria diligência para manter um local de serviço atualizado em seus scripts ou, pior, que pode confiar na equipe proprietária para informá-lo quando o local mudar. A diligência muitas vezes falha em momentos de estresse e, dependendo do rigor humano, seu sistema corre o risco de falhar sem aviso prévio.
Independentemente de as informações de localização serem codificadas ou não, seu aplicativo não deve depender de infraestrutura crítica estar em um determinado local. Em vez disso, um serviço recém-implantado precisa fazer algumas perguntas comuns dentro do sistema, como "onde está meu banco de dados?" e receber uma resposta precisa sobre a localização atual desse recurso externo. Fazer com que cada serviço se registre no sistema à medida que é implantado torna as coisas muito mais simples.
Assim como o sistema precisa fornecer respostas às perguntas "onde está meu banco de dados?" e "onde está o 'serviço X' do qual estou dependendo?", um serviço deve ser exposto ao sistema de tal forma que outros serviços possam facilmente encontrá-lo e falar com ele sem saber nada sobre como ele é implantado.
Uma prática de configuração fundamental em arquiteturas de microsserviços é a descoberta de serviços: o registro de novas informações de serviço e a atualização dinâmica dessas informações conforme acessadas por outros serviços. Depois de explicar por que a descoberta de serviços é necessária para microsserviços, vamos explorar um exemplo de como realizá-la com NGINX Open Source e Consul.
É uma prática comum ter várias instâncias (implantações) de um serviço em execução ao mesmo tempo. Isso permite não apenas o manuseio de tráfego adicional, mas também a atualização de um serviço sem tempo de inatividade por meio do lançamento de uma nova implantação. Atuando como proxy reverso e balanceador de carga, ferramentas como o NGINX processam o tráfego de entrada e o roteiam para a instância mais apropriada. Esse é um bom padrão, porque os serviços que dependem do seu serviço enviam solicitações somente ao NGINX e não precisam saber nada sobre suas implantações.
Por exemplo, digamos que você tenha uma única instância de um serviço chamado messenger em execução no NGINX, atuando como um proxy reverso.
E se seu aplicativo se tornar popular? Isso é considerado uma boa notícia, mas então você percebe que, devido ao aumento do tráfego, a instância do messenger está consumindo muita CPU e demorando mais para processar solicitações, enquanto o banco de dados parece estar funcionando bem. Isso indica que você pode resolver o problema implantando outra instância do serviço de mensagens .
Quando você implanta a segunda instância do serviço de mensagens , como o NGINX sabe que ela está ativa e começa a enviar tráfego para ela? Adicionar manualmente novas instâncias à sua configuração do NGINX é uma abordagem, mas rapidamente se torna incontrolável à medida que mais serviços aumentam ou diminuem.
Uma solução comum é rastrear os serviços em um sistema com um registro de serviços de alta disponibilidade, como o Consul . Novas instâncias de serviço são registradas no Consul à medida que são implantadas. O Consul monitora o status das instâncias enviando periodicamente verificações de integridade. Quando uma instância falha nas verificações de integridade, ela é removida da lista de serviços disponíveis.
O NGINX pode consultar um registro como o Consul usando uma variedade de métodos e ajustar seu roteamento adequadamente. Lembre-se de que, ao atuar como um proxy reverso ou balanceador de carga, o NGINX roteia o tráfego para servidores “upstream”. Considere esta configuração simples:
# Defina um grupo upstream chamado "messenger_service"
upstream messenger_service {
server 172.18.0.7:4000;
server 172.18.0.8:4000;
}
server {
listen 80;
location /api {
# Proxy de tráfego HTTP com caminhos começando com '/api' para o
# bloco 'upstream' acima. O algoritmo de balanceamento de carga padrão,
# Round-Robin, alterna solicitações entre os dois servidores
# no bloco.
proxy_pass http://messenger_service;
proxy_set_header X-Forwarded-For $remote_addr;
}
}
Por padrão, o NGINX precisa saber o endereço IP e a porta precisos de cada instância do messenger para rotear o tráfego para ela. Neste caso, é a porta 4000 em 172.18.0.7 e 172.18.0.8.
É aqui que entram o Consul e o modelo Consul . O modelo do Consul é executado no mesmo contêiner que o NGINX e se comunica com o cliente do Consul que mantém o registro de serviço.
Quando as informações do registro são alteradas, o modelo do Consul gera uma nova versão do arquivo de configuração do NGINX com os endereços IP e portas corretos, grava-o no diretório de configuração do NGINX e informa ao NGINX para recarregar sua configuração. Não há tempo de inatividade quando o NGINX recarrega sua configuração , e a nova instância começa a receber tráfego assim que a recarga é concluída.
Com um proxy reverso como o NGINX nesse tipo de situação, há um único ponto de contato para registrar no sistema como o local para outros serviços acessarem. Sua equipe tem flexibilidade para gerenciar instâncias de serviço individuais sem precisar se preocupar com outros serviços perdendo acesso ao serviço como um todo.
É certo que os microsserviços aumentam a complexidade, tanto em termos técnicos para seus serviços quanto em termos organizacionais para seus relacionamentos com outras equipes. Para aproveitar os benefícios de uma arquitetura de microsserviços, é importante reexaminar criticamente as práticas projetadas para monólitos para garantir que elas ainda forneçam os mesmos benefícios quando aplicadas a um ambiente muito diferente. Neste blog, exploramos como o Fator 3 do aplicativo de doze fatores ainda fornece valor em um contexto de microsserviços, mas pode se beneficiar de pequenas mudanças em como ele é aplicado concretamente.
Para saber mais sobre como aplicar o aplicativo de doze fatores às arquiteturas de microsserviços, confira a Unidade 1 de Microsserviços de março de 2023 ( em breve no blog ). Registre-se gratuitamente para ter acesso a um webinar sobre este tópico e a um laboratório prático.
"Esta postagem do blog pode fazer referência a produtos que não estão mais disponíveis e/ou não têm mais suporte. Para obter as informações mais atualizadas sobre os produtos e soluções F5 NGINX disponíveis, explore nossa família de produtos NGINX . O NGINX agora faz parte do F5. Todos os links anteriores do NGINX.com redirecionarão para conteúdo semelhante do NGINX no F5.com."