Dominar a arquitetura da API
Concebe, opera e desenvolve sistemas baseados em
API
James Gough, Daniel Bryant e Matthew Auburn
Dominar a arquitetura da API
por James Gough, Daniel Bryant e Matthew Auburn
Direitos de autor © 2023 James Gough Ltd, Big Picture Tech Ltd, e
Matthew Auburn Ltd. Todos os direitos reservados.
Impresso nos Estados Unidos da América.
Publicado por O'Reilly Media, Inc., 1005 Gravenstein Highway North,
Sebastopol, CA 95472.
Os livros da O'Reilly podem ser adquiridos para uso educacional, comercial
ou promocional de vendas. As edições on-line também estão disponíveis
para a maioria dos títulos([Link] Para mais informações,
contacta o nosso departamento de vendas empresariais/institucionais: 800-
998-9938 ou corporate@[Link].
Editor de aquisições: Melissa Duffield
Editor de desenvolvimento: Virginia Wilson
Editor de produção: Clare Laylock
Redator: Kim Cofer
Revisor: Amnet Systems LLC
Indexador: nSight, Inc.
Designer de interiores: David Futato
Desenha a capa: Karen Montgomery
Ilustra: Kate Dullea
outubro de 2022: Primeira edição
Histórico de revisões da primeira edição
2022-10-17: Primeiro lançamento
Consulta [Link] para
obteres informações sobre o lançamento.
O logótipo O'Reilly é uma marca registada da O'Reilly Media, Inc.
Mastering API Architecture, a imagem da capa e a imagem comercial
relacionada são marcas comerciais da O'Reilly Media, Inc.
Embora a editora e os autores tenham envidado esforços de boa fé para
garantir que as informações e instruções contidas nesta obra são exactas, a
editora e os autores declinam qualquer responsabilidade por erros ou
omissões, incluindo, sem limitação, a responsabilidade por danos
resultantes da utilização ou confiança nesta obra. A utilização das
informações e instruções contidas nesta obra é feita por tua conta e risco. Se
qualquer amostra de código ou outra tecnologia que esta obra contenha ou
descreva estiver sujeita a licenças de código aberto ou a direitos de
propriedade intelectual de terceiros, é da tua responsabilidade garantir que a
tua utilização está em conformidade com essas licenças e/ou direitos.
978-1-492-09063-2
[LSI]
Dedicação
Este livro é dedicado a Alex Blewitt, que infelizmente faleceu antes da
publicação. Gostaríamos de agradecer ao Alex pelo seu feedback sincero,
apoio constante e amizade calorosa ao longo dos anos.
-Os Autores
Prefácio
Quando criei as minhas primeiras APIs no Financial Times, há mais de uma
década, não havia muitas. Estávamos a construir uma arquitetura monólita e
as APIs serviam apenas para terceiros externos terem acesso ao nosso
conteúdo.
Agora, porém, as APIs estão em todo o lado e são fundamentais para o teu
sucesso na construção de um sistema.
Isso porque, na última década, algumas coisas se combinaram para mudar a
forma como muitos de nós fazemos desenvolvimento de software.
Em primeiro lugar, a tecnologia disponível para nós mudou. A ascensão da
computação em Cloud deu-nos o autosserviço e o aprovisionamento a
pedido. Os pipelines automatizados de construção e implantação
permitiram-nos fazer a integração e implantação contínuas, e os contentores
e as tecnologias associadas, como a orquestração, permitiram-nos executar
um grande número de pequenos serviços independentes como um sistema
distribuído.
Porque é que estamos a fazer isso? Por causa da segunda coisa: a pesquisa
que mostra que as organizações de desenvolvimento de software bem
sucedidas têm arquitecturas de acoplamento frouxo e equipas autónomas e
capacitadas. O sucesso aqui é definido em termos de um impacto positivo
no negócio: aumento da quota de mercado, produtividade e rentabilidade.
As nossas arquitecturas tendem agora a ser mais soltas, distribuídas e
construídas em torno de APIs. Queres que as tuas APIs sejam detectáveis,
consistentes e que não causem problemas aos consumidores, mesmo que
mudem inesperadamente ou desapareçam. Qualquer outra coisa irá acoplar
o trabalho e atrasar as tuas equipas.
Neste livro, James, Daniel e Matthew fornecem um guia abrangente e
prático para construir arquiteturas de API eficazes. Eles cobrem uma grande
quantidade de terreno, desde como construir e testar uma API individual,
passando pelo ecossistema em que as implementas, as formas de as lançar e
operar eficazmente e, talvez o mais importante, como utilizar APIs para
fazer evoluir a tua arquitetura. As primeiras APIs que construí no Financial
Times já não existem, e construímos esses sistemas de novo a partir do zero.
Isso é dispendioso. O James, o Daniel e o Matthew fornecem um modelo de
como lidar com as mudanças inevitáveis e fazer evoluir os teus sistemas,
utilizando as API como uma ferramenta fundamental.
A arquitetura de software foi definida como as decisões que são importantes
e difíceis de mudar. Estas são as decisões que farão com que o teu projeto
tenha sucesso - ou falhe.
O foco dos autores não está na arquitetura em abstração, mas em como
aplicar a arquitetura dentro de suas próprias organizações. Decidir adotar
um API gateway ou um service mesh, e qual deles, é exatamente o tipo de
decisão difícil de tomar que deve ser abordada com cautela e avaliada
cuidadosamente. O James, o Daniel e o Matthew dão uma orientação forte e
opinativa onde acham que é apropriado e, quando as opções são menos
claras, fornecem uma estrutura para te ajudar a fazer a melhor escolha para
as tuas circunstâncias.
Ilustram o livro com um estudo de caso prático e realista que pega nos
conceitos e mostra como os podes fazer funcionar na prática. O seu estudo
de caso evolui ao longo do livro, da mesma forma que os sistemas reais. Os
autores mostram que não é preciso fazer tudo de antemão; é possível
evoluir a arquitetura peça por peça, extraindo serviços e adicionando
ferramentas como API gateways e service meshes à medida que se descobre
a sua necessidade.
Quando construí as minhas primeiras APIs, cometi muitos erros. Gostava
de ter tido um livro como este, para me ajudar a perceber onde poderia
tropeçar e para me guiar em direção a decisões sensatas.
Recomendo este livro a qualquer pessoa que trabalhe em sistemas onde as
APIs desempenham um papel importante. Com ele, deves ser capaz de
desenvolver um conjunto consistente de ferramentas e normas para apoiar
todas as equipas que criam APIs na tua organização.
Sarah Wells,copresidente da conferência QCon London,consultora
independente e antigadiretora técnica doFinancial Times,Reading, Reino
Unido, setembro de 2022
Prefácio
Este trabalho foi traduzido com recurso a IA. Agradecemos o teu feedback e comentários:
translation-feedback@[Link]
Por que escrevemos este livro?
No início de 2020, participámos na O'Reilly Software Architecture em
Nova Iorque, onde o Jim e o Matt deram um workshop sobre APIs e uma
apresentação sobre gateways de API. O Jim e o Daniel conhecem-se da
comunidade Java de Londres e, como em muitos eventos de arquitetura,
juntámo-nos para falar sobre as nossas ideias e conhecimentos sobre
arquitecturas de API. Enquanto falávamos no corredor, vários delegados da
conferência vieram ter connosco e falaram sobre as suas experiências com
as API. As pessoas pediam as nossas ideias e orientações para o seu
percurso em matéria de API. Foi nessa altura que pensámos que escrever
um livro sobre o tema das API ajudaria a partilhar as nossas discussões nas
conferências com outros arquitectos.
Porque deves ler este livro?
Este livro foi concebido para fornecer uma visão completa sobre a
conceção, operação e evolução de uma arquitetura de API. Partilhámos a
nossa experiência e conselhos através da nossa escrita e de um estudo de
caso que imita um sistema de conferência de gestão de eventos da vida real,
que permite aos participantes ver e reservar sessões de apresentação. O
estudo de caso é apresentado ao longo do livro, com o objetivo de explorar
a forma como os conceitos abstratos se traduzem, por vezes, em aplicações
práticas. Se pretender uma visão geral de alto nível da evolução do estudo
de caso, pode encontrá-la no Capítulo 10.
Também acreditamos em permitir que tomes as tuas próprias decisões. Para
o apoiar, iremos:
Sê claro quando tiveres uma recomendação ou orientação forte.
Destaca as áreas de cuidado e os problemas que podes encontrar.
Fornece um Guia de Registo de Decisões de Arquitetura (ADR)1 para
ajudar a tomar a melhor decisão possível tendo em conta as
circunstâncias da tua arquitetura e fornecer orientações sobre o que
considerar (porque por vezes a resposta é "depende").
Destaca referências e artigos úteis onde podes encontrarconteúdos
mais aprofundados.
O livro não é apenas um livro de tecnologia de raiz. Sentimos que cobrir as
arquitecturas existentes com uma abordagem evolutiva em direção a
arquitecturas de API mais adequadas seria o mais benéfico para ti. Também
tentámos equilibrar isto com a perspetiva de novas tecnologias e
desenvolvimentos no domínio da arquitetura de API.
A quem se destina este livro
Embora tivéssemos uma persona inicial em mente ao criar este livro,
durante o processo de escrita e revisão surgiram três personas principais: o
programador, um arquiteto acidental e o arquiteto de soluções ou de
empresas. Descrevemos estas personas nas secções seguintes, com o
objetivo de que não só te identifiques com pelo menos uma delas, mas
também para que possas olhar para cada capítulo através das diferentes
lentes que estas personas fornecem.
Programador
É provável que tenhas programado profissionalmente durante vários anos e
que tenhas uma boa compreensão dos desafios, padrões e melhores práticas
comuns de desenvolvimento de software. Estás a aperceber-te cada vez
mais de que a marcha da indústria de software em direção à construção de
uma arquitetura orientada para os serviços (SOA) e à adoção de serviços
Cloud significa que a construção e operação de APIs está a tornar-se
rapidamente uma competência essencial. Estás interessado em aprender
mais sobre a conceção de APIs eficazes e testá-las. Queres explorar as
várias opções de implementação (por exemplo, comunicação síncrona
versus assíncrona) e tecnologias e aprender a fazer as perguntas certas e a
avaliar qual a melhor abordagem para um determinado contexto.
Arquiteto acidental
Provavelmente, tens vindo a desenvolver software há muitos anos e tens
trabalhado frequentemente como líder de uma equipa ou arquiteto de
software residente (mesmo que não tenhas os títulos oficiais). Compreendes
os principais conceitos de arquitetura, tais como a conceção para uma
elevada coesão e um acoplamento flexível, e aplica-os a todos os aspectos
do desenvolvimento de software, incluindo a conceção, os testes e os
sistemas operativos.
Percebe que a sua função está cada vez mais centrada na combinação de
sistemas para satisfazer os requisitos dos clientes. Isto pode incluir
aplicações criadas internamente e ofertas do tipo SaaS de terceiros. As APIs
desempenham um papel importante na integração bem-sucedida dos seus
sistemas com sistemas externos. Queres saber mais sobre as tecnologias de
suporte (por exemplo, API gateway, service mesh, etc.) e também
compreender como operar e proteger sistemas baseados em API.
Arquiteto de soluções/empresa
Há vários anos que desenha e constrói sistemas de software empresarial e,
muito provavelmente, tem a palavra arquiteto no seu título profissional ou
na descrição da sua função. É responsável pela visão global da entrega de
software e, normalmente, trabalha no contexto de uma grande organização
ou de uma série de grandes organizações interligadas.
Reconhece as mudanças que a última iteração de estilos de arquitetura
baseados em serviços está a ter na conceção, integração e governação do
software, e vê as APIs como fundamentais para o sucesso da estratégia de
software da sua organização. Está interessado em aprender mais sobre
padrões evolutivos e compreender como a escolha da conceção e
implementação de APIs terá impacto sobre isso. Também se quer
concentrar nas "ilities" multifuncionais - usabilidade, manutenção,
escalabilidade e disponibilidade - e compreender como construir sistemas
baseados em APIs que exibam essas propriedades, bem como fornecer
segurança.
O que vais aprender
Depois de leres este livro, vais compreender:
Os fundamentos das APIs REST e a melhor forma de criar, versionar e
testar APIs
Os padrões de arquitetura envolvidos na construção de uma plataforma
API
As diferenças na gestão do tráfego de API na entrada e na
comunicação serviço-a-serviço, e como aplicar padrões e tecnologias
como gateways de API e malhas de serviço
Modelação de ameaças e principais considerações de segurança para
APIs, tais como autenticação, autorização e encriptação
Como fazer evoluir os sistemas existentes para APIs e diferentes
implementações de destino, como a Cloud
E serás capaz de o fazer:
Concebe, constrói e testa sistemas baseados em API
Ajuda a implementar e a conduzir o programa API de uma organização
a partir de uma perspetiva arquitetónica
Implementar, lançar e configurar os principais componentes de uma
plataforma API
Implementa gateways e service meshes com base em estudos de caso
Identifica vulnerabilidades na arquitetura da API e implementa
medidas de mitigação da segurança
Contribui para as tendências emergentes das API e para as
comunidades associadas
O que este livro não é
Percebemos que as APIs abrangem um vasto espaço de mercado e
queremos deixar claro o que este livro não irá cobrir. Isso não significa que
acreditamos que esses tópicos não são importantes; no entanto, se
tentássemos cobrir tudo, não conseguiríamos partilhar o nosso
conhecimento de forma eficaz contigo.
Cobriremos padrões de aplicativos para migração e modernização que
incluirão o aproveitamento de plataformas Cloud, mas o livro não está
totalmente focado em tecnologias Cloud. Muitos de vocês terão arquiteturas
híbridas ou até mesmo terão todos os seus sistemas hospedados em data
centers. Queremos garantir que cobriremos os fatores operacionais e de
design das arquiteturas de API que suportam ambas as abordagens.
Olivro não está vinculado a uma linguagem específica, mas usará alguns
exemplos leves para demonstrar abordagens para construir/desenhar APIs e
sua infraestrutura correspondente. O livro se concentrará mais na
abordagem, e exemplos de código estarão disponíveis no repositório
GitHub que o acompanha.
O livro não favorece um estilo de arquitetura em detrimento de outro, no
entanto, discutiremos situações em que as abordagens arquitectónicas
podem causar limitações à oferta de API apresentada.
Convenções utilizadas neste livro
Neste livro são utilizadas as seguintes convenções tipográficas:
Itálico
Indica novos termos, URLs, endereços de e-mail, nomes de ficheiros e
extensões de ficheiros.
Constant width
Usado para listagens de programas, bem como dentro de parágrafos
para se referir a elementos do programa, como nomes de variáveis ou
funções, bases de dados, tipos de dados, variáveis de ambiente,
instruções e palavras-chave.
Constant width bold
Mostra comandos ou outro texto que deve ser digitado literalmente pelo
utilizador.
Constant width italic
Mostra o texto que deve ser substituído por valores fornecidos pelo
utilizador ou por valores determinados pelo contexto.
DICA
Este elemento significa uma dica ou sugestão.
NOTA
Este elemento significa uma nota geral.
AVISO
Este elemento indica um aviso ou precaução.
Utilizar exemplos de código
O material suplementar (exemplos de código, exercícios, etc.) está
disponível para transferência em [Link]
Se tiveres uma questão técnica ou um problema ao utilizar os exemplos de
código, envia uma mensagem de correio eletrónico para
bookquestions@[Link].
Este livro está aqui para te ajudar a fazer o teu trabalho. Em geral, se for
fornecido código de exemplo com este livro, podes utilizá-lo nos teus
programas e documentação. Não precisas de nos contactar para obter
permissão, a menos que estejas a reproduzir uma parte significativa do
código. Por exemplo, escrever um programa que use vários trechos de
código deste livro não requer permissão. A venda ou distribuição de
exemplos dos livros da O'Reilly requer permissão. Responder a uma
pergunta citando este livro e citando um exemplo de código não requer
permissão. Incorporar uma quantidade significativa de código de exemplo
deste livro na documentação do teu produto requer permissão.
Apreciamos, mas geralmente não exigimos, a atribuição. Uma atribuição
inclui normalmente o título, o autor, a editora e o ISBN. Por exemplo:
"Domina a arquitetura da API por James Gough, Daniel Bryant e Matthew
Auburn (O'Reilly). Copyright 2023 James Gough Ltd, Big Picture Tech Ltd,
e Matthew Auburn Ltd, 978-1-492-09063-2."
Se considerares que a tua utilização de exemplos de código não se enquadra
na utilização justa ou na autorização acima referida, não hesites em
contactar-nos através do endereço permissions@[Link].
Aprendizagem em linha da O'Reilly
NOTA
Há mais de 40 anos que a O'Reilly Media fornece formação em tecnologia e negócios,
conhecimentos e ideias para ajudar as empresas a ter sucesso.
A nossa rede única de especialistas e inovadores partilha os seus
conhecimentos e experiência através de livros, artigos e da nossa plataforma
de aprendizagem online. A plataforma de aprendizagem online da O'Reilly
dá-te acesso a cursos de formação em direto, percursos de aprendizagem
aprofundados, ambientes de codificação interactivos e uma vasta coleção de
textos e vídeos da O'Reilly e de mais de 200 outras editoras. Para obter mais
informações, visita [Link]
Como contactar-nos
Por favor, dirige os teus comentários e perguntas sobre este livro ao editor:
O'Reilly Media, Inc.
1005 Gravenstein Highway North
Sebastopol, CA 95472
800-998-9938 (nos Estados Unidos ou no Canadá)
707-829-0515 (internacional ou local)
707-829-0104 (fax)
Temos uma página web para este livro, onde listamos erratas, exemplos e
qualquer informação adicional. Podes aceder a esta página em
[Link]
Envia um e-mail para bookquestions@[Link] para fazeres comentários
ou perguntas técnicas sobre este livro.
Para notícias e informações sobre os nossos livros e cursos, visita
[Link]
Encontra-nos no LinkedIn: [Link]
Segue-nos no Twitter: [Link]
Vê-nos no YouTube: [Link]
Agradecimentos
Tal como acontece com quase todos os livros técnicos, apenas três nomes
podem ser listados como autores na capa deste livro, mas a realidade é que
muitas pessoas contribuíram, quer diretamente sob a forma de feedback
enquanto o livro era escrito, quer indiretamente através do seu ensino e
orientação ao longo dos anos.
Embora não seja possível enumerar todas as pessoas que nos ajudaram
durante esta viagem, gostaríamos de agradecer explicitamente às pessoas
que tiraram tempo das suas agendas ocupadas para nos proporcionarem
discussões aprofundadas, feedback e apoio.
Os nossos revisores técnicos: Sam Newman, Dov Katz, Sarah Wells,
Antoine Cailliau, Stefania Chaplin, Matt McLarty e Neal Ford.
Para pormenores gerais, encorajamento, conselhos e apresentações: Charles
Humble, Richard Li, Simon Brown, Nick Ebbitt, Jason Morgan, Nic
Jackson, Cliff Tiltman, Elspeth Minty, George Ball, Benjamin Evans e
Martijn Verberg.
A equipa O'Reilly: Virginia Wilson, Melissa Duffield e Nicole Tache.
James Gough
Gostaria de agradecer à minha família incrível: Megan, Emily e Anna. A
escrita não teria sido possível sem a sua ajuda e apoio. Também gostaria de
agradecer aos meus pais, Heather e Paul, por me incentivarem a aprender e
pelo seuapoio constante.
Gostaria de agradecer aos meus co-autores, Daniel e Matt; escrever um
livro é um desafio e, tal como a arquitetura, nunca é perfeito. Foi uma
viagem divertida e todos nós aprendemos muito uns com os outros e com os
nossos fantásticos revisores. Finalmente, gostaria de agradecer a Jon
Daplyn, Ed Safo, David Halliwell e Dov Katz por me terem dado apoio,
oportunidades e encorajamento ao longo da minha carreira.
Daniel Bryant
Gostaria de agradecer a toda a minha família pelo seu amor e apoio, tanto
durante o processo de criação como ao longo da minha carreira. Gostaria
também de agradecer ao Jim e ao Matt por serem grandes parceiros nesta
jornada de escrita. Começámos a escrever este livro no início de 2020,
quando a pandemia chegou. As nossas chamadas semanais às quartas-feiras
de manhã foram não só úteis para a colaboração, mas também uma grande
fonte de diversão e apoio à medida que os nossos mundos mudavam
rapidamente. Finalmente, gostaria de agradecer a todos os envolvidos na
London Java Community (LJC), às equipas InfoQ/QCon e a todos na
Ambassador Labs. Essas três comunidades me deram acesso a mentores,
orientação e muitas oportunidades. Espero um dia retribuir tudo isso.
Matthew Auburn
Gostaria de agradecer à minha fantástica mulher Hannah - sem o teu apoio
não teria conseguido escrever este livro. Obrigado a ambos os meus pais;
mostraram-me que tudo é possível e nunca deixaram de acreditar em mim.
Este livro foi uma experiência fantástica, e o Jim e o Dan foram ambos
excelentes mentores. Ambos me ensinaram muito e ajudaram-me a escrever
o melhor material possível. Um agradecimento adicional ao Jim - tu
introduziste-me à oratória e ajudaste-me mais do que qualquer outra pessoa
na minha carreira. Por último e mais importante, quero agradecer ao meu
filho Joshi: és uma alegria absoluta.
1 Aprenderás mais sobre os ADRs e a sua importância para a tomada e documentação de
decisões de arquitetura na Introdução.
Introdução
Nesta introdução, descobrirás os conceitos básicos das APIs e o seu
potencial para fazer parte do percurso da arquitetura. Apresentaremos uma
definição ligeira para as APIs e a sua utilização dentro e fora do processo.
Para demonstrar a importância das APIs, apresentaremos o estudo de caso
do sistema de conferências, um exemplo em execução que evoluirá ao
longo do livro. As APIs fora do processo permitem-te pensar para além de
uma simples arquitetura de três níveis; introduziremos padrões de tráfego e
a sua importância para o demonstrar. Apresentaremos um resumo das etapas
do estudo de caso, permitindo-te passar à frente se uma área for do teu
interesse imediato.
Para apresentar as APIs e o seu ecossistema associado, utilizaremos uma
série de artefactos importantes. Introduziremos o estudo de caso com
diagramas de modelo C4 e revisitaremos as especificidades e a lógica por
detrás da abordagem. Também aprenderás sobre a utilização de Registos de
Decisão de Arquitetura (ADRs) e o valor de definir claramente as decisões
ao longo do ciclo de vida do software. No final da introdução, delinearemos
as Diretrizes de ADR - a nossa abordagem para te ajudar a tomar decisões
quando a resposta é "depende".
A viagem da arquitetura
Qualquer pessoa que tenha feito uma longa viagem terá, sem dúvida,
deparado com a pergunta (e possivelmente persistente) "já chegámos?"Para
as primeiras perguntas, olha para o GPS ou para um planeador de rotas e faz
uma estimativa - esperando não encontrar atrasos pelo caminho. Da mesma
forma, a viagem para a construção de arquitecturas baseadas em API pode
ser complexa para os programadores e arquitectos navegarem; mesmo que
houvesse um GPS de Arquitetura, qual seria o seu destino?
A arquitetura é uma viagem sem destino e não é possível prever a forma
como as tecnologias e as abordagens arquitectónicas irão mudar. Por
exemplo, talvez não tenha sido possível prever que a tecnologia de malha
de serviço se tornaria tão amplamente utilizada, mas, depois de conhecer as
suas capacidades, pode fazer com que pense em evoluir a sua arquitetura
existente. Não são apenas as tecnologias que influenciam a mudança na
arquitetura; os novos requisitos e restrições comerciais também
impulsionam a mudança na direção da arquitetura.
O efeito culminante da entrega de valor incremental combinado com as
novas tecnologias emergentes conduz ao conceito de arquitetura evolutiva.
A arquitetura evolutiva é uma abordagem à mudança incremental de uma
arquitetura, centrando-se na capacidade de mudar com rapidez e reduzindo
o risco de impactos negativos. Ao longo do caminho, pedimos-te que tenhas
em mente os seguintes conselhos na abordagem da arquitetura da API:
Embora os arquitectos gostem de poder planear estrategicamente o
futuro, o ecossistema de desenvolvimento de software em constante
mudança torna isso difícil. Uma vez que não podemos evitar a mudança,
temos de a explorar.
—Construir Arquitecturas Evolutivas por Neal Ford,
Rebecca Parsons, e Patrick Kua (O'Reilly)
Em muitos projectos, as próprias APIs são evolutivas, exigindo mudanças à
medida que mais sistemas e serviços são integrados. A maioria dos
programadores construiu serviços que se concentram numa única função
sem considerar a reutilização mais ampla da API na perspetiva do
consumidor.
Conceção API-First é uma abordagem em que os programadores e
arquitectos consideram a funcionalidade do seu serviço e concebem uma
API de uma forma centrada no consumidor. O consumidor da API pode ser
uma aplicação móvel, outro serviço ou mesmo um cliente externo. No
Capítulo 1, iremos rever as técnicas de conceção para apoiar uma
abordagem API-First e descobrir como criamos APIs que são resistentes à
mudança e fornecem valor a uma ampla base de consumidores.
Se for responsável por um inventário técnico pré-existente, mostrar-lhe-
emos técnicas para evoluir a sua arquitetura de modo a promover a
utilização de APIs na sua plataforma. Por outro lado, se tiver sorte e tiver
uma tela em branco para trabalhar, partilharemos consigo os benefícios da
adoção de arquitecturas de APIs com base nos nossos anos de experiência,
destacando também os factores-chave na decisão de arquitetura.
Uma breve introdução às APIs
No campo da arquitetura de software, há um punhado de termos que são
incrivelmente difíceis de definir. O termo API, que significa interface de
programação de aplicativos, se enquadra nessa categorização, já que o
conceito surgiu pela primeira vez há 80 anos. Os termos que existem há um
tempo significativo acabam sendo usados em excesso e têm vários
significados em diferentes espaços de problemas. Consideramos que uma
API significa o seguinte:
Uma API representa uma abstração da implementação subjacente.
Uma API é representada por uma especificação que introduz tipos. Os
programadores podem compreender as especificações e utilizar
ferramentas para gerar código em várias linguagens para implementar
um consumidor de API (software que consome uma API).
Uma API tem uma semântica ou comportamento definido para
modelar eficazmente a troca de informações.
A conceção eficaz da API permite a extensão a clientes ou terceiros
para uma integração comercial.
Em termos gerais, as APIs podem ser divididas em duas categorias gerais,
dependendo se a invocação da API está em processo ou fora de processo. O
processo aqui referido é um processo do sistema operativo (SO). Por
exemplo, uma invocação de método Java de uma classe para outra é uma
invocação de API em processo, uma vez que a chamada é tratada pelo
mesmo processo a partir do qual a chamada foi efectuada. Uma aplicação
.NET que invoca uma API externa do tipo REST utilizando uma biblioteca
HTTP é uma invocação de API fora do processo, uma vez que a chamada é
tratada por um processo externo adicional que não o processo a partir do
qual a chamada foi efectuada. Normalmente, uma chamada de API fora do
processo envolverá dados que atravessam uma rede, potencialmente uma
rede local, uma rede de nuvem privada virtual (VPC) ou a Internet. Vamos
nos concentrar no último estilo de APIs; no entanto, os arquitetos
frequentemente encontrarão o requisito de remodelar uma API em processo
para uma API fora do processo. Para demonstrar esse conceito (e outros),
criaremos um estudo de caso em execução que evoluirá ao longo do livro.
Exemplo de execução: Estudo de caso do
sistema de conferência
Nós optámos por modelar um sistema de conferências para o nosso estudo
de caso porque o domínio é facilmente reconhecível, mas também oferece
complexidade suficiente para modelar uma arquitetura evolutiva.A Figura I-
1 visualiza o sistema de conferências ao mais alto nível, permitindo-nos
definir o contexto da arquitetura em discussão. O sistema é utilizado por um
cliente externo para criar a sua conta de participante, analisar as sessões de
conferência disponíveis e reservar a sua presença.
Figura I-1. Diagrama de contexto do sistema de conferência C4
Vamos ampliar a caixa do sistema de conferência na Figura I-2. A expansão
do sistema de conferência fornece-nos mais detalhes sobre os seus
principais componentes técnicos. O cliente interage com a aplicação Web,
que invoca APIs na aplicação de conferência. A aplicação de conferência
utiliza SQL para consultar o armazenamento de dados de apoio.
Figura I-2. Diagrama do contentor do sistema de conferência C4
A Figura I-2 revela que, do ponto de vista da API, a funcionalidade mais
interessante se encontra no contentor da aplicação de conferência.A Figura
I-3 faz uma ampliação deste contentor específico, permitindo explorar a
estrutura e as interações.
Quatro componentes principais e a base de dados estão envolvidos no
sistema atual. O Controlador da API enfrenta todo o tráfego de entrada da
IU e toma uma decisão sobre para onde encaminhar o pedido no sistema.
Este componente também seria responsável pela transferência da
representação ao nível da rede para um objeto ou representação em código.
O componente API Controller é intrigante do ponto de vista do roteamento
no processo e da atuação como um ponto de junção ou padrão de
controlador frontal. Para solicitações e processamento de API, esse é um
padrão importante; todas as solicitações passam pelo controlador, que toma
uma decisão sobre para onde a solicitação é direcionada. No Capítulo 3,
veremos o potencial de retirar o controlador do processo.
Os componentes Participante, Reserva e Sessão estão envolvidos na
tradução dos pedidos em consultas e executam SQL contra a base de dados
fora do processo. Na arquitetura existente, a base de dados é um
componente importante, potencialmente impondo relações - por exemplo,
restrições entre reservas e sessões.
Figura I-3. Diagrama dos componentes do sistema de conferência C4
Agora que chegámos ao nível de detalhe adequado, vamos rever os tipos de
interações da API no estudo de caso neste ponto .
Tipos de APIs no estudo de caso da conferência
Na Figura I-3, a seta da aplicação Web para o controlador da API é uma
chamada fora do processo, ao passo que a seta do controlador da API para
o componente dos participantes é um exemplo de uma chamada dentro do
processo. Todas as interações dentro do limite da aplicação de conferência
são exemplos de chamadas dentro do processo. A invocação dentro do
processo está bem definida e restringida pela linguagem de programação
utilizada para implementar a aplicação de conferência. A invocação é
segura em tempo de compilação (as condições em que o mecanismo de
intercâmbio é aplicado no momento da escrita do código).
Razões para alterar o sistema de conferências
A abordagem arquitetónica atual do funcionou durante muitos anos para o
sistema de conferências, mas o proprietário da conferência solicitou três
melhorias, que estão a conduzir a uma mudança arquitetónica:
Os organizadores da conferência gostariam de criar uma aplicação
móvel.
Os organizadores da conferência planeiam globalizar o seu sistema,
organizando dezenas de conferências em vez de uma por ano. Para
facilitar esta expansão, gostariam de se integrar com um sistema
externo de Call for Papers (CFP) para gerir os oradores e a sua
candidatura para apresentar sessões na conferência.
Os organizadores da conferência gostariam de desativar o seu centro
de dados privado e, em vez disso, executar o sistema da conferência
numa plataforma Cloud com alcance global.
O nosso objetivo é migrar o sistema de conferência para poder suportar os
novos requisitos, sem afetar o sistema de produção existente ou reescrever
tudo de uma só vez.
Da arquitetura em camadas à modelação de APIs
O ponto de partida do estudo de caso é uma arquitetura típica de três
camadas, composta por uma IU, uma camada de processamento do lado do
servidor e um armazenamento de dados. Para começar a discutir uma
arquitetura evolutiva, precisamos de um modelo para pensar sobre a forma
como os pedidos de API são processados pelos componentes. Precisamos
de um modelo/abstração que funcione tanto para a Cloud pública, como
para máquinas virtuais num centro de dados e para uma abordagem híbrida.
A abstração do tráfego nos permitirá considerar as interações fora do
processo entre um consumidor de API e um serviço de API, às vezes
chamado de produtor de API. Com abordagens arquitetônicas como a
arquitetura orientada a serviços (SOA) e a arquitetura baseada em
microsserviços, a importância de modelar as interações da API é crítica.
Aprender sobre o tráfego da API e o estilo de comunicação entre os
componentes será a diferença entre perceber as vantagens do aumento do
desacoplamento ou criar um pesadelo de manutenção.
AVISO
Tráfego padrões são usados por engenheiros de centros de dados para descrever trocas de rede
dentro de centros de dados e entre aplicações de baixo nível. No nível da API, estamos usando
padrões de tráfego para descrever fluxos entre grupos de aplicações. Para os propósitos deste
livro, estamos nos referindo a padrões de tráfego no nível da aplicação e da API.
Estudo de caso: Um passo evolutivo
Para começar a considerar os tipos de padrões de tráfego, será útil dar um
pequeno passo evolutivo na arquitetura do nosso estudo de caso. Na Figura
I-4, foi dado um passo para refactorizar a componente Attendee,
transformando-a num serviço independente, por oposição a um pacote ou
módulo dentro do sistema de conferências legado. O sistema de
conferências tem agora dois fluxos de tráfego: a interação entre o cliente e o
sistema de conferências legado e a interação entre o sistema legado e o
sistema de participantes.
Figura I-4. Etapa evolutiva do contexto do sistema de conferência C4
Tráfego Norte-Sul
Na Figura I-4, a interação entre o cliente e o sistema de conferência antigo é
referida como tráfego norte-sul e representa um fluxo de entrada. O cliente
está a utilizar a IU, que está a enviar pedidos para o sistema de conferência
antigo através da Internet. Isto representa um ponto na nossa rede que está
exposto publicamente e que será acedido pela IU.1 Isto significa que
qualquer componente que lide com o tráfego norte-sul deve fazer
verificações concretas sobre a identidade do cliente e também incluir
desafios apropriados antes de permitir que o tráfego avance através do
sistema.O Capítulo 7 entrará em detalhes sobre a segurança do tráfego da
API norte-sul.
Tráfego Este-Oeste
A nova interação entre o sistema de conferências antigo e o serviço
Attendee introduz um fluxo de tráfego este-oeste no nosso sistema. O
tráfego este-oeste pode ser considerado como um estilo de comunicação
serviço-a-serviço dentro de um grupo de aplicações. A maior parte do
tráfego este-oeste, especialmente se a origem estiver dentro da sua
infraestrutura mais alargada, pode ser de alguma forma fiável. Embora
possamos confiar na origem do tráfego, é ainda necessário considerar a
segurança do tráfego este-oeste .
Infraestrutura API e padrões de tráfego
Existem dois componentes-chave de infraestrutura presentes nas
arquitecturas baseadas em API, que são fundamentais para o controlo do
tráfego. O controlo e a coordenação do tráfego são frequentemente descritos
como gestão do tráfego. Geralmente, o tráfego norte-sul será controlado por
API gateways, o assunto-chave do Capítulo 3.
O tráfego leste-oeste será frequentemente tratado por componentes de
infraestrutura como Kubernetes ou service mesh, o assunto principal do
Capítulo 4. Componentes de infraestrutura como Kubernetes e service mesh
usam abstrações de rede para rotear serviços, exigindo que os serviços
sejam executados dentro de um ambiente gerenciado. Em alguns sistemas, o
tráfego leste-oeste é gerenciado pelo próprio aplicativo e técnicas de
descoberta de serviços são implementadas para localizar outros sistemas.
Estudo de caso do roteiro para a conferência
Ao longo do curso do livro, observarás as seguintes mudanças ou
aplicações da tecnologia ao estudo de caso:
No Capítulo 1, explorarás a conceção e a especificação da API
Attendee. Também apresentaremos a importância do controlo de
versões e das trocas de modelos para o desempenho da API Attendee.
No Capítulo 2, explorarás os testes de contrato e de componente para
verificar o comportamento do serviço Attendee. Também verás como
os Testcontainers podem ajudar nos testes de integração.
No Capítulo 3, verás como expor o serviço Attendee aos consumidores
usando um gateway de API. Também demonstraremos como evoluir o
sistema de conferência usando um gateway de API no Kubernetes.
No Capítulo 4, vamos refatorar a funcionalidade das sessões do
sistema de conferência legado usando um service mesh. Também
aprenderás como o service mesh ajuda no roteamento, na
observabilidade e na segurança.
No Capítulo 5, discutiremos a sinalização de recursos e como isso
pode ajudar a evoluir o sistema de conferência e evitar uma
implantação e uma versão acopladas. Também exploraremos
abordagens para modelar versões no sistema de conferência e
demonstraremos o uso do Argo Rollouts para o serviço Attendee.
No Capítulo 6, vais explorar como aplicar a modelação de ameaças e
mitigar as preocupações da OWASP no serviço Attendee.
No Capítulo 7, verás a autenticação e a autorização e como estas são
implementadas no serviço Attendee.
No Capítulo 8, verás como estabelecer os limites do domínio de
serviço do Participante e como os diferentes padrões de serviço podem
ajudar.
No Capítulo 9, vais analisar a adoção da Cloud e como mover o
serviço Attendee para a Cloud e considerar a possibilidade de
replataforma.
O estudo de caso e o roteiro planeado requerem a visualização da mudança
de arquitetura e o registo de decisões. Estes são artefactos importantes que
ajudam a explicar e a planear mudanças em projectos de software.
Acreditamos que os diagramas C4 e os Registos de Decisão de Arquitetura
(ADR) representam uma forma clara de registar a mudança .
Utilização de diagramas C4
Como parte da introdução do estudo de caso em , revelámos três tipos de
diagramas C4 a partir do modelo C4. Acreditamos que o C4 é o melhor
padrão de documentação para comunicar a arquitetura, o contexto e as
interações a um conjunto diversificado de partes interessadas. Poderás estar
a perguntar-te: e a UML? A Linguagem de Modelação Unificada (UML)
fornece um extenso dialeto para comunicar arquitecturas de software. Um
grande desafio é que a maior parte do que a UML fornece não é guardado
na memória por arquitectos e programadores, e as pessoas rapidamente
voltam a usar caixas/círculos/diamantes. Torna-se um verdadeiro desafio
compreender a estrutura dos diagramas antes de entrar no conteúdo técnico
da discussão. Muitos diagramas só ficam gravados no histórico do projeto
se alguém acidentalmente usar um marcador permanente em vez de um
marcador de limpeza a seco por engano. O modelo C4 fornece um conjunto
simplificado de diagramas que funcionam como um guia para a arquitetura
do projeto a vários níveis de detalhe.
Diagrama de contexto C4
AFigura I-1 é representada através de um diagrama de contexto C4 do
modelo C4. A intenção deste diagrama é definir o contexto tanto para um
público técnico como não técnico. Muitas conversas sobre arquitetura
mergulham diretamente nos pormenores de baixo nível e não definem o
contexto das interações de alto nível. Considera as implicações de um
diagrama de contexto do sistema errado - a vantagem de resumir a
abordagem pode poupar meses de trabalho para corrigir um mal-entendido.
Diagrama do contentor C4
Enquanto a Figura I-1 fornece o panorama geral do sistema de conferência,
um diagrama de contentores ajuda a descrever a divisão técnica dos
principais participantes na arquitetura. Um contentor em C4 é definido
como "algo que precisa de estar em funcionamento para que o sistema
geral funcione" (por exemplo, a base de dados da conferência). Os
diagramas de contentores são de natureza técnica e baseiam-se no diagrama
de contexto do sistema de nível superior.A Figura I-2, um diagrama de
contentores, documenta o pormenor de um cliente que interage com o
sistema de conferência.
NOTA
O contentor da aplicação de conferência na Figura I-2 está documentado simplesmente como
software. Normalmente, um contentor C4 forneceria mais detalhes sobre o tipo de contentor (por
exemplo, Java Spring Application). No entanto, neste livro, evitaremos especificidades
tecnológicas, a menos que isso ajude a demonstrar uma solução específica. A vantagem das API e,
na verdade, das aplicações modernas é que existe uma quantidade significativa de flexibilidade no
espaço da solução.
Diagrama de componentes C4
O diagrama de componentes C4 na Figura I-3 ajuda a definir os papéis e
responsabilidades dentro de cada contentor, juntamente com as interações
internas. Este diagrama é útil se o detalhe de um contentor for consultado, e
também fornece um mapa muito útil para a base de código. Pensa na
primeira vez que começaste a trabalhar num novo projeto: navegar numa
base de código auto-documentada é uma abordagem - mas pode ser difícil
juntar tudo. Um diagrama de componentes revela os detalhes da
linguagem/pilha que estás a utilizar para construir o teu software. Para
permanecermos agnósticos em relação à tecnologia, utilizámos o termo
pacote/módulo.
Utilizar registos de decisões de arquitetura
Como promotores, arquitectos e, na verdade, humanos, todos nós já
estivemos na posição de perguntar "em que é que eles estavam a
pensar?"Se alguma vez conduziste na M62 entre Leeds e Manchester, no
Reino Unido, podes ter ficado perplexo com a construção da autoestrada. À
medida que sobes a colina na autoestrada de três faixas, esta começa a
desviar-se do contra-fluxo do tráfego, até que finalmente surge a Quinta
Scott Hall rodeada por cerca de 15 acres de terrenos agrícolas aninhados
entre as carruagens. A lenda local sobre o que aconteceu descreveu o
proprietário do terreno como teimoso e recusando-se a mover-se ou a
entregar o seu terreno, pelo que os engenheiros simplesmente construíram à
sua volta.2 Cinquenta anos mais tarde, um documentário veio à tona
revelando que a verdadeira razão para isso era uma falha geológica por
baixo do terreno, o que significava que a autoestrada tinha de ser construída
daquela forma. Quando as pessoas adivinham porque é que algo foi feito de
uma determinada forma, espera que surjam rumores, humor e críticas.
Na arquitetura de software, haverá muitas restrições que teremos de
contornar, pelo que é importante garantir que as nossas decisões são
registadas e transparentes. Os ADRs ajudam a tornar claras as decisões de
arquitetura de software.
Uma das coisas mais difíceis de seguir durante a vida de um projeto é a
motivação por detrás de certas decisões. Uma nova pessoa que entra
num projeto pode ficar perplexa, perplexa, encantada ou enfurecida com
alguma decisão passada.
—Michael Nygard, criador do conceito de ADR
Existem quatro secções principais num ADR: estado, contexto, decisão e
consequências. Um ADR é criado com um estado proposto e, com base na
discussão, será normalmente aceite ou rejeitado. O contexto ajuda a definir
o cenário e a descrever o problema ou os limites em que a decisão será
tomada. Embora a criação de uma publicação no blogue antes da RAL e a
ligação a partir da RAL ajude a comunidade a seguir o seu trabalho, o
contexto não se destina a ser uma publicação no blogue ou uma descrição
detalhada. A decisão define claramente o que tencionas fazer e como
tencionas fazê-lo. Todas as decisões têm consequências ou soluções de
compromisso na arquitetura e, por vezes, podem ser incrivelmente
dispendiosas se forem mal tomadas.
Ao rever um ADR, é importante verificar se concorda com a decisão nele
contida ou se existe uma abordagem alternativa. Uma abordagem
alternativa que não tenha sido considerada pode fazer com que o ADR seja
rejeitado. Há muito valor num ADR rejeitado e a maioria das equipas opta
por manter os ADR imutáveis para captar a mudança de perspetiva. Os
ADR funcionam melhor quando são apresentados num local onde os
principais participantes os podem ver, comentar e ajudar a fazer com que o
ADR seja aceite.
DICA
Uma pergunta que nos fazem frequentemente é: em que momento deve a equipa criar um ADR? É
útil garantir que houve uma discussão antes do ADR e que o registo é o resultado do pensamento
coletivo da equipa. A publicação de um ADR para a comunidade em geral permite a oportunidade
de obter feedback para além da equipa imediata de.
Evolução dos participantes ADR
Na Figura I-4, tomámos a decisão de dar um passo evolutivo na arquitetura
do sistema de conferências. Trata-se de uma alteração importante que
justificaria um ADR.O Quadro I-1 apresenta um exemplo de ADR que
poderia ter sido proposto pela equipa de engenharia proprietária do sistema
de conferências.
Quadro I-1. ADR001 separação de participantes do sistema de conferência
antigo
Estado Proposta
Contexto Os proprietários da conferência solicitaram duas novas funcionalidades
importantes para o atual sistema de conferências que têm de ser
implementadas sem perturbar o sistema atual. O sistema de conferências terá
de ser desenvolvido para suportar uma aplicação móvel e uma integração com
um sistema externo de PCP. Tanto a aplicação móvel como o sistema externo
de PCP têm de poder aceder aos participantes para iniciarem sessão no serviço
de terceiros.
Decisão A evolução, tal como documentado na Figura I-4, consistirá em separar a
componente Attendee num serviço autónomo, o que permitirá o
desenvolvimento da API-First em relação ao serviço Attendee e a invocação
da API a partir do serviço de conferência antigo, bem como a possibilidade de
conceber um acesso direto ao serviço Attendee para fornecer informações
sobre os utilizadores ao sistema externo do PCP.
Consequências A chamada para o serviço Attendee não estará fora de processo e poderá
introduzir uma latência que terá de ser testada. O serviço Attendee poderá
tornar-se um ponto único de falha na arquitetura e poderemos ter de tomar
medidas para atenuar o potencial impacto da execução de um único serviço
Attendee. Com o modelo planeado de vários consumidores para o serviço
Attendee, teremos de garantir uma boa conceção, controlo de versões e testes
para reduzir as alterações acidentais de rutura.
Algumas das consequências do ADR são bastante importantes e requerem,
sem dúvida, uma discussão mais aprofundada, que adiaremos para capítulos
posteriores de .
Dominar a API: Diretrizes ADR
No âmbito do Mastering API Architecture, nós iremos fornecer Diretrizes
ADR para ajudar a recolher questões importantes a colocar quando se
tomam decisões sobre o tópico que estamos a cobrir. Tomar decisões sobre
uma arquitetura baseada em API pode ser realmente difícil, e em muitas
situações a resposta é "depende". Em vez de dizer que depende sem
contexto, as Diretrizes ADR irão ajudar a descrever do que depende e
ajudar a informar as suas decisões. As Diretrizes ADR podem ser usadas
como um ponto de referência para voltar ou para ler mais à frente se estiver
a enfrentar um desafio específico. O Quadro I-2 descreve o formato das
Diretrizes RAL e o que deves esperar delas.
Tabela I-2. Diretrizes ADR: Formato
Decisão Descreve uma decisão que poderás ter de tomar ao considerar um aspeto deste
livro.
Pontos de discussão Esta secção ajuda a identificar as principais discussões que deves ter ao tomar
uma decisão sobre a arquitetura da tua API.
Nesta secção, revelaremos algumas das nossas experiências que podem ter
influenciado a decisão. Ajudar-te-emos a identificar as informações essenciais
para o teu processo de tomada de decisão.
Recomendações Faremos recomendações específicas que deves ter em conta ao criar o teu
ADR, explicando a razão pela qual fazemos uma recomendação específica.
Resumo
Nesta introdução, fornecemos uma base com o estudo de caso e a
abordagem que iremos adotar para discutir as arquitecturas orientadas por
API:
A arquitetura é uma viagem sem fim e as API podem desempenhar um
papel importante na sua evolução.
As APIs são uma abstração da implementação e podem estar em
processoou fora de processo. Muitas vezes, os arquitetos encontram-se
na posição de evoluir para APIs fora de processo, o foco deste livro.
Nesta introdução, viste um pequeno passo evolutivo para desenvolver
o serviço Attendee de modo a responder aos requisitos comerciais
futuros.
Já viste os três primeiros níveis dos diagramas C4 e a sua importância
na partilha e comunicação da arquitetura.
Os ADR constituem um registo valioso para a tomada de decisões e
têm valor atual e histórico durante a vida de um projeto.
Já viste a estrutura das orientações para os ADR que serão utilizadas
ao longo do livro para facilitar a tomada de decisões.
Com a decisão tomada de separar o serviço Attendee do sistema de
conferências, vamos agora explorar as opções para conceber e especificar a
API Attendee.
1 A intenção é que seja a IU a aceder ao ponto de entrada. No entanto, está aberto a uma
potencial exploração.
2 Os traços de teimosia locais alimentaram esta explicação provável.
Parte I. Projetando, criando e
testando APIs
Esta secção fornece os blocos de construção fundamentais para
arquitecturas orientadas por API.
No Capítulo 1, aprenderás sobre as APIs baseadas em REST e Remote
Procedure Call (RPC). Exploraremos especificações e esquemas, padrões
recomendados, estratégias de controle de versão e como escolher a API
certa para o teu sistema.
No Capítulo 2, aprenderás sobre como testar APIs e como diferentes estilos
de teste são melhor aplicados a arquiteturas orientadas por API.
Capítulo 1. Projeta, constrói e
especifica APIs
Este trabalho foi traduzido com recurso a IA. Agradecemos o teu feedback e comentários:
translation-feedback@[Link]
É incrivelmente rápido criar um serviço com tecnologias e estruturas
modernas, mas a criação de uma abordagem duradoura exige reflexão e
consideração cuidadosas. Neste capítulo, exploraremos REST e RPC para
modelar as relações entre produtor e consumidor no estudo de caso.
Descobrirás como as normas podem ajudar a encurtar as decisões de
conceção e a evitar potenciais problemas de compatibilidade. Analisarás as
especificações OpenAPI, as utilizações práticas para as equipas e a
importância do controlo de versões.
As interações baseadas em RPC são especificadas através de um esquema;
para comparar e contrastar com uma abordagem REST, vamos explorar o
gRPC. Tendo em mente tanto o REST como o gRPC, vamos analisar os
diferentes factores a considerar na forma como modelamos as trocas.
Vamos analisar a possibilidade de fornecer uma API REST e RPC no
mesmo serviço e se isso é a coisa certa a fazer.
Estudo de caso: Projetando a API do
participante
Em a Introdução, decidimos migrar o nosso sistema de conferências antigo
e avançar para uma arquitetura mais orientada para as API. Como primeiro
passo para efetuar esta mudança, vamos criar um novo serviço de
participante, que irá expor uma API de participante correspondente.
Também fornecemos uma definição restrita de uma API. Para conceber
eficazmente, temos de considerar mais amplamente a troca entre o produtor
e o consumidor e, mais importante ainda, quem são o produtor e o
consumidor. O produtor é propriedade da equipa de participantes. Esta
equipa mantém duas relações fundamentais:
A equipa do participante é responsável pelo produtor e a equipa da
conferência tradicional é responsável pelo consumidor. Existe uma
relação estreita entre estas duas equipas e quaisquer alterações na
estrutura são facilmente coordenadas. É possível obter uma forte
coesão entre os serviços de produtor/consumidor.
Existe uma relação entre as equipas, mas quaisquer alterações têm de
ser coordenadas para não quebrar a integração. É necessário um
acoplamento flexível e as alterações de rutura têm de ser
cuidadosamente geridas.
Ao longo deste capítulo , comparamos e contrastamos as abordagens para
projetar e criar a API Attendee.
Introdução ao REST
REpresentation State Transfer (REST) é um conjunto de restrições
arquitectónicas, mais frequentemente aplicadas utilizando o HTTP como
protocolo de transporte subjacente. A dissertação de Roy Fielding
"Architectural Styles and the Design of Network-based Software
Architectures" fornece uma definição completa de REST. De uma
perspetiva prática, para ser considerada RESTful, a sua API deve garantir
que
É modelada uma interação produtor-consumidor em que o produtor
modela os recursos com que o consumidor pode interagir.
Os pedidos do produtor para o consumidor não têm estado, o que
significa que o produtor não armazena em cache os detalhes de um
pedido anterior. Para construir uma cadeia de pedidos num
determinado recurso, o consumidor deve enviar qualquer informação
necessária ao produtor para processamento.
Os pedidos podem ser armazenados em cache, o que significa que o
produtor pode fornecer sugestões ao consumidor quando tal for
apropriado. No HTTP, isto é frequentemente fornecido através de
informações contidas no cabeçalho.
Transmite uma interface uniforme ao consumidor. Em breve,
explorarás a utilização de verbos, recursos e outros padrões.
É um sistema em camadas, que abstrai a complexidade dos sistemas
que estão por trás da interface REST. Por exemplo, o consumidor não
deve saber ou importar-se se está a interagir com uma base de dados
ou outros serviços.
Introdução ao REST e HTTP por exemplo
Vejamos um exemplo de REST sobre HTTP. A troca seguinte é um pedido
GET, em que GET representa o método ou verbo. Um verbo como GET
descreve a ação a realizar num determinado recurso; neste exemplo,
consideramos o recurso participantes. É passado um cabeçalho Accept para
definir o tipo de conteúdo que o consumidor gostaria de recuperar. REST
define a noção de uma representação no corpo e permite que os metadados
de representação sejam definidos nos cabeçalhos.
Nos exemplos deste capítulo, representamos um pedido acima do separador
--- e uma resposta abaixo:
GET [Link]
Accept: application/json
---
200 OK
Content-Type: application/json
{
"displayName": "Jim",
"id": 1
}
A resposta inclui o código de estado e a mensagem do servidor, o que
permite ao consumidor interrogar o resultado da operação no recurso do
lado do servidor. O código de estado deste pedido foi 200 OK, o que
significa que o pedido foi processado com êxito pelo produtor. No corpo da
resposta é devolvida uma representação JSON que contém os participantes
da conferência. Muitos tipos de conteúdo são válidos para retorno de um
REST, no entanto, é importante considerar se o tipo de conteúdo é
analisável pelo consumidor. Por exemplo, retornar application/pdf é
válido, mas não representaria uma troca que poderia ser facilmente usada
por outro sistema. Exploraremos abordagens para modelar tipos de
conteúdo, principalmente olhando para JSON, mais adiante neste capítulo.
NOTA
O REST é relativamente simples de implementar porque a relação entre o cliente e o servidor não
tem estado, o que significa que o estado do cliente não é conservado pelo servidor. O cliente tem
de transmitir o contexto ao servidor nos pedidos subsequentes; por exemplo, um pedido
para[Link] iria obter mais informações sobre um participante
específico de.
O Modelo de Maturidade de Richardson
Falando em no QCon em 2008, Leonard Richardson apresentou suas
experiências de revisão de muitas APIs REST. Richardson encontrou níveis
de adoção que as equipes aplicam à construção de APIs a partir de uma
perspetiva REST. Martin Fowler também abordou as heurísticas de
maturidade de Richardson em seu blog. A Tabela 1-1 explora os diferentes
níveis representados pelas heurísticas de maturidade de Richardson e sua
aplicação às APIs RESTful.
Quadro 1-1. Heurística de maturidade de Richardson
Nível 0 - Estabelece que a API é construída utilizando HTTP e tem a noção de um
HTTP/RPC único URI. Tomando o nosso exemplo anterior de /attendees e não
aplicando um verbo para especificar a intenção, abriríamos um ponto final
para troca. Essencialmente, isto representa uma implementação RPC sobre o
protocolo REST.
Nível 1 - Recursos Estabelece a utilização de recursos e começa a introduzir a ideia de modelação
de recursos no contexto do URI. No nosso exemplo, se adicionássemos GET
/attendees/1, devolvendo um participante específico, começaria a
parecer uma API de nível 1. Martin Fowler faz uma analogia com o mundo
clássico orientado para objectos ao introduzir a identidade.
Nível 2 - Verbos Começa a introduzir a modelação correta de vários URIs de recursos acedidos
(Métodos) por diferentes métodos de pedido (também conhecidos como verbos HTTP)
com base no efeito dos recursos no servidor. Uma API de nível 2 pode dar
garantias de que os métodos GET não afectam o estado do servidor e
apresentam várias operações no mesmo URI de recurso. No nosso exemplo,
adicionar DELETE /attendees/1, PUT /attendees/1 começaria a
acrescentar a noção de uma API compatível com o nível 2.
Nível 3 - Controlos Este é o epítome da conceção REST e envolve APIs navegáveis através da
de hipermédia utilização de HATEOAS (Hypertext As The Engine Of Application State). No
nosso exemplo, quando chamamos GET /attendees/1, a resposta
conteria as acções possíveis no objeto devolvido pelo servidor, o que incluiria
a opção de atualizar ou eliminar o participante e o que o cliente tem de
invocar para o fazer. Em termos práticos, o nível 3 raramente é utilizado em
serviços HTTP RESTful modernos e, embora a navegação seja uma vantagem
em sistemas de estilo UI flexíveis, não se adequa a chamadas de API
interserviços. A utilização do HATEOAS seria uma experiência de
conversação e é muitas vezes encurtada por uma especificação completa das
interações possíveis logo à partida, durante a programação do produtor.
Ao conceber intercâmbios de API, é importante ter em conta os diferentes
níveis de maturidade de Richardson. Se avançar para o nível 2, poderá
projetar um modelo de recursos compreensível para o consumidor, com
acções apropriadas disponíveis em relação ao modelo. Por sua vez, isto
reduz o acoplamento e oculta todos os detalhes do serviço de apoio. Mais
tarde, veremos também como essa abstração é aplicada ao controle de
versão.
Se o consumidor for a equipa do PCP, a modelação de uma troca com baixo
acoplamento e a projeção de um modelo RESTful seria um bom ponto de
partida. Se o consumidor for a equipa da conferência antiga, podemos ainda
optar por utilizar uma API RESTful, mas existe também outra opção com o
RPC. Para começar a considerar este tipo de modelação tradicionalmente
este-oeste, vamos explorar o RPC.
Introdução às APIs de chamada de
procedimento remoto (RPC)
Enquanto o REST pode projetar um modelo do domínio e fornece uma
abstração da tecnologia subjacente ao consumidor, o RPC envolve a
exposição de um método de um processo e permite que este seja chamado
diretamente de outro.
O gRPC é um RPC moderno de alto desempenho de código aberto. O gRPC
está sob a administração da Linux Foundation e é o padrão de fato para
RPC na maioria das plataformas.A Figura 1-1 descreve uma chamada RPC
no gRPC, que envolve o serviço de conferência legado invocando o método
remoto no serviço Attendee. O serviço Attendee do gRPC inicia e expõe um
servidor gRPC em uma porta especificada, permitindo que os métodos
sejam invocados remotamente. No lado do cliente (o serviço de conferência
legado), um stub é usado para abstrair a complexidade de fazer a chamada
remota para a biblioteca. O gRPC requer um esquema para cobrir
totalmente a interação entre produtor e consumidor.
Figura 1-1. Exemplo de diagrama de componentes C4 utilizando gRPC
Uma diferença fundamental entre REST e RPC é o estado. O REST é, por
definição, sem estado - com o RPC, o estado depende da implementação.
As integrações baseadas no RPC, em determinadas situações, também
podem criar estado como parte da troca. Esta criação de estado tem a
conveniência de um elevado desempenho, mas com o custo potencial da
fiabilidade e das complexidades de encaminhamento. Com o RPC, o
modelo tende a transmitir a funcionalidade exacta a nível de método que é
exigida a um serviço secundário. Esta opcionalidade no estado pode levar a
uma troca potencialmente mais acoplada entre o produtor e o consumidor.
O acoplamento nem sempre é mau, especialmente em serviços Este-Oeste
em que o desempenho é uma consideração fundamental.
Uma breve menção ao GraphQL
Antes de explorar os estilos REST e RPC em detalhes, seria negligente não
mencionar o GraphQL e onde ele se encaixa no mundo das APIs. O RPC
oferece acesso a uma série de funções individuais fornecidas por um
produtor, mas normalmente não estende um modelo ou abstração para o
consumidor. O REST, por outro lado, estende um modelo de recursos para
uma única API fornecida pelo produtor. É possível oferecer várias APIs no
mesmo URL de base usando gateways de API. Se oferecermos várias APIs
dessa forma, o consumidor precisará consultar sequencialmente para
construir o estado no lado do cliente. O consumidor também precisa
entender a estrutura de todos os serviços envolvidos na consulta. Essa
abordagem é um desperdício se o consumidor estiver interessado apenas em
um subconjunto de campos na resposta. Os dispositivos móveis são
limitados por telas menores e disponibilidade de rede, portanto, o GraphQL
é excelente nesse cenário.
O GraphQL introduz uma camada de tecnologia sobre os serviços,
armazenamentos de dados e APIs existentes que fornece uma linguagem de
consulta para consultar várias fontes. A linguagem de consulta permite que
o cliente solicite exatamente os campos necessários, incluindo campos que
abrangem várias APIs. O GraphQL utiliza a linguagem de esquema
GraphQL para especificar os tipos em APIs individuais e como as APIs se
combinam. Uma grande vantagem da introdução de um esquema GraphQL
no seu sistema é a capacidade de fornecer uma única versão em todas as
APIs, eliminando a necessidade de uma gestão de versões potencialmente
complexa do lado do consumidor.
O GraphQL é excelente quando um consumidor precisa de acesso uniforme
à API em uma ampla gama de serviços interconectados. O esquema fornece
a conexão e estende o modelo de domínio, permitindo que o cliente
especifique exatamente o que é necessário no lado do consumidor. Isso
funciona extremamente bem para modelar uma interface de usuário e
também sistemas de relatórios ou sistemas do tipo armazenamento de
dados. Em sistemas em que grandes quantidades de dados são armazenadas
em diferentes subsistemas, o GraphQL pode fornecer uma solução ideal
para abstração da complexidade interna do sistema.
É possível colocar o GraphQL sobre sistemas legados existentes e usá-lo
como uma fachada para ocultar a complexidade, embora fornecer o
GraphQL sobre uma camada de APIs bem projetadas geralmente significa
que a fachada é mais simples de implementar e manter. O GraphQL pode
ser considerado como uma tecnologia complementar e deve ser considerado
ao projetar e construir APIs. O GraphQL também pode ser considerado
como uma abordagem completa para construir todo um ecossistema de API.
O GraphQL brilha em determinados cenários e encorajamos-te a dar uma
vista de olhos em Learning GraphQL (O'Reilly) e GraphQL in Action
(O'Reilly) para um mergulho mais profundo neste tópico.
Estrutura e padrões da API REST
O REST tem algumas regras muito básicas, mas a maior parte da
implementação e do design é deixada como um exercício para o
programador. Por exemplo, qual é a melhor forma de transmitir erros?
Como deve ser implementada a paginação? Como evita acidentalmente a
criação de uma API em que a compatibilidade é frequentemente quebrada?
Nesta altura, é útil ter uma definição mais prática em torno das APIs para
fornecer uniformidade e expectativas entre diferentes implementações. É
aqui que as normas ou diretrizes podem ajudar, no entanto, há uma
variedade de fontes por onde escolher.
Para efeitos de discussão do design, utilizaremos as Diretrizes da API
REST da Microsoft, que representam uma série de diretrizes internas que
foram abertas. As diretrizes utilizam o RFC-2119, que define a terminologia
para normas como MUST, SHOULD, SHOULD NOT, MUST NOT, etc.,
permitindo ao programador determinar se os requisitos são opcionais ou
obrigatórios.
DICA
Como os padrões da API REST estão a evoluir, uma lista aberta de padrões de API está disponível
na página do livro no Github. Por favor, contribui através de um pull request com quaisquer
padrões abertos que consideres úteis para outros leitores.
Vamos considerar o design de a API Attendee utilizando as Diretrizes da
API REST da Microsoft e introduzir um ponto final para criar um novo
attendee. Se estiveres familiarizado com o REST, pensarás
imediatamente em utilizar POST:
POST [Link]
{
"displayName": "Jim",
"givenName": "James",
"surname": "Gough",
"email": "jim@[Link]"
}
---
201 CREATED
Location: [Link]
O cabeçalho Location revela a localização do novo recurso criado no
servidor e, nesta API, estamos a modelar uma ID exclusiva para o
utilizador. É possível utilizar o campo de correio eletrónico como uma ID
exclusiva, mas as Diretrizes da API REST da Microsoft recomendam, na
secção 7.9, que as informações de identificação pessoal (PII) não devem
fazer parte do URL.
AVISO
A razão para remover dados sensíveis do URL é que os caminhos ou parâmetros de consulta
podem ser inadvertidamente armazenados em cache na rede - por exemplo, nos registos do
servidor ou noutro local.
Outro aspeto das APIs que pode ser difícil é a nomenclatura. Como
discutiremos em "Versionamento de API", algo tão simples como mudar um
nome pode quebrar a compatibilidade. Há uma pequena lista de nomes
padrão que devem ser usados nas Diretrizes da API REST da Microsoft,
mas as equipes devem expandir isso para ter um dicionário de dados de
domínio comum para complementar os padrões. Em muitas organizações, é
incrivelmente útil investigar proactivamente os requisitos em torno da
conceção de dados e, em alguns casos, da governação. As organizações que
fornecem consistência em todas as APIs oferecidas por uma empresa
apresentam uma uniformidade que permite aos consumidores compreender
e ligar respostas. Em alguns domínios, pode já existir uma terminologia
amplamente conhecida - utiliza-a !
Colecções e paginação
Parece razoável modelar o pedido GET /attendees como uma resposta
que contém uma matriz bruta. O seguinte trecho de código-fonte mostra um
exemplo do que isso pode parecer como um corpo de resposta:
GET [Link]
---
200 OK
[
{
"displayName": "Jim",
"givenName": "James",
"surname": "Gough",
"email": "jim@[Link]",
"id": 1,
},
...
]
Vamos considerar um modelo alternativo para o pedido GET
/attendees que aninhou a matriz de participantes num objeto. Pode
parecer estranho que uma resposta de matriz seja devolvida num objeto,
mas a razão para isso é que nos permite modelar colecções maiores e
paginação. A paginação envolve devolver um resultado parcial, ao mesmo
tempo que fornece instruções sobre como o consumidor pode pedir o
próximo conjunto de resultados. Isto é colher os benefícios da retrospetiva;
adicionar paginação mais tarde e converter de uma matriz para um objeto a
fim de adicionar um @nextLink (como recomendado pelas normas)
quebraria a compatibilidade:
GET [Link]
---
200 OK
{
"value": [
{
"displayName": "Jim",
"givenName": "James",
"surname": "Gough",
"email": "jim@[Link]",
"id": 1,
}
],
"@nextLink": "{opaqueUrl}"
}
Filtrar colecções
A nossa conferência parece um pouco solitária com apenas um participante,
no entanto, quando as colecções aumentam de tamanho, podemos precisar
de adicionar filtragem para além da paginação. A norma de filtragem
fornece uma linguagem de expressão no âmbito do REST para normalizar a
forma como as consultas de filtragem se devem comportar, com base na
norma OData. Por exemplo, podemos encontrar todos os participantes com
o displayName Jim utilizando:
GET [Link] eq
'Jim'
Não é necessário completar todos os recursos de filtragem e pesquisa desde
o início. No entanto, projetar uma API de acordo com os padrões permitirá
que o desenvolvedor suporte uma arquitetura de API em evolução sem
quebrar a compatibilidade para os consumidores. Filtragem e consulta é um
recurso em que o GraphQL é realmente bom, especialmente se a consulta e
a filtragem em muitos dos seus serviços se tornarem relevantes.
Tratamento de erros
Uma consideração importante quando se estende as API aos consumidores
é definir o que deve acontecer em vários cenários de erro. É útil definir
antecipadamenteas normas de erro e partilhá-las com os produtores para
garantir a consistência. É importante que os erros descrevam ao consumidor
exatamente o que correu mal com o pedido, uma vez que isso evitará
aumentar o suporte necessário para a API.
As diretrizes afirmam: "Para condições de não sucesso, os programadores
DEVERÃO ser capazes de escrever um pedaço de código que trate os erros
de forma consistente."Deve ser fornecido um código de estado exato ao
consumidor, porque muitas vezes os consumidores constroem a lógica em
torno do código de estado fornecido na resposta. Vimos muitas API que
devolvem erros no corpo juntamente com um tipo de resposta 2xx, que é
utilizado para indicar sucesso. Os códigos de estado 3xx para
redireccionamentos são ativamente seguidos por algumas implementações
de bibliotecas de consumo, permitindo que os fornecedores se desloquem e
acedam a fontes externas. 4xx geralmente indica um erro do lado do cliente;
nesse ponto, o conteúdo do campo message é extremamente útil para o
desenvolvedor ou usuário final. 5xx geralmente indica uma falha no lado do
servidor e algumas bibliotecas clientes tentarão novamente nesses tipos de
falhas. É importante considerar e documentar o que acontece no serviço
com base em uma falha inesperada - por exemplo, em um sistema de
pagamento, um 500 significa que o pagamento foi realizado ou não?
AVISO
Assegura-te de que as mensagens de erro enviadas de volta a um consumidor externo não contêm
traços de pilha e outras informações sensíveis. Estas informações podem ajudar um pirata
informático que pretenda comprometer o sistema. A estrutura de erro nas diretrizes da Microsoft
tem o conceito de um InnerError, que pode ser útil para colocar traços de pilha/descrições mais
detalhadas de problemas. Isto seria incrivelmente útil para a depuração, mas deve ser retirado
antes de um consumidor externo.
Se combinarmos o desejo de apresentar APIs intuitivas que sejam
consistentes e permitir uma API compatível e em evolução, vale a pena
adotar um padrão de API desde o início.
Diretrizes ADR: Escolher uma norma API
Para tornar a sua decisão sobre as normas da API, a diretriz na Tabela 1-2
enumera tópicos importantes a considerar. Há uma série de diretrizes para
escolher, incluindo as diretrizes da Microsoft discutidas nesta secção, e
encontrar uma que melhor corresponda aos estilos das APIs que estão a ser
produzidas é uma decisão fundamental.
Tabela 1-2. Diretrizes das normas API
Decisão Que norma API devemos adotar?
Pontos de discussão A organização já tem outras normas dentro da empresa? Podemos alargar
essas normas aos consumidores externos?
Estamos a utilizar alguma API de terceiros que tenhamos de expor a um
consumidor (por exemplo, Serviços de Identidade) que já tenha uma norma?
Qual é o impacto da inexistência de uma norma para os nossos consumidores?
Recomendações Escolhe um padrão de API que melhor se adeqúe à cultura da organização e
aos formatos de APIs que já possas ter no inventário.
Prepara-te para evoluir e acrescentar a uma norma quaisquer alterações
específicas de um domínio ou sector.
Começa com algo cedo para evitar ter de quebrar a compatibilidade mais tarde
para obter consistência.
Sê crítico em relação às APIs existentes. Estão num formato que os
consumidores entenderiam ou é necessário mais esforço para oferecer o
conteúdo?
Especificando APIs REST usando OpenAPI
Como estamos a começar a ver, o design de uma API é fundamental para o
sucesso de uma plataforma de API. A próxima consideração que iremos
discutir é a partilha da API com os programadores que consomem as nossas
APIs.
Os mercados de API fornecem uma lista pública ou privada de APIs
disponíveis para um consumidor. Um programador pode navegar pela
documentação e experimentar rapidamente uma API no browser para
explorar o comportamento e a funcionalidade da API. Os mercados de API
públicos e privados colocaram as APIs REST de forma proeminente no
espaço do consumidor. O sucesso das APIs REST tem sido impulsionado
tanto pelo panorama técnico como pela baixa barreira à entrada, tanto para
o cliente como para o servidor.
À medida que o número de APIs cresceu, rapidamente se tornou necessário
ter um mecanismo para partilhar a forma e a estrutura das APIs com os
consumidores. É por isso que a Iniciativa OpenAPI foi formada por líderes
do sector das APIs para construir a Especificação OpenAPI (OAS). O
Swagger foi a implementação de referência original das Especificações
OpenAPI, mas a maioria das ferramentas convergiu agora para a utilização
da OpenAPI.
As especificações da OpenAPI são representações da API baseadas em
JSON ou YAML que descrevem a estrutura, os objectos de domínio
trocados e quaisquer requisitos de segurança da API. Para além da estrutura,
também transmitem metadados sobre a API, incluindo quaisquer requisitos
legais ou de licenciamento, e também contêm documentação e exemplos
que são úteis para os programadores que consomem a API. As
especificações OpenAPI são um conceito importante em torno das
modernas APIs REST, e muitas ferramentas e produtos foram criados em
torno da sua utilização .
Aplicação prática das especificações
OpenAPI
Uma vez que um OAS é partilhado, o poder da especificação começa a
tornar-se aparente.O [Link] documenta uma gama completa de
ferramentas de código aberto e fechado disponíveis. Nesta secção, vamos
explorar algumas das aplicações práticas das ferramentas com base na sua
interação com a especificação OpenAPI.
Na situação em que a equipa do PCP é o consumidor, a partilha do OAS
permite à equipa compreender a estrutura da API. A utilização de algumas
das seguintes aplicações práticas pode ajudar a melhorar a experiência do
programador e a garantir a saúde da bolsa.
Geração de código
Talvez um dos recursos mais úteis de um OAS seja permitir a geração de
código do lado do cliente para consumir a API. Como discutido
anteriormente, podemos incluir todos os detalhes do servidor, segurança e,
claro, a própria estrutura da API. Com todas essas informações, podemos
gerar uma série de objetos de modelo e serviço que representam e invocam
a API. O projeto OpenAPI Generator suporta uma grande variedade de
linguagens e cadeias de ferramentas. Por exemplo, em Java podes escolher
usar Spring ou JAX-RS e em TypeScript podes escolher uma combinação
de TypeScript com a tua framework favorita. Também é possível gerar os
stubs de implementação da API a partir do OAS.
Isto levanta uma questão importante sobre o que deve vir primeiro - a
especificação ou o código do lado do servidor? No Capítulo 2, discutimos o
"rastreio de contratos", que apresenta uma abordagem orientada para o
comportamento para testar e construir APIs. O desafio com as
especificações OpenAPI é que, sozinhas, apenas transmitem a forma da
API. As especificações OpenAPI não modelam totalmente a semântica (ou
o comportamento esperado) da API sob diferentes condições. Se vai
apresentar uma API a utilizadores externos, é importante que a gama de
comportamentos seja modelada e testada para ajudar a evitar ter de alterar
drasticamente a API mais tarde.
As API devem ser concebidas na perspetiva do consumidor e ter em conta a
necessidade de abstração da representação subjacente para reduzir o
acoplamento. É importante poder refactorizar livremente os componentes
nos bastidores sem quebrar a compatibilidade da API, caso contrário a
abstração da API perde valor.
Validação da OpenAPI
Especificações da OpenAPI são úteis para validar o conteúdo de uma troca
para garantir que a solicitação e a resposta correspondam às expectativas da
especificação. A princípio, pode não parecer aparente onde isso seria útil -
se o código for gerado, certamente a troca estará sempre correta. Uma
aplicação prática da validação da OpenAPI é a segurança das APIs e da
infraestrutura da API. Em muitas organizações, uma arquitetura zonal é
comum, com a noção de uma zona desmilitarizada (DMZ) usada para
proteger uma rede do tráfego de entrada. Um recurso útil é interrogar
mensagens na DMZ e encerrar o tráfego se a especificação não
corresponder. Cobriremos a segurança com mais detalhes no Capítulo 6.
A Atlassian, por exemplo, abriu uma ferramenta chamada swagger-request-
validator, que é capaz de validar o conteúdo JSON REST. O projeto
também tem adaptadores que se integram a várias estruturas de teste e
simulação para ajudar a garantir que as especificações da API estejam em
conformidade como parte do teste. A ferramenta tem um
OpenApiInteractionValidator, que é usado para criar um
ValidationReport em uma troca. O código a seguir demonstra a
construção de um validador a partir da especificação, incluindo qualquer
basePathOverrides- que pode ser necessário se implantar uma API
por trás de uma infraestrutura que altera o caminho. O relatório de
validação é gerado a partir da análise da solicitação e da resposta no ponto
em que a validação é executada:
//Using the location of the specification create an interaction
validator
//The base path override is useful if the validator will be used
//behind a gateway/proxy
final OpenApiInteractionValidator validator =
OpenApiInteractionValidator
.createForSpecificationUrl(specUrl)
.withBasePathOverride(basePathOverride)
.build;
//Requests and Response objects can be converted or created using
a builder
final ValidationReport report = [Link](request,
response);
if ([Link]()) {
// Capture or process error information
}
Exemplos e zombaria
O OAS pode fornecer exemplos de respostas para os caminhos na
especificação. Os exemplos, como já discutimos, são úteis para a
documentação para ajudar os desenvolvedores a entender o comportamento
esperado da API. Alguns produtos começaram a usar exemplos para
permitir que o usuário consulte a API e retorne exemplos de respostas de
um serviço simulado. Isto pode ser muito útil em funcionalidades como um
portal de programador, que permite aos programadores explorar a
documentação e invocar APIs. Outra caraterística útil dos simulacros e
exemplos é a capacidade de partilhar ideias entre o produtor e o consumidor
antes de se comprometerem a construir o serviço. Poder "experimentar" a
API é muitas vezes mais valioso do que tentar rever se uma especificação
satisfaz os seus requisitos.
Os exemplos podem potencialmente introduzir um problema interessante,
que é o facto de esta parte da especificação ser essencialmente uma cadeia
de caracteres (para modelar XML/JSON, etc.).openapi-examples-validator
valida que um exemplo corresponde ao OAS para o pedido/resposta
correspondente component da API .
Detetar alterações
OpenAPI As especificações também podem ser úteis para detetar alterações
em uma API. Isso pode ser incrivelmente útil como parte de um pipeline de
DevOps. Detetar alterações para compatibilidade com versões anteriores é
muito importante, mas primeiro precisamos entender o versionamento de
APIs com mais detalhes.
Controle de versão da API
Já explorámos as vantagens de partilhar um OAS com um consumidor,
incluindo a velocidade de integração. Considera o caso em que vários
consumidores começam a operar com a API. O que acontece quando há
uma alteração à API ou um dos consumidores solicita a adição de novas
funcionalidades à API?
Se as alterações à biblioteca fossem feitas numa nova versão e até o código
ser recompilado e testado com a nova versão, não haveria impacto nas
aplicações de produção. Como as APIs são serviços em execução, temos
algumas opções de atualização que estão imediatamente disponíveis quando
são pedidas alterações:
Lança uma nova versão e implanta em um novo local.
As aplicações mais antigas continuam a funcionar com a versão mais
antiga das APIs, o que é bom do ponto de vista do consumidor, uma vez
que este só actualiza para a nova localização e API se necessitar das
novas funcionalidades. No entanto, o proprietário da API tem de manter
e gerir várias versões da API, incluindo a aplicação de correcções e a
correção de erros que possam ser necessárias.
Lança uma nova versão da API que seja compatível com a versão anterior
da API.
Não são necessárias alterações por parte do consumidor, mas poderá ser
necessário ter em conta o tempo de inatividade ou a disponibilidade das
versões antiga e nova durante a atualização. Se houver uma pequena
correção de erro que altere algo tão pequeno como um nome de campo
incorreto, isso quebraria a compatibilidade.
Quebra a compatibilidade com a API anterior e todos os consumidores
devem atualizar o código para utilizar a nova API.
A princípio, parece uma péssima ideia, pois isso resultaria em quebras
inesperadas na produção.1 No entanto, pode surgir uma situação em que
não podemos evitar a quebra de compatibilidade com versões mais
antigas. Este tipo de alteração pode despoletar uma mudança de todo o
sistema que requer coordenação do tempo de inatividade.
O desafio é que todas estas diferentes opções de atualização oferecem
vantagens, mas também desvantagens, quer para o consumidor, quer para o
produtor. A realidade é que queremos ser capazes de suportar uma
combinação das três opções. Para o fazer, precisamos de introduzir regras
em torno do controlo de versões e da forma como as versões são expostas
ao consumidor .
Versionamento semântico
O versionamentosemântico oferece a uma abordagem que podemos aplicar
às APIs REST para nos dar uma combinação das opções de atualização
anteriores. O versionamento semântico define uma representação numérica
atribuída a uma versão da API. Esse número baseia-se na alteração do
comportamento em comparação com a versão anterior, utilizando as
seguintes regras:
Uma versão principal introduz alterações não compatíveis com
versões anteriores da API. Numa plataforma de API, a atualização para
uma nova versão principal é uma decisão ativa do consumidor. É
provável que exista um guia de migração e um acompanhamento à
medida que os consumidores actualizam para a nova API.
Uma versão secundária introduz uma alteração compatível com a
versão anterior da API. Numa plataforma de serviços API, é aceitável
que os consumidores recebam versões secundárias sem efectuarem
uma alteração ativa no lado do cliente.
Uma versão de correção não altera nem introduz novas
funcionalidades, mas é utilizada para corrigir erros numa versão de
funcionalidade existente [Link].
A formatação para o controlo de versões semântico pode ser representada
como [Link]. Por exemplo, 1.5.1 representaria a versão
principal 1, a versão secundária 5, com uma atualização de correção de 1.
No Capítulo 5, explorarás a forma como o controlo de versões semântico se
relaciona com o conceito de ciclo de vida e lançamentos de API.
Especificação e versão da OpenAPI
Agora que explorámos o controlo de versões, podemos ver exemplos de
alterações de rutura e de não rutura utilizando a especificação da API
Attendee. Existem várias ferramentas à escolha para comparar
especificações e, neste exemplo, iremos utilizar o openapi-diff do
OpenAPITools.
Começaremos com uma alteração de rutura: mudaremos o nome do campo
givenName parafirstName. Esta é uma alteração de rutura porque os
consumidores estarão à espera de analisar givenName, e não
firstName. Podemos executar a ferramenta de comparação a partir de
um contentor Docker utilizando o seguinte comando:
$docker run --rm -t \
-v $(pwd):/specs:ro \
openapitools/openapi-diff:latest /specs/[Link]
/specs/[Link]
=================================================================
=========
...
- GET /attendees
Return Type:
- Changed 200 OK
Media types:
- Changed */*
Schema: Broken compatibility
Missing property: [n].givenName (string)
-----------------------------------------------------------------
---------
-- Result
--
-----------------------------------------------------------------
---------
API changes broke backward compatibility
-----------------------------------------------------------------
---------
Podemos tentar adicionar um novo atributo ao tipo de retorno
/attendees para adicionar um campo adicional chamado age. A adição
de novos campos não quebra o comportamento existente e, portanto, não
quebra a compatibilidade:
$ docker run --rm -t \
-v $(pwd):/specs:ro \
openapitools/openapi-diff:latest --info /specs/[Link]
/specs/[Link]
=================================================================
=========
...
- GET /attendees
Return Type:
- Changed 200 OK
Media types:
- Changed */*
Schema: Backward compatible
-----------------------------------------------------------------
---------
-- Result
--
-----------------------------------------------------------------
---------
API changes are backward compatible
-----------------------------------------------------------------
---------
Vale a pena experimentar isto para ver quais as alterações que seriam
compatíveis e quais não seriam. A introdução deste tipo de ferramentas
como parte do pipeline da API vai ajudar a evitar alterações não
compatíveis inesperadas para os consumidores. As especificações OpenAPI
são uma parte importante de um programa de API e, quando combinadas
com ferramentas, controlo de versões e ciclo de vida, são inestimáveis.
AVISO
As ferramentas são muitas vezes específicas da versão da OpenAPI, por isso é importante verificar
se a ferramenta suporta a especificação com que estás a trabalhar. No exemplo anterior, tentámos a
ferramenta diff com uma versão anterior de uma especificação e não foram detectadas alterações
de rutura .
Implementação de RPC com gRPC
Os serviços Este-Oeste como o Attendee tendem a ter um tráfego mais
elevado e podem ser implementados como microsserviços utilizados em
toda a arquitetura. O gRPC pode ser uma ferramenta mais adequada do que
o REST para serviços Este-Oeste, devido à menor transmissão de dados e à
velocidade dentro do ecossistema.
Vamos explorar a utilização de um Spring Boot Starter para criar
rapidamente um servidor gRPC. O seguinte ficheiro .proto modela o mesmo
objeto attendee que explorámos no nosso exemplo de Especificação
OpenAPI. Tal como acontece com as Especificações OpenAPI, a geração de
código a partir de um esquema é rápida e suportada em várias linguagens.
O ficheiro .proto dos participantes define um pedido vazio e devolve uma
resposta Attendee repetida. Nos protocolos utilizados para
representações binárias, é importante notar que a posição e a ordem dos
campos são críticas, uma vez que determinam a disposição da mensagem.
Adicionar um novo serviço ou um novo método é compatível com as
versões anteriores, tal como adicionar um campo a uma mensagem, mas é
necessário ter cuidado. Quaisquer novos campos que sejam adicionados não
devem ser campos obrigatórios, caso contrário a compatibilidade com as
versões anteriores seria quebrada.
Remover um campo ou renomear um campo quebrará a compatibilidade,
assim como alterar o tipo de dados de um campo. Alterar o número do
campo também é um problema, pois os números de campo são usados para
identificar os campos no fio. As restrições de codificação com gRPC
significam que a definição deve ser muito específica. REST e OpenAPI são
bastante tolerantes, pois a especificação é apenas um guia.2 Campos extras
e ordenação não importam na OpenAPI e, portanto, o controle de versão e a
compatibilidade são ainda mais importantes quando se trata de gRPC:
syntax = "proto3";
option java_multiple_files = true;
package [Link];
message AttendeesRequest {
}
message Attendee {
int32 id = 1;
string givenName = 2;
string surname = 3;
string email = 4;
message AttendeeResponse {
repeated Attendee attendees = 1;
}
service AttendeesService {
rpc getAttendees(AttendeesRequest) returns (AttendeeResponse);
}
O seguinte código Java demonstra uma estrutura simples para implementar
o comportamento nas classes de servidor gRPC geradas:
@GrpcService
public class AttendeesServiceImpl extends
[Link] {
@Override
public void getAttendees(AttendeesRequest request,
StreamObserver<AttendeeResponse> responseObserver) {
[Link] responseBuilder
= [Link]();
//populate response
[Link]([Link]());
[Link]();
}
}
Podes encontrar o serviço Java que modela este exemplo na página GitHub
deste livro. O gRPC não pode ser consultado diretamente a partir de um
browser sem bibliotecas adicionais, no entanto podes instalar a IU do gRPC
para usar o browser para [Link] também fornece uma ferramenta
de linha de comandos:
$ grpcurl -plaintext localhost:9090 \
[Link]/getAttend
ees
{
"attendees": [
{
"id": 1,
"givenName": "Jim",
"surname": "Gough",
"email": "gough@[Link]"
}
]
}
O gRPC dá-nos outra opção para consultar o nosso serviço e define uma
especificação para o consumidor gerar código. O gRPC tem uma
especificação mais rigorosa do que a OpenAPI e exige que os
métodos/internos sejam compreendidos pelo consumidor .
Modelagem de intercâmbios e escolha de um
formato de API
Na Introdução, discutimos o conceito de padrões de tráfego e a diferença
entre pedidos provenientes de fora do ecossistema e pedidos dentro do
ecossistema. Os padrões de tráfego são um fator importante para determinar
o formato apropriado de API para o problema em questão. Quando temos
controlo total sobre os serviços e as trocas dentro da nossa arquitetura de
microsserviços, podemos começar a fazer compromissos que não
poderíamos fazer com consumidores externos.
É importante reconhecer que as caraterísticas de desempenho de um serviço
este-oeste são provavelmente mais aplicáveis do que as de um serviço
norte-sul. Numa troca norte-sul, o tráfego proveniente de fora do ambiente
do produtor envolverá geralmente a troca através da Internet. A Internet
introduz um elevado grau de latência e uma arquitetura de API deve ter
sempre em conta os efeitos combinados de cada serviço. Numa arquitetura
baseada em microsserviços, é provável que um pedido norte-sul envolva
várias trocas este-oeste. A troca de tráfego este-oeste elevado tem de ser
eficiente para evitar abrandamentos em cascata que se propaguem até
aoconsumidor.
Serviços de elevado tráfego
No nosso exemplo, Attendees é um serviço central. Numa arquitetura de
microsserviços, os componentes irão acompanhar um attendeeId. As
APIs oferecidas aos consumidores irão potencialmente recuperar dados
armazenados no serviço Attendee e, em escala, será um componente de
elevado tráfego. Se a frequência de troca de dados entre os serviços for
elevada, o custo da transferência na rede, devido ao tamanho da carga útil e
às limitações de um protocolo em relação a outro, será mais acentuado à
medida que a utilização aumentar. O custo pode traduzir-se em custos
monetários de cada transferência ou no tempo total necessário para que a
mensagem chegue ao destino.
Grandes cargas úteis de intercâmbio
Grandes tamanhos de carga útil podem também tornar-se um desafio nas
trocas de API e são susceptíveis de diminuir o desempenho da transferência
através do fio. O JSON sobre REST é legível por humanos e será
frequentemente mais detalhado do que uma representação fixa ou binária,
alimentando um aumento nos tamanhos da carga útil.
DICA
Um equívoco comum é que a "legibilidade humana" é citada como a principal razão para usar
JSON em transferências de dados. O número de vezes que um programador terá de ler uma
mensagem versus a consideração de desempenho não é um caso forte com ferramentas de rastreio
modernas. Também é raro que grandes ficheiros JSON sejam lidos do início ao fim. Um melhor
registo e tratamento de erros pode mitigar o argumento da legibilidade humana.
Outro fator nas trocas de grandes cargas úteis é o tempo que os
componentes demoram a analisar o conteúdo da mensagem em objectos de
domínio ao nível da linguagem. O tempo de desempenho dos formatos de
dados de análise varia muito, dependendo da linguagem em que um serviço
é implementado. Muitas linguagens tradicionais do lado do servidor podem
ter dificuldades com o JSON em comparação com uma representação
binária, por exemplo. Vale a pena explorar o impacto da análise e incluir
essa consideração ao escolher um formato de troca .
Benefícios de desempenho do HTTP/2
Usando Os serviços baseados em HTTP/2 podem ajudar a melhorar o
desempenho dos intercâmbios, suportando a compressão binária e o
enquadramento. A camada de enquadramento binário é transparente para o
programador, mas nos bastidores divide e comprime a mensagem em
pedaços mais pequenos. A vantagem do enquadramento binário é que
permite uma multiplexagem completa do pedido e da resposta numa única
ligação. Considera o processamento de uma lista noutro serviço e a
necessidade de obter 20 participantes diferentes; se os obtivéssemos como
pedidos HTTP/1 individuais, seria necessário criar 20 novas ligações TCP.
A multiplexagem permite-nos efetuar 20 pedidos individuais através de
uma única ligação HTTP/2.
O gRPC utiliza HTTP/2 por defeito e reduz o tamanho da troca de dados
através da utilização de um protocolo binário. Se a largura de banda for uma
preocupação ou um custo, o gRPC será vantajoso, em especial à medida
que as cargas de conteúdo aumentam significativamente de tamanho. O
gRPC pode ser vantajoso em comparação com o REST se a largura de
banda da carga útil for uma preocupação cumulativa ou se o serviço trocar
grandes volumes de dados.
DICA
O HTTP/3 está a caminho e vai mudar tudo. O HTTP/3 utiliza o QUIC, um protocolo de
transporte baseado no UDP. Podes saber mais em HTTP/3 explicado.
Formatos vintage
Nem todos os serviços de uma arquitetura se baseiam num design moderno.
No Capítulo 8, veremos como isolar e desenvolver componentes antigos,
uma vez que os componentes mais antigos serão uma consideração ativa
para as arquitecturas em evolução. É importante que os envolvidos numa
arquitetura de API compreendam o impacto global no desempenho da
introdução de componentes antigos.
Orientações: Modelação de intercâmbios
Quando o consumidor do é a equipa do sistema de conferência antigo, a
troca é tipicamente uma relação Este-Oeste. Quando o consumidor é a
equipa do CFP, a troca é tipicamente uma relação Norte-Sul. A diferença
nos requisitos de acoplamento e de desempenho exigirá que as equipas
considerem a forma como a troca é modelada. Verá alguns aspectos a
considerar na diretriz apresentada na Tabela 1-3.
Tabela 1-3. Diretriz de intercâmbio de modelos
Decisão Que formato devemos utilizar para modelar a API do nosso serviço?
Pontos de discussão A troca é norte-sul ou leste-oeste? Controlamos o código do consumidor?
Existe um domínio comercial forte em vários serviços ou queremos permitir
que os consumidores construam as suas próprias consultas?
Que considerações sobre o controlo de versões precisamos de ter?
Qual é a frequência de implementação/alteração do modelo de dados
subjacente?
Trata-se de um serviço de elevado tráfego em que foram levantadas questões
de largura de banda ou de desempenho?
Recomendações Se a API for consumida por utilizadores externos, o REST constitui uma
barreira reduzida à entrada e proporciona um modelo de domínio sólido. Os
utilizadores externos também significam, normalmente, que é desejável um
serviço com um acoplamento flexível e baixa dependência.
Se a API estiver a interagir entre dois serviços sob controlo apertado do
produtor ou se o serviço for comprovadamente de elevado tráfego, considera o
gRPC.
Especificações múltiplas
Neste capítulo explorámos uma variedade de formatos de API a considerar
numa arquitetura de API, e talvez a pergunta final seja "Podemos fornecer
todos os formatos?"A resposta é sim, podemos suportar uma API que tenha
uma apresentação RESTful, um serviço gRPC e ligações a um esquema
GraphQL. No entanto, não vai ser fácil e pode não ser a coisa certa a fazer.
Nesta secção final, vamos explorar algumas das opções disponíveis para
uma API multiformato e os desafios que pode apresentar.
Existe a Especificação Dourada?
O ficheiro .proto para os participantes e a especificação OpenAPI não
parecem muito diferentes; contêm os mesmos campos e ambos têm tipos de
dados. É possível gerar um ficheiro .proto a partir de um OAS utilizando a
ferramenta openapi2proto? Executar openapi2proto --spec spec-
[Link] produzirá o ficheiro .proto com os campos ordenados
alfabeticamente por predefinição. Isto é bom até adicionarmos um novo
campo ao OAS que seja compatível com as versões anteriores e, de repente,
o ID de todos os campos muda, quebrando a compatibilidade com as
versões anteriores.
O seguinte exemplo de ficheiro .proto mostra que a adição de
a_new_field seria adicionada alfabeticamente ao início, alterando o
formato binário e quebrando os serviços existentes:
message Attendee {
string a_new_field = 1;
string email = 2;
string givenName = 3;
int32 id = 4;
string surname = 5;
}
NOTA
Existem outras ferramentas disponíveis para resolver o problema da conversão de especificações,
mas é importante notar que algumas ferramentas apenas suportam a versão 2 da especificação
OpenAPI. O tempo necessário para passar entre as versões 2 e 3 em algumas das ferramentas
criadas em torno da OpenAPI levou a que muitos produtos precisassem de suportar ambas as
versões da OAS.
Uma opção alternativa em é o grpc-gateway, que gera um proxy reverso
fornecendo uma fachada REST em frente ao serviço gRPC. O proxy
reverso é gerado em tempo de compilação contra o arquivo .proto e
produzirá um mapeamento de melhor esforço para REST, semelhante a
openapi2proto. Você também pode fornecer extensões dentro do
arquivo .proto para mapear os métodos RPC para uma boa representação no
OAS:
import "google/api/[Link]";
//...
service AttendeesService {
rpc getAttendees(AttendeesRequest) returns (AttendeeResponse) {
option([Link]) = {
get: "/attendees"
};
}
Usar o grpc-gateway dá-nos outra opção para apresentar um serviço REST
e gRPC. No entanto, o grpc-gateway envolve vários comandos e uma
configuração que só seria familiar para os programadores que trabalham
com a linguagem Go ou com o ambiente de compilação.
Desafios das especificações combinadas
É importante dar um passo atrás e considerar o que estamos a tentar fazer.
Ao converter da OpenAPI, estamos efetivamente a tentar converter a nossa
representação RESTful numa série de chamadas gRPC. Estamos a tentar
converter um modelo de domínio hipermédia alargado numa chamada de
função para função de nível inferior. Esta é uma potencial fusão da
diferença entre RPC e APIs e é provável que resulte em problemas de
compatibilidade.
Com a conversão de gRPC para OpenAPI temos um problema semelhante;
o objetivo é tentar pegar no gRPC e fazê-lo parecer uma API REST, o que
provavelmente vai criar uma série de problemas difíceis quando o serviço
evoluir.
Uma vez que as especificações são combinadas ou geradas a partir umas
das outras, o controlo de versões torna-se um desafio. É importante ter em
atenção a forma como as especificações gRPC e OpenAPI mantêm os seus
requisitos de compatibilidade individuais. Deve ser tomada uma decisão
ativa sobre se o acoplamento do domínio REST a um domínio RPC faz
sentido e acrescenta valor global.
Em vez de gerar RPC para este-oeste a partir de norte-sul, o que faz mais
sentido é conceber cuidadosamente a comunicação da arquitetura de
microsserviços (RPC) independentemente da representação REST,
permitindo que ambas as API evoluam livremente. Esta é a escolha que
fizemos para o estudo de caso da conferência e seria registada como um
ADR no projeto .
Resumo
Neste capítulo, abordamos como projetar, construir e especificar APIs e as
diferentes circunstâncias nas quais você pode escolher REST ou gRPC. É
importante lembrar que não se trata de REST versus gRPC, mas sim, dadas
as situações, qual é a escolha mais apropriada para modelar a troca. As
principais conclusões são:
A barreira para a criação de APIs baseadas em REST e RPC é baixa na
maioria das tecnologias. Considerar cuidadosamente o design e a
estrutura é uma importante decisão de arquitetura.
Ao escolher entre os modelos REST e RPC, considera o Modelo de
Maturidade de Richardson e o grau de acoplamento entre o produtor e
o consumidor.
REST é um padrão bastante flexível. Ao criar APIs, a conformidade
com um padrão de API acordado garante que suas APIs sejam
consistentes e tenham o comportamento esperado para seus
consumidores. Os padrões de API também podem ajudar a evitar
possíveis decisões de design que poderiam levar a uma API
incompatível.
As especificações OpenAPI são uma forma útil de partilhar a estrutura
da API e automatizar muitas actividades relacionadas com a
codificação. Deves selecionar ativamente as caraterísticas da OpenAPI
e escolher que ferramentas ou caraterísticas de geração serão aplicadas
aos projectos.
O controlo de versões é um tópico importante que acrescenta
complexidade para o produtor, mas é necessário para facilitar a
utilização da API pelo consumidor. Não planear o controlo de versões
nas APIs expostas aos consumidores é perigoso. O controlo de versões
deve ser uma decisão ativa no conjunto de caraterísticas do produto e
um mecanismo para transmitir o controlo de versões aos consumidores
deve fazer parte da discussão.
O gRPC tem um desempenho incrivelmente bom em trocas de alta
largura de banda e é uma opção ideal para trocas leste-oeste. As
ferramentas para o gRPC são poderosas e oferecem outra opção ao
modelar trocas.
A modelação de várias especificações começa a tornar-se bastante
complicada, especialmente quando se gera de um tipo de especificação
para outro. O controlo de versões complica ainda mais as coisas, mas é
um fator importante para evitar alterações de rutura. As equipas devem
pensar cuidadosamente antes de combinarem representações RPC com
representações RESTful API, uma vez que existem diferenças
fundamentais em termos de utilização e controlo sobre o código do
consumidor.
O desafio de uma arquitetura de API é satisfazer os requisitos do ponto de
vista do negócio do consumidor, criar uma excelente experiência de
desenvolvimento em torno das API e evitar problemas de compatibilidade
inesperados. No Capítulo 2, irá explorar os testes, que são essenciais para
garantir que os serviços cumprem estes objectivos.
1 Já estivemos muitas vezes nesta situação, normalmente logo à segunda-feira!
2 A validação das especificações OpenAPI em tempo de execução ajuda a impor um maior
rigor.
Capítulo 2. Testar APIs
Este trabalho foi traduzido com recurso a IA. Agradecemos o teu feedback e comentários:
translation-feedback@[Link]
O Capítulo 1 abordou os diferentes tipos de APIs e o valor que elas
fornecem à sua arquitetura. Este capítulo encerra a seção Projetando,
criando e testando APIs deste livro, revisando as abordagens para testar
APIs. A nova API de participante que foi extraída na Introdução deve
obviamente ser testada e validada. Acreditamos que os testes são
fundamentais para a criação de APIs. Eles ajudam a fornecer um alto nível
de confiança de que seu serviço está funcionando conforme o esperado, o
que o ajudará a fornecer um produto de qualidade aos consumidores de sua
API. É somente testando sua API sob condições variadas que você ganhará
a confiança de que ela está operando corretamente.
Quando constrói APIs, tal como acontece com a criação de qualquer
produto, a única forma de verificar se o produto funciona como esperado é
testá-lo. No caso de um protetor bucal, isto pode significar esticar, bater,
empurrar e puxar o produto, ou mesmo executar simulações.1
Como discutido em "Especificando APIs REST usando OpenAPI", uma
API não deve retornar nada que seja diferente do que está documentado.
Também é frustrante quando uma API introduz alterações de rutura ou
causa timeouts de rede devido à grande duração de tempo para recuperar
um resultado. Esses tipos de problemas afastam os clientes e são totalmente
evitáveis criando testes de qualidade em torno do serviço da API. Qualquer
API construída deve estar pronta para cumprir uma variedade de requisitos,
incluindo o envio de feedback útil aos utilizadores que fornecem uma má
entrada, ser segura e devolver resultados dentro de um objetivo de nível de
serviço (SLO) especificado com base nos nossos indicadores de nível de
serviço (SLIs) acordados.2
Neste capítulo, vamos apresentar os diferentes tipos de testes que podes
aplicar à tua API para ajudar a evitar que estes problemas ocorram.
Vamos destacar os pontos positivos e negativos de cada tipo de teste, para
que possas decidir onde melhor investir o teu tempo. Vamos concentrar-nos
no teste de APIs e onde acreditamos que ganharás mais valor; não vamos
cobrir testes genéricos de serviços. O capítulo conterá recursos adicionais
para os leitores que procuram obter um conhecimento significativamente
mais profundo e especializado sobre testes.
Cenário do sistema de conferência para este
capítulo
Em "Evolução do ADR dos participantes", explicámos as razões para
separar a API dos participantes do resto do sistema de conferência. A
separação da API dos participantes introduz novas interações. A API de
participantes será utilizada pelo sistema CFP externo e pelo sistema de
conferência antigo, conforme ilustrado na Figura 2-1. Neste capítulo, serão
abordados os testes necessários para o serviço de participantes e a forma
como os testes podem ajudar a verificar as interações entre o sistema de
conferência antigo e a API de participantes. Como coletivo, já vimos
bastantes API que se tornam inconsistentes ou produzem alterações
acidentais à medida que são lançadas novas versões, o que se deve
principalmente à falta de testes. Para a nova API Attendee, é importante
garantir que evita estas armadilhas, proporcionando a confiança de que
serão sempre devolvidos os resultados corretos, e a única forma de o fazer é
investindo nos níveis corretos de testes.
Figura 2-1. Cenário do capítulo
Os testes podem ser aplicados a diferentes níveis de uma API, começando
com os blocos de construção individuais que compõem o serviço, indo até à
verificação de que funciona como parte de todo o ecossistema. Antes de te
mostrar algumas ferramentas e estruturas disponíveis para testes de API, é
importante compreender as estratégias que podem ser utilizadas.
Estratégias de teste
Testes são importantes; eles garantem que você está construindo uma
aplicação que funciona. No entanto, você não quer algo que apenas
funcione, você quer algo que também tenha o comportamento correto.
Realisticamente, no entanto, você tem tempo e recursos limitados para
escrever testes, então você vai querer garantir que não está desperdiçando
ciclos escrevendo testes que fornecem pouco ou nenhum valor. Afinal de
contas, o valor para os clientes é quando estás a correr em produção. Por
isso, precisas de ser inteligente ao decidir sobre a cobertura e proporções
dos tipos de testes que deves usar. Evita criar testes irrelevantes, testes
duplicados e quaisquer testes que vão consumir mais tempo e recursos do
que o valor que fornecem (i.e., testes com falhas), Nem todos os testes
introduzidos precisam de ser implementados para poder lançar uma API,
uma vez que pode não ser viável devido a restrições de tempo e exigências
do negócio.
Para te orientar no sentido de obteres o equilíbrio certo e os testes certos
para o teu caso, vamos apresentar o quadrante de testes e a pirâmide de
testes, que te vão ajudar a identificar os testes que deves implementar.
Quadrante de teste
O quadrante de teste foi introduzido pela primeira vez por Brian Marick em
sua série de blogs sobre testes ágeis. Isso se tornou popular no livro Agile
Testing de Lisa Crispin e Janet Gregory (Addison-Wesley). O lado
tecnológico da construção de uma API se preocupa que ela tenha sido
construída corretamente, que suas peças (por exemplo, funções ou
endpoints) respondam como esperado e que seja resiliente e continue a se
comportar sob circunstâncias anormais, O negócio preocupa-se com o facto
de estar a ser desenvolvido o serviço correto (ou seja, no nosso caso, que a
API Attendee forneça a funcionalidade correta). Para clarificar, o termo "o
negócio" significa alguém que tem uma compreensão clara do produto e das
caraterísticas e funcionalidades que devem ser desenvolvidas; não precisam
de ter uma compreensão técnica.
O quadrante de testes reúne testes que ajudam tanto as partes interessadas
em tecnologia como em negócios - cada perspetiva terá opiniões diferentes
sobre as prioridades. A imagem popular do quadrante de testes é mostrada
na Figura 2-2.
Figura 2-2. Quadrantes do Agile Testing (Addison-Wesley) de Lisa Crispin e Janet Gregory
O quadrante de teste não representa qualquer ordem. Os quadrantes são
rotulados por conveniência e esta é uma fonte comum de confusão que Lisa
descreve numa das suas publicações no blogue. Os quatro quadrantes
podem ser geralmente descritos da seguinte forma:
Q1
Testes unitários e de componentes para a tecnologia. Estes devem
verificar se o serviço que foi criado funciona, e esta verificação deve ser
efectuada utilizando testes automatizados.
Q2
Faz testes com a empresa. Garante que o que está a ser construído serve
um objetivo. Verifica-o com testes automatizados e pode também incluir
testes manuais.
Q3
Testes para o negócio. Trata-se de garantir que os requisitos funcionais
sejam atendidos e também inclui testes exploratórios. Quando a Figura
2-2 foi originalmente criada, este tipo de teste era manual; agora é
possível realizar testes automatizados nesta área também.
Q4
Garantir que o que existe funciona de um ponto de vista técnico. A
partir do Q1, sabes que o que foi construído funciona; no entanto,
quando o produto está a ser utilizado, o seu desempenho é o esperado?
Exemplos de desempenho correto de um ponto de vista técnico podem
incluir a aplicação da segurança, a integridade do SLA e o
escalonamento automático.
O lado esquerdo do quadrante (Q1, Q2) tem a ver com o apoio ao produto.
Ajuda a guiar o produto e a evitar defeitos. O lado direito (Q3, Q4) trata de
criticar o produto e encontrar defeitos. A parte superior do quadrante (Q2,
Q3) é a qualidade externa do seu produto, certificando-se de que satisfaz as
expectativas dos seus utilizadores. A parte inferior do quadrante (Q1, Q4)
são os testes voltados para a tecnologia para manter a qualidade interna da
tua aplicação.3
O quadrante de teste não diz onde deve começar a testar; ajuda a orientá-lo
sobre os testes que pode querer. Isto é algo que tem de decidir e deve
basear-se nos factores importantes para si. Por exemplo, um sistema de
emissão de bilhetes tem de lidar com grandes picos de tráfego, pelo que
pode ser melhor começar por garantir que o seu sistema de bilhetes é
resiliente (por exemplo, teste de desempenho). Esta seria a parte do Q4.
Teste a pirâmide
Em adição aos quadrantes de teste, a pirâmide de teste (também conhecida
como a pirâmide de automação de teste) pode ser usada como parte de sua
estratégia para automação de teste. A pirâmide de teste foi introduzida pela
primeira vez no livro Succeeding with Agile por Mike Cohn. Esta pirâmide
ilustra uma noção de quanto tempo deve ser gasto em uma determinada área
de teste, sua dificuldade correspondente para manter, e o valor que ela
fornece em termos de confiança adicional. A pirâmide de teste em seu
núcleo permaneceu inalterada. Ela tem testes unitários como sua base,
testes de serviço no bloco do meio e testes de interface do usuário no topo
da pirâmide.A Figura 2-3 mostra as áreas da pirâmide de testes que você irá
explorar.
Figura 2-3. A pirâmide de testes, mostrando a proporção de testes desejados
A pirâmide de automação de testes mostra as soluções de compromisso que
existem em termos de confiança, isolamento e âmbito. Ao testar pequenas
partes da base de código, tens um melhor isolamento e testes mais rápidos;
no entanto, isto não te dá confiança de que toda a aplicação está a funcionar.
Ao testar toda a aplicação no seu ecossistema, o oposto é verdadeiro. Os
testes dão-te mais confiança de que a aplicação está a funcionar, mas o
âmbito do teste será grande, uma vez que muitas peças estarão a interagir
entre si. Isto também torna a manutenção mais difícil e lenta. A seguir,
define cada um dos elementos centrais da pirâmide de testes:
Testes de unidade estão na base da pirâmide; eles formam a fundação
dos teus testes. Eles testam unidades pequenas e isoladas do teu código
para garantir que a tua unidade definida está a funcionar como
esperado.4 Se o teu teste vai escapar aos limites da tua unidade, podes
usar duplos de teste. Os duplos de teste são objectos que se parecem
com versões reais de uma entidade externa; no entanto, estão sob o teu
controlo.5 Como os testes unitários formam a base da tua pirâmide,
deve haver mais testes unitários do que qualquer outro tipo de teste;
recomendamos o uso do TDD como prática.6 O TDD consiste em
escrever testes antes de escrever a lógica. Os testes unitários
enquadram-se no Q1 do quadrante de testes e são utilizados para
fornecer qualidade aos componentes internos da aplicação. Os testes
unitários não serão abordados mais detalhadamente, uma vez que nos
vamos concentrar em testes que verificam a sua API do ponto de vista
do consumidor externo, em oposição aos componentes internos de uma
API.
Testes de serviço constituem a camada intermédia da pirâmide. Eles
lhe darão mais confiança de que sua API está funcionando
corretamente do que os testes de unidade, embora sejam mais caros. A
despesa vem do fato de os testes terem um escopo maior e menos
isolamento, o que incorre em um custo maior de manutenção e
desenvolvimento. Os testes de serviço incluem alguns dos seguintes
casos: a verificação de que várias unidades estão funcionando juntas,
que o comportamento é o esperado e que o aplicativo em si é
resiliente. Portanto, os testes de serviço se encaixam em Q1, Q2 e Q4
do quadrante de teste.
Testes de UI ficam no topo da pirâmide de testes. Antigamente, a
maioria das aplicações construídas para a Web eram pilhas LAMP e a
única forma de testar a sua aplicação da frente para trás era através da
IU da Web. Existe uma IU com APIs: apenas não é gráfica, pelo que
estes testes serão agora referidos como testes end-to-end. Cobrem o
mesmo terreno de um pedido que flui de um ponto inicial para um
ponto final, mas não implicam ou assumem necessariamente que o
tráfego tem origem numa IU Web. Os testes de extremo a extremo são
os mais complexos. Têm o âmbito mais alargado e são lentos a
executar; no entanto, verificam se os módulos inteiros estão a
funcionar em conjunto, pelo que proporcionam muita confiança. Os
testes extremo-a-extremo situam-se geralmente no Q2, Q3, Q4 do
quadrante. As ferramentas para testes melhoraram e tornaram-se mais
avançadas, e estão agora a tornar cada vez mais o Q3 disponível para
automatização.
Um tipo de teste não é melhor do que outro - a pirâmide de testes é um guia
para as proporções de cada tipo de teste que deves tentar implementar. Pode
ser tentador ignorar a pirâmide de testes e concentrar-se em testes de ponta
a ponta, pois isso dá um alto grau de confiança. No entanto, isso é uma
falácia e, em vez disso, dá uma falsa sensação de segurança de que esses
testes de nível superior são de maior qualidade/valor do que os testes
unitários. A falácia dá origem à representação de teste em forma de cone de
sorvete, que é o oposto de uma pirâmide de teste. Para um argumento
robusto sobre este tópico, leia o post do blog de Steve Smith "End-to-End
Testing considered harmful". Você também pode considerar a
implementação de outras proporções de testes, embora isso não seja
[Link] Fowler escreveu um artigo atualizado sobre formas de
teste e explicou por que ele acha que o teste que é guiado por qualquer
forma diferente da pirâmide de teste é incorreto.
Diretrizes ADR para estratégias de ensaio
Para ajudar-te a decidir sobre a estratégia de teste que deves utilizar, as
Diretrizes ADR no Quadro 2-1 devem ajudar-te a tomar uma decisão
informada.
Tabela 2-1. Diretrizes ADR: Estratégias de ensaio
Decisão Ao criar a tua API, que estratégia de teste deve fazer parte do processo de
desenvolvimento?
Pontos de discussão Todas as partes interessadas na API têm tempo e disponibilidade para discutir
regularmente como a API deve funcionar? Se não conseguir comunicar
eficazmente com as partes interessadas, pode acabar por paralisar o seu
produto à espera que seja tomada uma decisão.
Nem toda a gente utilizou estas práticas antes, por isso tens de ponderar se
tens os recursos de tempo para formar toda a gente sobre elas.
Existem outras práticas no teu local de trabalho que sejam recomendadas e
devam ser utilizadas? Por vezes, podem existir estratégias internas para criar
software que funcionam para uma organização ou que são necessárias devido
à natureza do negócio.
Recomendações Recomendamos que utilizes os quadrantes de teste e a pirâmide de teste.
O quadrante de teste é muito valioso para garantir que os teus clientes estão a
receber o produto certo. O quadrante de teste, juntamente com a pirâmide de
teste, vai ajudar-te a construir uma excelente API.
Reconhecemos que nem sempre é possível usar o quadrante de testes na sua
forma mais verdadeira, tendo alguém prontamente disponível no negócio para
ajudar a orientar os teus testes. No entanto, no mínimo, usa a pirâmide de
testes, uma vez que esta concentra o lado automatizado do quadrante de testes.
Isto, no mínimo, irá garantir que encontras bugs no início do teu ciclo de
desenvolvimento.
Seja qual for o caso, precisarás sempre de alguém que te ajude a orientar a
direção do produto.
Testes de contrato
O teste de contrato tem duas entidades: um consumidor e um produtor. Um
consumidor solicita dados de uma API (por exemplo, cliente Web, terminal
shell) e um produtor (também conhecido como fornecedor) responde aos
pedidos da API, ou seja, produz dados, como um serviço Web RESTful,
Um contrato é uma definição de uma interação entre o consumidor e o
produtor. É uma declaração que diz que se um consumidor fizer um pedido
que corresponda à definição de pedido do contrato, então o produtor
devolverá uma resposta que corresponda à definição de resposta do
contrato. No caso da API Attendee, é um produtor e o consumidor é o
sistema de conferências antigo. O sistema de conferências antigo é um
consumidor, uma vez que chama a API Attendee.7 Então, porquê utilizar
contratos? O que é que eleste oferecem?
Porque é que os testes por contrato são muitas vezes
preferíveis
Como aprendeste em "Especificar APIs REST usando OpenAPI", as APIs
devem ter uma especificação, e é importante que as respostas da tua API
estejam em conformidade com a especificação da API que estabeleceste.
Ter uma definição escrita destas interações que devem ser cumpridas pelo
produtor garante que os consumidores podem continuar a usar a tua API e
torna possível gerar testes. O contrato define o aspeto que um pedido e uma
resposta devem ter e estes podem ser utilizados para verificar se o produtor
(a API) está a cumprir o contrato. Se quebrar um teste de contrato, isso
significa que o produtor já não está a cumprir o contrato, o que significa que
os consumidores ficarão sem resposta.
Como o contrato tem a definição de resposta, também é possível gerar um
servidor stub . Esse servidor stub pode ser usado pelos consumidores para
verificar se eles podem chamar o produtor corretamente e analisar a
resposta do produtor.8 Este servidor de stub pode ser utilizado pelos
consumidores para verificar se podem chamar o produtor corretamente e
analisar a resposta do produtor. O teste do contrato pode ser efectuado
localmente - não é necessário lançar serviços adicionais, o que o torna parte
dos seus testes de serviço. Os contratos evoluirão e os consumidores e
produtores apanham estas alterações à medida que são disponibilizadas, o
que garante que são capazes de se integrar continuamente com o contrato
mais recente.
Já há muito valor aqui sobre o motivo pelo qual você desejaria usar
contratos. Além disso, o teste de contratos tem um ecossistema bem
desenvolvido. Existem metodologias estabelecidas que orientam o que o
contrato deve ser, bem como estruturas e integrações de teste para gerar
contratos e fornecer maneiras eficazes de distribuí-los. Acreditamos que os
contratos são a melhor maneira de definir as interações entre o serviço que
você implementa e um consumidor. Outros testes são importantes e também
devem ser implementados, mas esses oferecem o melhor custo-benefício.
NOTA
É importante notar que testar contratos não é o mesmo que dizer que uma API está em
conformidade com um esquema . Um sistema ou é compatível com um esquema (como o
OpenAPI Spec) ou não é; um contrato é sobre uma interação definida entre as partes e fornece
exemplos. Matt Fellows tem um excelente artigo sobre isto intitulado "Schema-based contract
testing with JSON schemas and Open API (Part 1)".
Como um contrato é implementado
Como mencionou, um contrato é uma definição compartilhada de como um
produtor e um consumidor interagem. O exemplo a seguir mostra um
contrato para uma solicitação GET para o ponto de extremidade
/conference/{conference-id}/attendees. Afirma que a
resposta esperada tem uma propriedade chamada value que contém uma
matriz de valores sobre os participantes. Nesta definição de exemplo de um
contrato, pode ver que está a definir uma interação, que é utilizada para
gerar os testes e o servidor stub:
[Link] {
request {
description('Get a list of all the attendees at a
conference')
method GET()
url '/conference/1234/attendees'
headers {
contentType('application/json')
}
}
response {
status OK()
headers {
contentType('application/json')
}
body(
value: [
$(
id: 123456,
givenName: 'James',
familyName: 'Gough'
),
$(
id: 123457,
givenName: 'Matthew',
familyName: 'Auburn'
)
]
)
}
}
Na Figura 2-4, vê como os testes gerados são utilizados pelo consumidor e
pelo produtor.
Figura 2-4. Gera um servidor stub e testes a partir de um contrato
AVISO
É tentador utilizar contratos para testes de cenários. Por exemplo:
Passo 1: adiciona um participante a uma conferência.
Passo 2: obtém a lista de participantes da conferência e verifica se o participante foi
adicionado corretamente.
Os contratos servem para definir a interação; se quiseres testar este tipo de comportamento, utiliza
testes de componentes.
Uma das principais vantagens da utilização de contratos é que, uma vez que
o produtor concorda em implementar um contrato, este dissocia a
dependência da construção do consumidor e do produtor.
DICA
Utilizámos servidores stub gerados para executar demonstrações para as partes interessadas, o que
foi útil porque o produtor ainda estava a implementar a lógica, mas já tinha concordado com os
contratos.
O consumidor tem um servidor de stub para desenvolver e o produtor tem
testes para garantir que está a construir a interação correta. O processo de
teste de contrato poupa tempo, uma vez que quando o consumidor e o
produtor são implementados, devem integrar-se sem problemas.
NOTA
Os testes gerados têm de ser executados contra a tua API em execução (produtor). Quando a tua
API é lançada, deves utilizar duplas de testes para dependências externas. Não queres testar
integrações com outros serviços como parte dos teus testes de contrato gerados contra o
consumidor.
Para compreenderes a forma como os contratos são acordados, vamos
analisar as duas principais metodologias de contrato.
Contratos de produtor
Produtor O teste de contrato é quando um produtor define os seus próprios
contratos. Esta prática é normalmente utilizada quando a sua API está a ser
utilizada fora da sua organização imediata (ou seja, terceiros externos).
Quando está a desenvolver uma API para um público externo, a API precisa
de manter a sua integridade, porque a interface não pode fazer alterações de
rutura sem um plano de migração, como aprendeu em "Versionamento da
API". Embora as interações sejam actualizadas e melhoradas, nenhum
consumidor individual poderá pedir alterações que afectem toda a API e
receber uma alteração rápida, porque estas alterações precisam de ser
cuidadosamente orquestradas.
Um exemplo real de uma API desse tipo é a API Graph da Microsoft. A
Microsoft tem milhares de consumidores desta API de empresas de todo o
mundo. Não é viável que as empresas ou indivíduos ajustem os contratos
para a API Graph com o que acreditam que o contrato deve ser. Isto não
quer dizer que as alterações não devam ser sugeridas à Microsoft, pois são-
no definitivamente. No entanto, mesmo que uma alteração seja acordada,
não será feita rapidamente, pois a alteração terá de ser verificada e testada
cuidadosamente.
Se a API Attendee for disponibilizada para consumo público, as mesmas
preocupações ocorrem. O que é importante para a API Attendee é utilizar
contratos para garantir que as interações não divergem e que os dados
devolvidos são consistentes.
Outra razão para utilizar contratos de produtor é que é mais fácil começar. É
uma boa forma de introduzir contratos nas suas APIs. Ter contratos é muito
mais benéfico do que não os ter. No entanto, quando os consumidores e os
produtores estão ambos na mesma organização, sugerimos que utilize a
metodologia dos contratos orientados para o consumidor .
Contratos orientados para o consumidor
Os contratos orientados para o consumidor (CDCs), por definição, são
implementados por um consumidor que orienta a funcionalidade que
pretende ver numa interação. Os consumidores submetem contratos, ou
alterações a um contrato, ao produtor para obterem uma funcionalidade API
nova ou adicional. Quando o contrato novo/atualizado é submetido ao
produtor, inicia-se uma discussão sobre a alteração, que resultará na
aceitação ou rejeição dessa alteração.
O CDC é um processo muito interativo e social. Os proprietários das
aplicações que são consumidores e produtores devem estar ao alcance (por
exemplo, na mesma organização). Quando um consumidor pretende uma
nova interação (por exemplo, uma chamada à API) ou uma atualização de
uma interação (por exemplo, a adição de uma nova propriedade), apresenta
um pedido para essa funcionalidade.
Estudo de caso: Aplicação do CDC
No nosso caso, , isto pode significar que é apresentado um pedido de
transferência do sistema de conferências antigo para o novo serviço da API
Attendee. O pedido para a nova interação é então analisado e é realizada
uma discussão sobre esta nova funcionalidade. Por exemplo, se for sugerido
um contrato para um pedido PUT, pode ter lugar uma discussão, uma vez
que pode ser preferível que seja um pedido PATCH.
É aqui que reside uma boa parte do valor dos contratos: esta discussão entre
ambas as partes sobre qual é o problema e a utilização de um contrato para
afirmar que é isto que as duas partes aceitam e concordam.
Visão geral da metodologia dos contratos
Essas metodologias devem dar uma visão geral de como usar contratos
como parte do processo de desenvolvimento. Isso não deve ser tomado
como evangelho, pois existem variações nas etapas exatas. Por exemplo,
um processo pode solicitar que o consumidor - ao escrever o contrato -
também crie uma implementação básica do código do produtor para
cumprir o contrato. Em outro exemplo, o consumidor deve fazer o TDD da
funcionalidade necessária e, em seguida, criar o contrato antes de enviar o
pull request. O processo exato que é colocado em prática pode variar de
acordo com a equipe. Depois de entender os principais conceitos e padrões
do CDC, o processo exato que é usado é apenas um detalhe de
implementação.
Se estiveres a começar a adicionar contratos, deves ter em atenção que
existe um custo - o tempo de configuração para incorporar contratos num
projeto e também o custo de redigir os contratos. Vale a pena procurar
ferramentas que possam criar contratos para ti com base numa
especificação OpenAPI.9
Quadros de teste de contratos
É provável que, quando se trata de frameworks de teste de contrato para
HTTP, você vai querer olhar para o Pact. O Pact evoluiu para o framework
de teste de contrato padrão devido ao ecossistema que foi construído em
torno dele e ao grande número de linguagens que ele suporta. Outros
frameworks de teste de contrato estão disponíveis, e eles podem ser
opinativos. O Pact é opinativo; ele impõe que você deve executar CDC e é
especificamente projetado para isso. Um teste é escrito por um consumidor
e esse teste gera um contrato, que assume a forma de uma representação
intermediária da interação. Essa representação intermediária independente
de idioma é o motivo pelo qual o Pact tem um uso tão amplo de idiomas.
Outros frameworks têm opiniões diferentes; por exemplo, o Spring Cloud
Contracts não tem uma opinião forte sobre CDC ou contratos de produtor, e
ambos podem ser realizados. Embora o Spring Cloud Contracts seja
agnóstico em relação à linguagem por usar uma versão em contêiner do
produto, para tirar o máximo proveito dele, é necessário usar o ecossistema
Spring e JVM.10
Existem opções para testar contratos para outros protocolos; não se destina
exclusivamente a comunicações HTTP.
Armazenamento e publicação de contratos API
Tendo visto como os contratos funcionam e as metodologias para os
incorporar no processo de desenvolvimento, a próxima consideração é onde
os contratos são armazenados e como devem ser publicados.
Existem algumas opções para armazenar e publicar contratos e, mais uma
vez, estas dependem da configuração disponível para ti e para a tua
organização.
Os contratos podem ser armazenados juntamente com o código do produtor
no controlo de versões (por exemplo, Git). Também podem ser publicados
juntamente com a sua construção num repositório de artefactos, como o
Artifactory.
Em última análise, os contratos devem poder ser obtidos pelo produtor e
pelo consumidor. O ponto de armazenamento também tem de permitir a
apresentação de novos contratos. O produtor deve ter controlo sobre os
contratos que são aceites no projeto e pode garantir que não são feitas
alterações indesejadas ou que são acrescentados contratos adicionais. A
desvantagem desta abordagem é que, numa grande organização, pode ser
difícil encontrar todos os serviços API que utilizam contratos.
Outra opção é armazenar todos os contratos numa localização centralizada
para permitir a visibilidade de outras interações da API que estão
disponíveis. Esta localização central pode ser um repositório Git, mas a
desvantagem desta abordagem é que, a menos que seja organizada e
configurada corretamente, é possível e provável que os contratos sejam
empurrados para um módulo que o produtor não tem intenção de cumprir.
Outra opção para armazenar contratos é utilizar um broker. A estrutura de
contratos do Pact tem um produto de broker que pode ser utilizado como
uma localização central para alojar contratos. Um broker pode mostrar
todos os contratos que foram validados pelo produtor, uma vez que o
produtor publicará os contratos que foram cumpridos. Um broker também
pode ver quem está a utilizar um contrato para produzir um diagrama de
rede, integrar-se com pipelines CI/CD e fornecer ainda mais informações
valiosas. Esta é a solução mais abrangente disponível e, se utilizar uma
estrutura compatível com o Pact Broker, é recomendada em.
Diretriz ADR: Testes de contrato
Para perceber se a aplicação de testes de contratos é válida para o teu caso e
pesar os prós e os contras da utilização de contratos, as orientações do ADR
no Quadro 2-2 devem ajudar-te a tomar uma decisão.
Tabela 2-2. Diretriz ADR: Testes contratuais
Decisão Ao construir uma API, deves utilizar testes de contratos e, em caso afirmativo,
deves utilizar contratos orientados para o consumidor ou para o produtor?
Pontos de discussão Determina se estás pronto para incluir testes de contrato como parte dos teus
testes de API.
Queres adicionar uma camada extra de testes à tua API que os
programadores terão de conhecer?
Se os contratos nunca foram utilizados antes, é preciso tempo para decidir
como os vais utilizar.
Os contratos devem ser centralizados ou num projeto?
É necessário fornecer ferramentas e formação adicionais para ajudar as
pessoas com contratos?
Se decidires utilizar contratos, qual a metodologia a utilizar - CDC ou
contratos de produtor?
Sabes quem vai utilizar esta API?
Esta API será utilizada apenas na tua organização?
A API tem consumidores que estão dispostos a colaborar contigo para
ajudar a impulsionar a tua funcionalidade?
Recomendações Recomendamos a utilização de testes de contratos ao criar uma API. Mesmo
que haja uma curva de aprendizagem do programador e esteja a decidir como
vai configurar os seus contratos pela primeira vez, acreditamos que vale a
pena o esforço. As interações definidas que são testadas poupam muito tempo
ao integrar serviços.
Se estiver a expor a sua API a um grande público externo, é importante
utilizar contratos de produtor. Mais uma vez, é crucial ter interações definidas
que ajudem a garantir que a sua API não quebra a compatibilidade com
versões anteriores.
Se estiveres a construir uma API interna, o ideal é trabalhar em direção ao
CDC, mesmo que tenhas de começar com contratos de produtor e evoluir para
o CDC.
Se o teste de contratos não for viável, então, para um produtor, são necessárias
alternativas para garantir que a sua API está em conformidade com as
interações acordadas e fornecer uma forma de os consumidores poderem
testá-la. Isto significa que tem de ter muito cuidado com os seus testes para
que as respostas e os pedidos correspondam ao que é esperado, o que pode ser
complicado e demorado.
Teste de componentes API
Teste de componentes pode ser usado para validar se várias unidades
funcionam juntas e deve ser usado para validar o comportamento - eles são
testes de serviço na pirâmide de teste na Figura 2-3. Um exemplo de um
teste de componente é enviar uma solicitação para sua API e verificar a
resposta. Em um nível alto, isso exigirá que seu aplicativo possa ler a
solicitação, executar autenticação e autorização, desserializar uma carga
útil, executar a lógica comercial, serializar a carga útil e responder. São
muitas unidades sendo testadas, e seria difícil apontar exatamente onde
poderia estar um bug. O que difere este exemplo de um teste de contrato é
que deves verificar se o serviço tem o comportamento correto; por exemplo,
se isto era criar um novo participante, queres verificar se o serviço fez uma
chamada para a base de dados (simulada). Não estás apenas a verificar a
forma da resposta como fazem os testes de contrato. Como os testes de
componentes verificam várias unidades em conjunto, são (normalmente)
mais lentos do que os testes de unidade. Os testes de componentes não
devem chamar dependências externas. Tal como os testes de contrato, não
está a utilizar estes testes para verificar os pontos de integração externos. O
tipo de testes que pretende desencadear neste âmbito varia com base no
caso de negócio; no entanto, para as APIs, estaria a procurar validar casos
como:
É devolvido o código de estado correto quando é feito um pedido?
A resposta contém os dados corretos?
Um payload de entrada é rejeitado se for passado um parâmetro nulo
ou vazio?
Quando envio um pedido em que o tipo de conteúdo aceite é XML, os
dados devolvem o formato esperado?
Se um pedido for feito por um utilizador que não tem os direitos
corretos, qual será a resposta?
O que acontecerá se for devolvido um conjunto de dados vazio? É um
404 ou é um array vazio?
Ao criar um recurso, o cabeçalho de localização aponta para o novo
ativo criado?
A partir desta seleção de testes, podes ver como estes se dividem em duas
áreas do quadrante de teste. Isto inclui o Q1, onde estás a confirmar que a
API que está a ser construída funciona (ou seja, está a produzir resultados),
e o Q2, onde testas para verificar se as respostas da API de participantes
estão corretas.
Teste de contrato versus teste de componente
Se o teste de contratos não estiver disponível, deve utilizar testes de
componentes da API para verificar se a sua API está em conformidade com
as interações acordadas, ou seja, a sua especificação da API. Utilizar testes
de componentes da API para verificar se a sua API está em conformidade
com uma interação não éo ideal - para começar, é muito mais provável que
seja propenso a erros e é fastidioso de escrever. Deve fazer dos contratos a
sua fonte dourada de interações acordadas, uma vez que os testes gerados
garantem que a forma da sua API é exacta.
Estudo de caso: Teste de componentes para verificar o
comportamento
Vamos analisar um exemplo de um caso para a nossa API Attendee para o
ponto de extremidade /conference/{conference-
id}/attendees. Este ponto de extremidade devolve uma lista dos
participantes num evento de conferência. Para este teste de componente, é
utilizada uma simulação para representar a nossa dependência de base de
dados externa e, como se pode ver na Figura 2-5, neste caso é o DAO.
Algumas coisas para testar este ponto final são:
Os pedidos que são bem sucedidos têm uma resposta de 200 (OK)
Os utilizadores sem o nível de acesso correto devolverão um estado de
403 (Proibido)
Quando uma conferência não tem participantes, é devolvido um
conjunto vazio
Figura 2-5. Teste do componente API com DAO simulado
Uma biblioteca ou estrutura de teste que envolva um cliente de pedido pode
ser muito útil. Neste caso, o REST-Assured é utilizado para chamar o ponto
de extremidade da API Attendee e para verificar estes casos de teste:11
@Test
void response_for_attendees_should_be_200() {
given()
.header("Authorization", VALID_CREDENTIAL)
.when()
.get("/conference/conf-1/attendees")
.then()
.statusCode([Link]());
}
@Test
void response_for_attendees_should_be_403() {
given()
.header("Authorization", INVALID_CREDENTIAL)
.when()
.get("/conference/conf-1/attendees")
.then()
.statusCode([Link]());
...
}
A execução deste tipo de teste dá-nos a confiança de que a nossa API está a
comportar-se corretamente.
Teste de integração de API
Testes de integração na nossa definição são testes que atravessam as
fronteiras entre o módulo que está a ser desenvolvido e quaisquer
dependências externas. Os testes de integração são um tipo de teste de
serviço e podem ser vistos na imagem da pirâmide de testes na Figura 2-3.
Ao efetuar testes de integração, pretende confirmar que a comunicação
através da fronteira está correta, ou seja, que o seu serviço pode comunicar
corretamente com outro serviço que lhe é externo.
Os tipos de coisas que queres verificar são os seguintes:
Assegura que uma interação está a ser feita corretamente; por exemplo,
para um serviço RESTful, pode ser a especificação do URL correto ou
que o corpo do payload está correto.
A unidade que está a interagir com um serviço externo pode lidar com
as respostas que estão a ser devolvidas?
No nosso caso, o sistema de conferência antigo tem de verificar se pode
fazer um pedido à nova API Attendee e se pode interpretar a resposta.
Usando servidores Stub: Porquê e como
Se estiveres a utilizar testes de contrato, os servidores de stub gerados
podem ser utilizados para verificar se o consumidor pode comunicar com o
produtor. O sistema de conferência antigo tem um servidor de stub gerado e
pode utilizá-lo para testar. Assim, mantém os testes locais e o servidor stub
será exato. Esta é a opção preferida para testar um limite externo.
No entanto, um servidor stub gerado a partir de um contrato nem sempre
está disponível e são necessárias outras opções, como no caso de testes com
uma API externa, como a API do Microsoft Graph, ou dentro da sua
organização, quando os contratos não são usados. A opção mais simples é
criar manualmente um servidor stub que imite as solicitações e as respostas
do serviço com o qual você interage. Essa é certamente uma opção viável,
pois na linguagem e na estrutura escolhidas geralmente é muito fácil para
um desenvolvedor criar um servidor stub com respostas predefinidas que se
integram aos testes.
É muito fácil cometer erros, tais como retratar incorretamente o URL ou
cometer erros nos nomes e valores das propriedades da resposta. Consegues
ver os erros nesta resposta manual?12
{
"values": [
{
"id": 123456,
"givenName": "James",
"familyName": "Gough"
},
{
"id": 123457,
"givenName": "Matthew",
"familyNane": "Auburn"
},
{
"id": 123456,
"givenName": "Daniel",
"familyName": "Bryant"
}
]
}
Um dos autores teve grande sucesso com esta abordagem depois de um
requisito de um projeto que o obrigou a implementar um servidor stub para
um serviço de login.
Uma forma de evitar estas imprecisões e de garantir que os pedidos a URLs
são capturados com precisão juntamente com as respostas é utilizar um
gravador. É possível utilizar uma ferramenta que regista os pedidos e as
respostas a um ponto final e gera ficheiros que podem ser utilizados para
stubbing.A Figura 2-6 mostra como isto funciona.
Figura 2-6. Como um consumidor da API Attendee utilizaria um gravador para capturar um
pedido/resposta para dados de teste
Estes ficheiros gerados são mapeamentos que podem então ser utilizados
para testes para retratar com precisão os pedidos e as respostas e, como não
são feitos à mão, é garantido que são precisos no ponto de geração. Para
utilizar estes ficheiros gerados, é lançado um servidor stub capaz de ler os
ficheiros de mapeamento. Quando é feito um pedido ao servidor stub,
verifica se o pedido corresponde a algum dos pedidos esperados no ficheiro
de mapeamento. Se corresponder, então a resposta mapeada será
devolvida.13 A gravação de chamadas para APIs produzirá stubs mais
precisos do que a rolagem manual de um stub. Se você usar gravações,
precisará garantir que elas permaneçam atualizadas e sincronizadas; além
disso, se fizer gravações em relação à produção, precisará verificar se
nenhuma PII é salva nos arquivos de mapeamento .
Diretriz ADR: Teste de integração
Integração Os testes de integração são importantes, por isso, para te ajudar a
compreender que tipos de testes de integração necessitas, consulta a Diretriz
ADR na Tabela 2-3.
Tabela 2-3. Diretriz ADR: Testes de integração
Decisão Os testes de integração devem ser adicionados aos testes de API?
Pontos de discussão Se a tua API estiver a integrar-se com qualquer outro serviço, que nível de
teste de integração deves utilizar?
Sentes-te confiante de que podes simplesmente simular respostas e não
precisas de realizar testes de integração?
Para criar um servidor de stub para testar, és capaz de criar com
precisão o pedido e as respostas ou devem ser registados?
Serás capaz de manter os stub servers actualizados e reconhecer se uma
interação está incorrecta?
Se os teus stubs estiverem incorrectos ou desactualizados, isto significa que é
possível ter testes que passam no teu servidor stub, mas quando implementas
em produção, o teu serviço não consegue interagir com a outra API, uma vez
que esta foi alterada.
Recomendações Recomendamos a utilização dos servidores stub gerados a partir de testes de
contrato. No entanto, se isso não estiver disponível, ter testes de integração
usando gravações de interações é a próxima melhor opção. Ter testes de
integração que podem ser executados localmente dá a confiança de que uma
integração funcionará, especialmente ao refatorar uma integração; ajudará a
garantir que quaisquer alterações não tenham quebrado nada.
Os testes de integração são uma ferramenta realmente útil; no entanto, as
definições destas interações têm problemas. O principal problema é que são
instantâneos pontuais. Estas configurações à medida não são actualizadas
com as alterações.
Temos utilizado servidores stub para as integrações que analisámos; no
entanto, é possível utilizar uma instância real do serviço externo para
verificar uma integração.
Contentorização de componentes de teste: Contentores
de teste
É comum criar aplicações como imagens em contentores, o que significa
que muitas aplicações com as quais o teu serviço se vai integrar também
estão disponíveis como soluções em contentores. Estas imagens podem ser
executadas na tua máquina local como parte dos teus testes. A utilização de
contentores locais não só permite testar a comunicação com os serviços
externos, como também podes executar a mesma imagem que é executada
em produção.
Testcontainers é uma biblioteca que se integra com a tua estrutura de testes
para orquestrar contentores. Testcontainers irá iniciar e parar e, em geral,
organizar o ciclo de vida dos contentores que usas com os teus testes.
Estudo de caso: Aplicando Testcontainers para verificar
integrações
Vamos dar uma olhada em dois casos de uso em que isso é útil para a API
Attendee. O primeiro caso é que o serviço da API Attendee suportará uma
interface gRPC, bem como a interface RESTful. A interface gRPC deve ser
desenvolvida após a interface RESTful, mas há desenvolvedores ansiosos
que querem começar a testar com uma interface gRPC. É tomada a decisão
de fornecer um servidor stub para a interface gRPC, que será um stub que
fornece algumas respostas prontas. Para atingir esse objetivo, é criada uma
aplicação bare-bones que atende a esse objetivo. Esse stub gRPC é então
empacotado, contentorizado e publicado. Esse stub pode agora ser usado
pelos desenvolvedores para testes além de um limite; ou seja, eles podem
fazer chamadas reais para esse stub, eles podem fazer chamadas reais para
esse servidor stub em seus testes, e esse servidor stub em contêiner pode ser
executado localmente em sua máquina.
As opções para testar os limites de integração de um banco de dados seriam
simular o banco de dados, usar um banco de dados na memória (por
exemplo, H2) ou executar uma versão local do banco de dados usando
Testcontainers, H2) ou executar uma versão local do banco de dados usando
Testcontainers. Usar uma instância real do banco de dados em seu teste
fornece muito valor porque, com simulações, você pode simular o valor de
retorno errado ou fazer uma suposição incorreta. Com um banco de dados
na memória, você está assumindo que a implementação corresponde ao
banco de dados real. Usando uma instância real da dependência e sendo a
mesma versão que executa na produção significa que obtém testes
confiáveis através de um limite, o que garante que a integração funcionará
quando for para a produção. Na Figura 2-7, vê a estrutura do teste para
confirmar uma integração bem-sucedida através de um limite com um
banco de dados.
Figura 2-7. Teste de DAO dos contentores de teste
Os Testcontainers são uma ferramenta poderosa e devem ser considerados
ao testar os limites entre quaisquer serviços externos. Outros serviços
externos comuns que se beneficiam do uso de Testcontainers incluem
Kafka, Redis e NGINX. A adição desse tipo de solução aumentará o tempo
de execução dos testes; no entanto, os testes de integração geralmente são
menores e a confiança adicional fornecida na maioria das vezes é uma
solução de compromisso válida para o tempo adicional.
A utilização de Testcontainers levanta algumas questões. Em primeiro
lugar, este tipo de teste é considerado um teste de integração ou um teste de
ponta a ponta, uma vez que está a ser testada uma instância real de outro
serviço? Em segundo lugar, por que não usar isto em vez de contratos?
Sugerimos que utilize Testcontainers para testar integrações; garantir que o
contentor tem o comportamento correto não é tarefa sua (assumindo que o
proprietário da imagem está fora do seu domínio). Por exemplo, se eu
emitir uma declaração para publicar uma mensagem num broker Kafka, não
devo subscrever o tópico para verificar se o item publicado está correto.
Devo confiar que o Kafka está a fazer o seu trabalho e que os subscritores
estão a receber a mensagem. Se quiseres verificar este comportamento,
torna-o parte dos teus testes de extremo-a-extremo. É por isso que o limite
do que estás a testar é importante, pelo que o caso do DAO para a base de
dados não é um teste de extremo-a-extremo, porque apenas as interações
através do limite são validadas.
Os contentores de teste e a integração com um serviço real são uma
verdadeira bênção e podem acrescentar muito valor aos teus testes, embora
não substituam os contratos só porque podes utilizar uma versão real de um
serviço. Trabalhar com uma instância real é bom; no entanto, os contratos
fornecem muito mais do que apenas um servidor stub - fornecem todos os
testes, integração, e colaboração.
Teste de ponta a ponta
A essência dos testes de ponta a ponta é testar os serviços e as suas
dependências em conjunto para verificar se funcionam como esperado. É
importante validar que, quando um pedido é efectuado e chega à porta da
frente (ou seja, o pedido chega à sua infraestrutura), o pedido flui por todo o
caminho e o consumidor obtém a resposta correta. Esta validação dá a
confiança de que todos estes sistemas funcionam em conjunto como
esperado. No nosso caso, isto é testar o sistema de conferências antigo, o
novo serviço Attendee e a base de dados em conjunto.
Automatizando a validação de ponta a ponta
Esta secção de concentra-se em testes automatizados de ponta a ponta. A
automatização destina-se a poupar tempo, por isso, apresentaremos os testes
automatizados que acreditamos serem os mais vantajosos. Terá sempre de
verificar se os seus sistemas funcionam em conjunto - no entanto, pode
fazê-lo manualmente num ambiente de teste antes de lançar o software em
produção.
AVISO
Se estiveres a construir uma API externa e tiveres vários terceiros a consumi-la, não tentes copiar
a interface de utilizador de terceiros e replicar o seu funcionamento.
Para testes de ponta a ponta, o ideal é ter versões reais dos seus serviços em
execução e interagindo entre si; no entanto, às vezes isso nem sempre é
viável. Portanto, não há problema em deixar de fora algumas entidades de
um sistema que estão fora do domínio da sua organização e são fornecidas
por uma parte externa. Um caso hipotético seria se o serviço Attendee
exigisse o uso do AWS S3. Depender de uma entidade externa gera
preocupações como problemas de Network+ ou até mesmo a
indisponibilidade do provedor externo. Além disso, se os testes não forem
utilizar uma entidade, não é necessário disponibilizá-la para o teste. Para
um teste de ponta a ponta do serviço Attendee, é necessário iniciar a base de
dados e o serviço Attendee, mas isso não requer o sistema de conferência
legado, pois é supérfluo. É por isso que os testes de ponta a ponta às vezes
exigem limites. O limite para este teste de ponta a ponta é mostrado na
Figura 2-8.
Figura 2-8. Escopo de teste de ponta a ponta
Gerenciar e coordenar vários sistemas juntos não é fácil de automatizar e os
testes de ponta a ponta podem ser frágeis. No entanto, executar testes de
ponta a ponta localmente está se tornando mais fácil. Como acabaste de ver
em "Containerizing Test Components: Testcontainers", a contentorização
permite-te rodar múltiplos sistemas localmente. Mesmo que isto esteja a
tornar-se mais fácil, deves ainda seguir as orientações da pirâmide de testes
- os testes end-to-end estão no topo da pirâmide de testes por uma razão.
Já vimos casos em que os testes utilizam cargas pequenas e concisas e,
depois, quando se investiga a razão pela qual as APIs estão a falhar,
descobre-se que os consumidores estão a enviar regularmente cargas muito
grandes - maiores do que os buffers suportam. É por isso que os teus testes
de ponta a ponta têm de ser representativos da forma como um consumidor
utiliza a tua API.
Tipos de testes de ponta a ponta
Os testes end-to-end que escreves devem ser orientados pelos requisitos
mais importantes, como viste no "Quadrante de Testes".
No Q3 do quadrante de teste, podes ver testes de cenário. Os testes de
cenário são uma forma comum de teste de ponta a ponta. Servem para testar
percursos típicos do utilizador e fornecem a confiança de que o serviço está
a funcionar corretamente. Um teste de cenário pode basear-se numa única
ação ou em várias acções. É importante que esteja a testar apenas os
percursos principais do utilizador e não casos extremos ou testes de
exceção. Para o ajudar a escrever os seus testes, pode utilizar o
desenvolvimento orientado pelo comportamento (BDD). É uma boa forma
de escrever as histórias de utilizador como parte dos testes orientados para a
atividade. Um exemplo para o sistema de conferências seria que, quando
um participante se regista para uma palestra da conferência, a contagem de
participantes deve ter aumentado quando a informação da palestra da
conferência é recuperada.
O que é bom nos testes de cenário e na validação dessas jornadas principais
do usuário é que não vais ficar preocupado se um componente for mais
lento do que na produção. O que está a ser interrogado é o comportamento
correto e os resultados esperados. No entanto, precisas de ter mais cuidado
ao executar testes de desempenho de ponta a ponta. Os testes de
desempenho, Q4 no quadrante de testes, devem ser implementados num
ambiente semelhante ao ambiente de produção. Se os dois forem diferentes,
não obterá resultados indicativos do funcionamento dos seus serviços. Isto
significa que terá de implementar os seus serviços neste hardware
representativo e, dependendo dos seus recursos e ambiente, isso pode ser
complicado. Deve ter isto em consideração se os seus testes ficarem
instáveis ou se custar mais tempo de desenvolvimento do que o retorno da
confiança. No entanto, isto não o deve desencorajar, porque já vimos este
tipo de testes extremo-a-extremo ser bem sucedido.
Os testes de desempenho que você escreve como parte do seu teste de ponta
a ponta devem ser focados em garantir que você ainda está atendendo aos
pedidos dentro dos SLOs visados. Você quer que esses testes de
desempenho mostrem que você não introduziu nenhum atraso repentino nos
seus serviços (por exemplo, adicionando acidentalmente algum código de
bloqueio), Se o volume for importante, você quer verificar se o seu serviço
é capaz de lidar com as cargas esperadas. Algumas ótimas ferramentas estão
disponíveis para testes de desempenho, como Gatling, JMeter, Locust e K6.
Mesmo que nenhuma delas seja atraente para você, outras estão disponíveis
e em muitas linguagens diferentes com as quais você deve estar
familiarizado. Os números de desempenho que você quer devem ser
orientados pelos seus requisitos de negócios.
Como parte dos testes de ponta a ponta, tu também deves garantir que a tua
segurança está em vigor (ou seja, o TLS está ativado e os mecanismos de
autenticação adequados estão em vigor). A segurança não deve ser
desactivada para estes testes, uma vez que não os torna representativos de
uma viagem do utilizador ou deturpa as métricas.
Os testes de ponta a ponta são mais complexos do que qualquer outro tipo
de teste, uma vez que requerem recursos para serem criados e mantidos.
Embora possam poupar tempo em relação aos testes manuais de ponta a
ponta, proporcionam confiança na aplicação e provas de que os serviços
estavam a funcionar de um ponto de vista técnico para cumprir os acordos
de serviço .
Diretrizes ADR: Teste de ponta a ponta
É importante saber o que incluir e se vale a pena fazer testes de ponta a
ponta para o teu caso. As Diretrizes ADR no Quadro 2-4 devem ajudar-te a
tomar uma decisão.
Tabela 2-4. Diretrizes ADR: Teste de ponta a ponta
Decisão Como parte da tua configuração de testes, deves utilizar testes automatizados
de ponta a ponta?
Pontos de discussão Determina a complexidade da tua configuração para permitir testes de
extremo-a-extremo. Tens uma boa ideia dos testes de extremo-a-extremo de
que necessitas e que serão úteis? Existem requisitos específicos ou testes de
extremo-a-extremo mais avançados que deves acrescentar?
Recomendações Recomendamos que realizes, no mínimo, testes de ponta a ponta nas
principais jornadas do utilizador. Isto vai dar feedback o mais cedo possível
no teu ciclo de desenvolvimento de que um utilizador pode ser afetado pelas
alterações que foram feitas. Idealmente, podes executar estes testes de ponta a
ponta localmente; no entanto, se não for possível, então deve fazer parte do
teu pipeline de construção.
Se não for possível efetuar testes automatizados de ponta a ponta, é necessário
dispor de um livro de execução de testes manuais que possa ser utilizado. Este
livro de execução deve ser utilizado num ambiente de teste antes de uma
versão de produção. Este tipo de testes manuais atrasará consideravelmente as
suas versões de produção e a sua capacidade de fornecer valor aos clientes .
Resumo
Neste capítulo, aprendeste sobre os principais tipos de testes para APIs,
incluindo o que deve ser testado e onde o tempo deve ser dedicado. As
principais conclusões são:
Mantém os fundamentos dos testes e faz dos testes unitários o núcleo
da tua API.
Os testes de contrato podem ajudar-te a desenvolver uma API
consistente e a testar com outras APIs.
Executa testes de serviço no teu componente e isola as integrações
para validar o tráfego de entrada e de saída.
Utiliza testes de ponta a ponta para replicar as principais jornadas do
utilizador para ajudar a validar que todas as suas APIs se integram
corretamente.
Utiliza as Diretrizes ADR como uma forma de saber se deves
adicionar testes diferentes à tua API.
Embora te tenhamos dado muitas informações, ideias e técnicas para testar
a tua API, esta não é, de forma alguma, uma lista exaustiva das ferramentas
disponíveis. Encorajamos-te a fazer alguma pesquisa sobre as estruturas de
teste e as bibliotecas que podes querer utilizar, para garantir que estás a
tomar uma decisão informada.
No entanto, não importa quantos testes sejam feitos antecipadamente, nada
é tão bom quanto ver como um aplicativo realmente funciona em produção.
Aprenderá mais sobre testes em produção no Capítulo 5. O próximo
capítulo se concentrará em expor e gerenciar APIs em um ambiente de
produção usando gateways de API.
1 O amigo do Mateus é dono de uma empresa de protectores bucais e ouviu falar do árduo
processo de testar a integridade do produto. Ninguém quer um protetor bucal em que o único
teste é feito durante o jogo!
2 Os SLOs e SLIs serão discutidos mais detalhadamente no Capítulo 5.
3 Para saber mais sobre testes Agile, consulta os livros Agile Testing (O'Reilly), More Agile
Testing (O'Reilly) ou a série de vídeos Agile Testing Essentials.
4 O exemplo típico de uma unidade em linguagens orientadas para objectos (OO) é uma classe.
5 As duplas de teste incluem stubs, que se parecem com implementações reais de uma entidade
externa, exceto que retornam respostas codificadas. Os simulacros parecem implementações
reais de objectos pré-programados, mas são utilizados para verificar o comportamento.
6 O livro de Kent Beck Test Driven Development: By Example (Addison-Wesley) é um recurso
fantástico para aprenderes mais sobre TDD.
7 Para clarificar, também é possível que um serviço possa ser simultaneamente produtor e
consumidor.
8 Um stub server é um serviço que pode ser executado localmente e que devolve respostas
predefinidas.
9 No momento em que escrevo, existem alguns projectos disponíveis, embora nenhum seja
mantido ativamente, pelo que é difícil recomendar algum.
10 O Pacto faz um bom trabalho de comparação com outros quadros contratuais.
11 Essas bibliotecas de teste geralmente têm uma linguagem específica de domínio (DSL) e
facilitam a análise das respostas da API. O RestAssured é um desses frameworks de teste
REST em Java, e o pacote httptest vem de fábrica com Java. Dependendo da linguagem ou
da estrutura que usas, deve haver algo disponível; caso contrário, criar um pequeno wrapper
em torno de um cliente padrão pode facilitar consideravelmente a integração de respostas ao
escrever testes.
12 Valor duplicado para id e escreve incorretamente familyNane (sic).
13 O Wiremock é uma ferramenta que pode ser utilizada como um serviço autónomo, o que o
torna independente da linguagem, embora, uma vez que é escrito em Java, existam algumas
integrações específicas em Java de que podes tirar partido. Existem muitas outras ferramentas
disponíveis que têm uma capacidade semelhante noutras linguagens, como o camouflage, que é
escrito em Typescript.
Parte II. Gestão de tráfego API
Esta secção explora a forma como o tráfego da API é gerido, o que inclui o
tráfego proveniente de utilizadores finais que entra (ingressing) no seu
sistema e o tráfego proveniente de serviços que percorre (service-to-service)
o seu sistema.
No Capítulo 3, onde recomendamos que comeces a tua viagem, vais
explorar a utilização da tecnologia API gateway para gerir o tráfego de
entrada, ou tráfego norte-sul.
No Capítulo 4, aprenderás a gerir o tráfego este-oeste utilizando o padrão
service mesh.
Capítulo 3. Gateways de API:
Gerenciamento de tráfego de
entrada
Este trabalho foi traduzido com recurso a IA. Agradecemos o teu feedback e comentários:
translation-feedback@[Link]
Agora que tens uma boa compreensão da definição e teste de uma API,
podemos voltar a nossa atenção para as plataformas e ferramentas que são
responsáveis pela entrega de APIs aos consumidores na produção. Um
gateway de API é uma parte crítica de qualquer pilha de tecnologia
moderna, situando-se na "borda" da rede dos sistemas e actuando como uma
ferramenta de gestão que faz a mediação entre um consumidor e uma
coleção de serviços de backend.
Neste capítulo, aprenderás sobre o "porquê", "o quê" e "onde" dos gateways
de API e explorarás a história do gateway de API e de outras tecnologias de
ponta. Também explorarás a taxonomia dos gateways de API e saberás
como estes se enquadram no panorama geral da arquitetura do sistema e dos
modelos de implementação, evitando armadilhas comuns.
Com base em todos esses tópicos, concluirá o capítulo aprendendo a
selecionar um gateway de API apropriado com base em seus requisitos,
restrições e casos de uso.
Um API Gateway é a única solução?
Nós, , temos sido frequentemente questionados: "Um gateway de API é a
única solução para obter tráfego de utilizadores para sistemas backend?" A
resposta curta é não.
Muitos sistemas de software precisam de encaminhar os pedidos de API do
consumidor ou o tráfego de entrada de uma origem externa para uma
aplicação interna de backend. Com sistemas de software baseados na Web,
muitas vezes os pedidos de API do consumidor têm origem num utilizador
final que interage com um sistema de backend através de um navegador
Web ou de uma aplicação móvel. Os pedidos de um consumidor podem
também ter origem num sistema externo (muitas vezes de terceiros) que faz
pedidos a uma API através de uma aplicação implantada noutro local na
Internet.
Como aprenderás ao longo deste capítulo, um API gateway não é a única
tecnologia que pode fornecer estes requisitos. Por exemplo, podes utilizar
um proxy simples ou uma implementação de balanceador de carga. No
entanto, acreditamos que é a solução mais utilizada, particularmente num
contexto empresarial, e à medida que o número de consumidores e
fornecedores aumenta, é frequentemente a opção mais escalável,
sustentável e segura.
Como se mostra na Tabela 3-1, é necessário fazer corresponder os requisitos
actuais às capacidades de cada solução. Não te preocupes se não
compreenderes todos estes requisitos, pois aprenderás mais sobre eles ao
longo do capítulo.
Tabela 3-1. Comparação de proxies reversos, balanceadores de carga
e gateways de API
Caraterística Proxy invertido Balanceador de carga Gateway da API
Backend único * * *
TlS/SSL * * *
Vários back-ends * *
Descoberta de serviços * *
Composição API *
Autorização *
Lógica de repetição *
Limitação da taxa *
Registo e rastreio *
Quebra de circuitos *
Orientações: Proxy, balanceador de carga ou
gateway de API
A Tabela 3-2 fornece uma série de Diretrizes ADR para te ajudar a decidir
qual a melhor solução de entrada para o sistema da tua organização ou para
o projeto atual.
Tabela 3-2. Orientação para ADR: Proxy, balanceador de carga ou
gateway de API
Decisão Deves utilizar um proxy, um balanceador de carga ou gateways de API para
encaminhar o tráfego de entrada?
Pontos de discussão Pretendes um encaminhamento simples, por exemplo, de um único ponto de
extremidade para um único serviço de backend?
Tens requisitos multifuncionais que requerem funcionalidades mais
avançadas, como autenticação, autorização ou limitação de taxas?
Necessitas de funcionalidades de gestão de API, como chaves/tokens de API
ou monetização/chargeback?
Já tens uma solução implementada ou existe um mandato de toda a
organização que obriga a que todo o tráfego seja encaminhado através de
determinados componentes na extremidade da tua rede?
Recomendações Utiliza sempre a solução mais simples para as tuas necessidades, tendo em
conta o futuro imediato e as necessidades conhecidas.
Se tiveres requisitos multifuncionais avançados, um gateway de API é
normalmente a melhor escolha.
Se a tua organização for uma empresa, recomenda-se um gateway de API que
suporte funcionalidades de Gestão de API (APIM).
Efectua sempre a devida diligência na tua organização relativamente a
mandatos, soluções e componentes existentes.
Estudo de caso: Expondo o Serviço ao
Participante aos Consumidores
Uma vez que o sistema de conferências tem tido uma aceitação
considerável desde o seu lançamento, os proprietários gostariam de permitir
que os participantes na conferência pudessem ver os seus detalhes através
de uma nova aplicação móvel. Para tal, é necessário que a API do serviço
Attendee seja exposta externamente para que a aplicação móvel possa
consultar estes dados. Uma vez que o serviço Attendee contém informações
de identificação pessoal (PII), isto significa que a API deve ser segura, para
além de fiável e observável. Pode simplesmente expor a API utilizando um
proxy ou um equilibrador de carga e implementar quaisquer requisitos
adicionais utilizando caraterísticas específicas da linguagem ou da estrutura.
No entanto, deve perguntar a si próprio se esta solução seria escalável, se
seria reutilizável (potencialmente suportando APIs adicionais utilizando
diferentes linguagens e estruturas) e se estes desafios já foram resolvidos no
âmbito de tecnologias ou produtos existentes. Neste estudo de caso,
sabemos que está planeada a exposição de APIs adicionais no futuro e que
podem ser utilizadas linguagens e estruturas adicionais na sua
implementação. Por conseguinte, faz sentido implementar uma solução
baseada num gateway de API.
À medida que este capítulo se desenvolve, adiciona um gateway de API ao
estudo de caso do sistema de conferências existente para expor a API do
participante de forma a cumprir todos os requisitos listados. A Figura 3-1
mostra como será a arquitetura do sistema de conferência com a adição de
um gateway de API.
Figura 3-1. Usa um gateway de API para rotear para o serviço Attendee executado
independentemente do monólito
O que é um API Gateway?
Em poucas palavras, um gateway de API é uma ferramenta de gestão que se
situa na extremidade de um sistema entre um consumidor e um conjunto de
serviços de backend e actua como um ponto de entrada único para um
grupo definido de APIs. O consumidor pode ser uma aplicação ou
dispositivo de utilizador final, como uma aplicação Web de página única ou
uma aplicação móvel, ou outro sistema interno, ou uma aplicação ou
sistema de terceiros.
Um gateway de API é implementado com dois componentes fundamentais
de alto nível: um plano de controlo e um plano de dados. Estes
componentes podem normalmente ser agrupados ou implementados
separadamente. O plano de controlo é o local onde os operadores interagem
com o gateway e definem rotas, políticas e a telemetria necessária. O plano
de dados é o local onde ocorre todo o trabalho especificado no plano de
controlo, os pacotes de rede são encaminhados, as políticas são aplicadas e
a telemetria é emitida.
Que funcionalidades oferece um API
Gateway?
A nível da rede , um gateway de API funciona normalmente como um
proxy inverso para aceitar todos os pedidos de API de um consumidor,
chama e agrega os vários serviços backend a nível de aplicação (e
potencialmente serviços externos) necessários para os satisfazer e devolve o
resultado adequado.
O QUE É UM PROXY, PROXY DIRETO E PROXY
REVERSO?
Um servidor proxy, por vezes referido como proxy direto, é um servidor
intermediário que encaminha pedidos de conteúdo de vários clientes
para diferentes servidores na Internet. Um proxy direto é utilizado para
proteger os clientes. Por exemplo, uma empresa pode ter um proxy que
encaminha e filtra o tráfego dos funcionários para a Internet pública.
Um servidor proxy inverso, por outro lado, é um tipo de servidor proxy
que normalmente se situa atrás da firewall numa rede privada e
encaminha os pedidos dos clientes para o servidor backend adequado.
Um proxy inverso foi concebido para proteger os servidores.
Um gateway de API fornece requisitos transversais, como a autenticação do
utilizador, a limitação da taxa de pedidos e os tempos limite/retenções, e
pode fornecer métricas, registos e dados de rastreio para apoiar a
implementação da observabilidade no sistema. Muitos gateways de API
fornecem funcionalidades adicionais que permitem aos programadores gerir
o ciclo de vida de uma API, ajudar na integração e gestão dos
programadores que utilizam as API (como fornecer um portal de
programador e administração de contas e controlo de acesso relacionados) e
fornecer governação empresarial.
Onde é implementado um API Gateway?
Um gateway de API é normalmente implantado na borda de um sistema,
mas a definição de "sistema", nesse caso, pode ser bastante flexível. Para
startups e muitas pequenas e médias empresas (SMBs), um gateway de API
será frequentemente implantado na borda do data center ou da Cloud.
Nessas situações, pode haver apenas um único gateway de API (implantado
e executado por meio de várias instâncias para alta disponibilidade) que
atua como a porta de entrada para toda a propriedade de back-end, e o
gateway de API fornecerá toda a funcionalidade de borda discutida neste
capítulo por meio desse único componente.
A Figura 3-2 mostra como os clientes interagem com um gateway de API e
sistemas backend através da Internet.
Figura 3-2. Uma implementação típica de startup/SMB API gateway
Para grandes organizações e empresas, um gateway de API será
normalmente implantado em vários locais, muitas vezes como parte da
pilha de borda inicial no perímetro de um centro de dados, e gateways
adicionais podem ser implantados como parte de cada produto, linha de
negócios ou departamento organizacional. Neste contexto, estes gateways
seriam mais tipicamente implementações separadas e podem oferecer
funcionalidades diferentes, dependendo da localização geográfica (por
exemplo, governação necessária) ou capacidades de infraestrutura (por
exemplo, executando em recursos de computação de borda de baixa
potência).
A Figura 3-3 mostra como um gateway de API fica frequentemente entre a
Internet pública e a zona desmilitarizada (DMZ) de uma rede privada.
Figura 3-3. Uma implantação típica de gateway de API grande/empresa
Como aprenderás mais tarde neste capítulo, a definição e a funcionalidade
exacta oferecida num API gateway nem sempre é consistente entre
implementações, pelo que os diagramas anteriores devem ser considerados
mais conceptuais do que uma implementação exacta do .
Como é que um API Gateway se integra com
outras tecnologias no Edge?
Existem normalmente muitos componentes implantados na borda de um
sistema baseado em API. É aqui que os consumidores e usuários interagem
pela primeira vez com o back-end e, portanto, muitas preocupações
transversais são melhor abordadas aqui. Portanto, uma pilha de tecnologia
de borda moderna ou "pilha de borda" fornece uma gama de
funcionalidades que atendem aos requisitos multifuncionais essenciais para
aplicativos baseados em API. Em alguns edge stacks, cada funcionalidade é
fornecida por um componente implantado e operado separadamente e, em
outros, a funcionalidade e/ou os componentes são combinados. Você
aprenderá mais sobre os requisitos individuais na próxima seção do
capítulo, mas, por enquanto, a Figura 3-4 deve destacar as principais
camadas de um edge stack moderno.
Essas camadas não devem ser tratadas como um componente monólito.
Normalmente, elas são implantadas separadamente e podem pertencer e ser
operadas por equipes individuais ou por provedores de serviços
terceirizados. Vários gateways de API fornecem todas as funcionalidades
de uma pilha de borda. Outros se concentram simplesmente na
funcionalidade do gateway de API e no gerenciamento de API. Também é
comum em ambientes Cloud que o fornecedor de Cloud forneça um
balanceador de carga que pode ser integrado a um gateway de API.
Figura 3-4. Uma pilha de bordas moderna
Agora que já tens uma boa ideia sobre "o quê" e "onde" de um gateway de
API, vamos ver por que razão uma organização utilizaria um gateway de
API .
Porquê utilizar um API Gateway?
Uma grande parte do papel do arquiteto de software moderno é fazer as
perguntas difíceis sobre o design e a implementação. Isto não é diferente
quando se lida com APIs, gestão de tráfego e tecnologias relacionadas. É
necessário equilibrar a implementação a curto prazo e a manutenção a longo
prazo. Há muitas preocupaçõestransversais relacionadas com as APIs que
podes ter, incluindo a manutenção, a extensibilidade, a segurança, a
observabilidade, a gestão do ciclo de vida do produto e a monetização. Um
gateway de API pode ajudar com tudo isto!
Esta secção do capítulo fornece-te uma visão geral dos principais problemas
que um gateway de API pode resolver, tais como:
Reduzir o acoplamento utilizando um adaptador/facada entre frontends
e backends
Simplificar o consumo através da agregação/tradução de serviços
backend
Proteger as APIs contra uso excessivo e abuso com deteção e
mitigação de ameaças
Compreender como as API estão a ser consumidas (observabilidade)
Gerir APIs como produtos com a gestão do ciclo de vida da API
Rentabilizar as APIs utilizando a gestão de contas, a faturação e o
pagamento
Reduzir o acoplamento: Adaptador/Facada entre
Frontends e Backends
Três conceitos fundamentais que todos os arquitectos de software devem
aprender no início da sua carreira são o acoplamento, a coesão e a ocultação
de informação. É-te ensinado que os sistemas que são concebidos para
exibirem um acoplamento frouxo e uma coesão elevada serão mais fáceis
de compreender, manter e modificar. A ocultação de informação é o
princípio da segregação das decisões de design num sistema de software
que têm maior probabilidade de mudar. O acoplamento frouxo permite que
diferentes implementações sejam facilmente trocadas e pode ser
especialmente útil ao testar sistemas (por exemplo, é mais fácil simular
dependências frouxamente acopladas), A elevada coesão promove a
compreensibilidade - ou seja, todo o código num módulo ou sistema suporta
um objetivo central - e a fiabilidade e reutilização. A ocultação de
informação protege outras partes do sistema de modificações extensas se a
decisão de conceção for alterada. Na nossa experiência, as APIs são
frequentemente os locais num sistema em que a teoria da arquitetura se
encontra com a realidade; uma API é literal e figurativamente uma interface
com a qual outros engenheiros se integram.
Um gateway de API pode funcionar como um ponto de entrada único e
como uma fachada ou um adaptador, promovendo assim o acoplamento
frouxo e a coesão. Uma fachada define uma nova interface mais simples
para um sistema, enquanto um adaptador reutiliza uma interface antiga com
o objetivo de apoiar a interoperabilidade entre duas interfaces existentes. Os
clientes integram-se com a API exposta no gateway, o que, desde que o
contrato acordado seja mantido, permite que os componentes no backend
mudem de localização, arquitetura e implementação (linguagem, estrutura,
etc.) com impacto mínimo. A Figura 3-5 demonstra como um gateway de
API pode atuar como um ponto de entrada único para pedidos de clientes às
APIs e serviços de backend.
Figura 3-5. Um gateway de API que fornece uma fachada entre frontends e backends
Simplifica o consumo: Agregação/tradução de serviços
de back-end
Construindo na discussão sobre acoplamento na seção anterior, muitas
vezes a API que você deseja expor aos sistemas front-end é diferente da
interface atual fornecida por um back-end ou composição de sistemas back-
end. Por exemplo, você pode querer agregar as APIs de vários serviços
back-end que são de propriedade de vários proprietários em uma única API
voltada para o consumidor, a fim de simplificar o modelo mental para
engenheiros front-end, agilizar o gerenciamento de dados ou ocultar a
arquitetura back-end. É claro que existem soluções de compromisso com a
implementação deste tipo de funcionalidade aqui, e pode ser muito fácil
acoplar a lógica dentro de um gateway de API com a lógica de negócios do
serviço de back-end.
ORQUESTRAÇÃO DE CHAMADAS DE API
SIMULTÂNEAS
Uma abordagem popular de simplificação do implementada em
gateways de API é a orquestração de chamadas simultâneas de APIs de
back-end. É aqui que o gateway orquestra e coordena a chamada
simultânea de várias APIs de back-end independentes. Normalmente, o
usuário deseja chamar várias APIs independentes e não acopladas em
paralelo, em vez de sequencialmente, para economizar tempo ao reunir
resultados para o consumidor. Mais uma vez, a solução de compromisso
é que a lógica comercial pode ficar espalhada pelo gateway da API e
pelos sistemas de backend. Há também questões de acoplamento de
operações a considerar. Uma mudança de implementação num gateway
da API que altere a ordem das chamadas da API pode ter impacto nos
resultados esperados, especialmente se as chamadas de backend não
forem idempotentes.
Por exemplo, pode ter vários sistemas "tradicionais" que fornecem apenas
APIs baseadas em SOAP, mas pretende apenas expor APIs do tipo REST
aos consumidores. Um gateway de API pode fornecer esta funcionalidade
de agregação e tradução, embora seja necessário ter cuidado com esta
utilização. Existe um custo de conceção, implementação e teste para
garantir que a tradução tem a fidelidade correta. Existe também um custo de
recurso de computação para implementar a tradução, que pode ser
dispendioso quando se trata de um grande número de pedidos. A Figura 3-6
mostra como um gateway de API pode fornecer agregação de chamadas de
serviço de backend e tradução de protocolos .
Figura 3-6. Um gateway de API que fornece agregação e tradução
Protege as APIs contra o uso excessivo e abusivo:
Deteçãoe atenuação de ameaças
O edge de um sistema é onde os utilizadores interagem pela primeira vez
com as suas aplicações. É também muitas vezes o ponto onde os maus
actores e os hackers encontram os seus sistemas pela primeira vez. Embora
a grande maioria das organizações empresariais tenha várias camadas
focadas na segurança para a sua pilha de edge, tais como uma rede de
entrega de conteúdos (CDN) e uma firewall de aplicações Web (WAF), e
mesmo uma rede de perímetro e uma zona desmilitarizada dedicada (DMZ),
para muitas organizações mais pequenas o gateway de API pode ser a
primeira linha de defesa. Por esse motivo, muitos gateways de API incluem
funcionalidades voltadas para a segurança, como terminação de TLS,
autenticação/autorização, listas de permissão/negação de IP, WAFs
(embutidos ou por meio de integração externa), limitação de taxa e redução
de carga e validação de contrato de API. A Figura 3-7 destaca como uma
lista de permissão/negação e a limitação de taxa podem ser usadas para
mitigar o abuso de APIs.
Figura 3-7. Uso excessivo e abuso do gateway da API
Uma grande parte desta funcionalidade é a capacidade de detetar abusos da
API, quer acidentais quer deliberados, e para isso terás de implementar uma
estratégia abrangente de observabilidade.
Compreende como as APIs estão a ser consumidas:
Observabilidade
Compreender o desempenho dos sistemas e das aplicações é de importância
vital para garantir que os objetivos do negócio estão sendo alcançados e que
os requisitos do cliente estão sendo satisfeitos.1 É cada vez mais comum
medir os objectivos empresariais através de indicadores-chave de
desempenho (KPIs), como a conversão de clientes, receitas por hora, início
de fluxos por segundo, etc. As infra-estruturas e as plataformas são
normalmente observadas através da lente dos indicadores de nível de
serviço (SLIs), como a latência, os erros, a profundidade da fila, etc.
É um local ideal para capturar métricas de entrada de primeira linha, como
o número de erros, a taxa de transferência e a latência, e também é um local
importante para identificar e anotar solicitações (potencialmente com
metadados específicos da aplicação) que fluem pelo sistema mais a
montante.2 são normalmente injetados em uma solicitação por meio do
gateway de API e, em seguida, podem ser propagados por cada serviço
upstream. Esses identificadores podem ser usados para correlacionar
entradas de log e traços de solicitação entre serviços e sistemas.
Embora a emissão e a recolha de dados de observabilidade sejam
importantes ao nível do sistema, também é necessário pensar
cuidadosamente como processar, analisar e interpretar estes dados em
informações acionáveis que podem depois ser utilizadas para orientar a
tomada de decisões. A criação de painéis de controlo para visualização e
manipulação, e também a definição de alertas, são vitais para uma estratégia
de observabilidade bem sucedida .
Gere APIs como produtos: Gerenciamento do ciclo de
vida da API
APIs modernas são frequentemente projetadas, construídas e executadas
como produtos que são consumidos tanto por sistemas internos quanto por
terceiros, e devem ser gerenciadas como tal. Muitas grandes organizações
vêem as APIs como um componente crítico e estratégico e, como tal,
criarão uma estratégia de programa de API e definirão objetivos comerciais,
restrições e recursos claros. Com uma estratégia definida, a abordagem
tática do dia a dia é frequentemente focada no gerenciamento do ciclo de
vida da API. A gestão completa do ciclo de vida da API (APIM) abrange
todo o período de vida de uma API, que começa na fase de planeamento e
termina quando a API é retirada. Muitas das fases do ciclo de vida estão
fortemente associadas à implementação fornecida por uma porta de ligação
da API. Por estas razões, a escolha de uma porta de ligação da API
adequada é uma decisão crítica se estiver a apoiar a APIM.
Existem várias definições para as principais fases do ciclo de vida da API, e
acreditamos que a equipa da Axway consegue um bom equilíbrio ao definir
3 componentes principais - criar, controlar e consumir - e 10 fases
principais do ciclo de vida de uma API:
Construção
Conceber e construir a tua API.
Testes
Verifica a funcionalidade, o desempenho e as expectativas de segurança.
Publicação
Expor as tuas APIs aos programadores.
Proteger
Atenuar os riscos e preocupações de segurança.
Gerir
Mantém e gere APIs para garantir que são funcionais, actualizadas e
cumprem os requisitos comerciais.
Integração
Permitir que os programadores aprendam rapidamente a consumir as
APIs expostas. Por exemplo, oferecendo documentação OpenAPI ou
AsyncAPI e fornecendo um portal e uma caixa de areia.
Analisar
Permite a observabilidade e analisa os dados de monitorização para
compreender a utilização e detetar problemas.
Promover
Anunciar APIs para desenvolvedores - por exemplo, listando-as em um
mercado de APIs.
Monetização
Permite a cobrança e a recolha de receitas pela utilização de uma API.
Abordamos este aspeto da gestão do ciclo de vida da API como uma
fase separada na secção seguinte.
Reforma
Apoia a descontinuação e a remoção de APIs, o que acontece por várias
razões, incluindo mudanças de prioridades comerciais, alterações
tecnológicas e preocupações de segurança.
A Figura 3-8 demonstra como a gestão do ciclo de vida da API se integra
com um gateway de API e serviços backend .
Figura 3-8. Gestão do ciclo de vida do gateway da API
Monetiza as APIs: Gestão de contas, faturação e
pagamento
O tópico das APIs monetizadas por faturação está intimamente relacionado
com a gestão do ciclo de vida das APIs. As APIs expostas aos clientes têm
normalmente de ser concebidas como um produto e oferecidas através de
um portal de programador que também inclui a gestão de contas e opções
de pagamento. Muitos dos gateways de API empresariais incluem
monetização.3 Estes portais de pagamento integram-se frequentemente com
soluções de pagamento, como o PayPal ou o Stripe, e permitem a
configuração de planos para programadores, limites de taxas e outras
opções de consumo de API .
Uma história moderna dos API Gateways
Agora que tens uma boa compreensão do "o quê", "onde" e "porquê" das
gateways de API, é altura de dar uma vista de olhos à história antes de olhar
para a tecnologia atual de gateways de API. Como Mark Twain terá dito, "a
história não se repete, mas muitas vezes rima", e qualquer pessoa que tenha
trabalhado em tecnologia durante mais do que alguns anos apreciará
definitivamente a relevância que esta citação tem para a abordagem geral
vista na indústria. O estilo e os padrões da arquitetura se repetem em vários
"ciclos" ao longo da história do desenvolvimento de software, assim como
as abordagens operacionais. Normalmente, há progresso entre esses ciclos,
mas precisamos ter cuidado para não perder os ensinamentos que a história
tem a oferecer.
É por isso que é importante compreender o contexto histórico dos gateways
de API e da gestão de tráfego na extremidade dos sistemas. Ao olhar para
trás, podemos construir sobre bases sólidas, compreender os requisitos
fundamentais e também tentar evitar repetir os mesmos erros.
Anos 90 em diante: balanceadores de carga de hardware
O conceito da World Wide Web (WWW) foi proposto por Tim Berners-Lee
no final da década de 1980, mas não entrou na consciência do público em
geral até meados da década de 1990, altura em que o entusiasmo inicial
culminou no boom e na falência das dot-com no final da década de 1990.
Este período da "Web 1.0" impulsionou a evolução dos navegadores Web (o
Netscape Navigator foi lançado no final de 1994), do servidor Web (o
Apache Web Server foi lançado em 1995) e dos equilibradores de carga de
hardware (a F5 foi fundada em 1996). A experiência da Web 1.0 consistia
em os utilizadores visitarem sítios Web através de pedidos HTTP utilizando
o seu browser, sendo devolvido na resposta todo o documento HTML de
cada página de destino. Os aspectos dinâmicos de um sítio Web eram
implementados através da Common Gateway Interface (CGI) em
combinação com scripts escritos em linguagens como Perl ou C. Esta foi,
sem dúvida, a primeira incursão daquilo a que hoje chamaríamos "função
como serviço (FaaS)".
À medida que um número cada vez maior de utilizadores acedia a cada sítio
Web, os servidores Web subjacentes ficavam sobrecarregados, o que
obrigava a conceber sistemas que permitissem distribuir o aumento da carga
e também fornecer tolerância a falhas. Os equilibradores de carga de
hardware foram implementados na extremidade do centro de dados, com o
objetivo de permitir que os engenheiros de infraestruturas, os especialistas
em redes e os administradores de sistemas distribuíssem os pedidos dos
utilizadores por várias instâncias de servidores Web. Estas primeiras
implementações de balanceadores de carga suportavam normalmente
verificações básicas de saúde e, se um servidor Web falhasse ou começasse
a responder com maior latência, os pedidos dos utilizadores poderiam ser
encaminhados para outro local em conformidade. Os balanceadores de
carga de hardware continuam a ser muito utilizados atualmente. A
tecnologia pode ter melhorado juntamente com a tecnologia de transístores
e a arquitetura dos chips, mas a funcionalidade principal permanece a
mesma.
Início dos anos 2000 em diante: Balanceadores de carga
de software
À medida que a web ultrapassava os primeiros tropeções empresariais da
falência das dot-com, a procura de suporte a uma série de atividades, como
a partilha de conteúdos pelos utilizadores, o comércio eletrónico e as
compras online, e a colaboração e integração de sistemas pelas empresas,
continuava a aumentar. Em reação, as arquiteturas de software baseadas na
web começaram a assumir várias formas. As organizações mais pequenas
estavam a desenvolver o seu trabalho inicial com CGI e estavam também a
criar aplicações monólitas nas linguagens emergentes e amigas da Web,
como Java e .NET. As empresas maiores começaram a adotar a arquitetura
orientada para os serviços (SOA) e as especificações de "serviços Web"
associadas (WS-*) tiveram um breve momento de glória.
Os requisitos de alta disponibilidade e escalabilidade dos sítios Web
estavam a aumentar e o custo e a inflexibilidade dos primeiros
equilibradores de carga de hardware começavam a tornar-se um fator
limitativo. Entram em cena os equilibradores de carga de software e os
proxies de uso geral que podiam ser utilizados para implementar esta
funcionalidade, com o HAProxy a ser lançado em 2001 e o NGINX em
2002. Os utilizadores-alvo continuavam a ser as equipas de operações, mas
as competências necessárias significavam que os administradores de
sistemas que se sentiam confortáveis com a configuração de servidores Web
baseados em software estavam cada vez mais satisfeitos por assumir a
responsabilidade pelo que costumava ser uma preocupação de hardware.
BALANCEADORES DE CARGA DE SOFTWARE: AINDA
HOJE UMA ESCOLHA POPULAR
Embora ambos tenham evoluído desde o lançamento inicial, o NGINX e o HAProxy continuam a
ser amplamente utilizados e ainda são muito úteis para pequenas organizações e casos de
utilização simples de gateway de API (ambos também oferecem variantes comerciais mais
adequadas à implementação empresarial). A ascensão da Cloud (e da virtualização) cimentou o
papel dos equilibradores de carga de software e recomendamos que aprendas os conceitos básicos
desta tecnologia.
As redes de distribuição de conteúdo (CDNs), impulsionadas
principalmente pela necessidade de eliminar os gargalos de desempenho da
Internet, começaram a ser cada vez mais adotadas para descarregar as
solicitações dos servidores Web de origem. Os firewalls de aplicativos Web
(WAFs) também começaram a ser cada vez mais adotados, primeiro
implementados usando hardware especializado e, mais tarde, via software.
O projeto de código aberto ModSecurity e a integração dele com o Apache
Web Server, sem dúvida, impulsionaram a adoção em massa dos WAFs.
Meados dos anos 2000: Controladores de entrega de
aplicações (ADCs)
Em meados da década de 2000, continuou a assistir-se à crescente
penetração da Web na vida quotidiana. O aparecimento de telemóveis com
acesso à Internet apenas acelerou este fenómeno, com o BlackBerry
inicialmente a liderar o campo e tudo a ganhar maior velocidade com o
lançamento do primeiro iPhone em 2007. O navegador Web baseado em PC
continuava a ser o método de facto para aceder à Web e, em meados da
década de 2000, assistiu-se ao aparecimento da "Web 2.0", juntamente com
a adoção generalizada nos browsers da API XMLHttpRequest e da técnica
correspondente denominada Asynchronous JavaScript and XML (Ajax). Na
altura, esta tecnologia foi revolucionária. A natureza assíncrona da API
significava que já não era necessário devolver uma página HTML inteira,
analisá-la e atualizar completamente o ecrã com cada pedido. Ao dissociar a
camada de intercâmbio de dados da camada de apresentação, o Ajax
permitiu que as páginas Web alterassem o conteúdo dinamicamente sem a
necessidade de recarregar a página inteira.
Todas estas alterações colocaram novas exigências aos servidores Web e
aos equilibradores de carga para, mais uma vez, lidarem com mais carga,
mas também suportarem um tráfego mais seguro (SSL), cargas de dados
cada vez maiores (ricos em multimédia) e pedidos de prioridade diferentes,
o que levou ao aparecimento de controladores de entrega de aplicações
(ADC), um termo cunhado pelos intervenientes em redes existentes, como a
F5 Network+, a Citrix e a Cisco. Os ADCs forneciam suporte para
compressão, armazenamento em cache, multiplexagem de ligações,
modelação do tráfego e descarregamento de SSL, combinados com o
equilíbrio de carga. Os utilizadores-alvo eram, mais uma vez, engenheiros
de infra-estruturas, especialistas em redes e administradores de sistemas.
Em meados da década de 2000, quase todos os componentes de um edge
stack de gestão de tráfego moderno foram amplamente adoptados em toda a
indústria. No entanto, a implementação e o funcionamento de muitos dos
componentes estavam cada vez mais isolados entre as equipas. Se um
programador quisesse expor uma nova aplicação numa grande organização,
isso significava normalmente muitas reuniões separadas com os
fornecedores de CDN, as equipas de balanceamento de carga, as equipas
InfoSec e WAF e a equipa do servidor Web/aplicação. Se ainda tiver um
grande número de camadas na sua pilha de edge e estiver a migrar para a
Cloud ou para uma nova plataforma, agora é a altura de pensar
potencialmente nas soluções de compromisso com várias camadas e equipas
especializadas.
Início da década de 2010: Gateways de API de primeira
geração
Organizações como a Twilio estavam a perturbar as telecomunicações, com
o seu fundador, Jeff Lawson, a dizer que "Pegámos em todo o mundo
confuso e complexo da telefonia e reduzimo-lo a cinco chamadas de API."
A API do Google Ads estava a permitir aos criadores de conteúdos
rentabilizar os seus sites e a Stripe estava a permitir às grandes organizações
cobrar facilmente pelo acesso a serviços. Fundada no final de 2007, a
Mashape foi uma das primeiras pioneiras na tentativa de criar um mercado
de API para programadores. Embora esta visão exacta não tenha vingado
(sem dúvida que estava à frente do seu tempo, olhando agora para o
surgimento de soluções "sem código"/"low code"), um subproduto do
modelo de negócio da Mashape foi a criação do Kong API Gateway,
construído com base no OpenResty e na implementação NGINX de código
aberto. Outras implementações incluíram a WSO2 com o Cloud Services
Gateway, a Sonoa Systems com o Apigee e a Red Hat com o 3Scale
Connect.
Estas foram as primeiras tecnologias de ponta direcionadas para os
programadores, para além das equipas de plataformas e dos administradores
de sistemas. Um grande enfoque era a gestão do ciclo de vida de
desenvolvimento de software (SDLC) de uma API e o fornecimento de
funcionalidades de integração de sistemas, como pontos finais e conectores
de protocolo, e módulos de tradução. Devido à gama de funcionalidades
oferecidas, a grande maioria dos gateways de API de primeira geração foi
implementada em software. Surgiram portais para programadores em
muitos produtos, que permitiam aos engenheiros documentar e partilhar as
suas APIs de forma estruturada. Estes portais também forneciam controlos
de acesso, gestão de contas de utilizadores/desenvolvedores e controlos de
publicação e análise. A teoria era que isto permitiria a fácil monetização das
APIs e a gestão de "APIs como um produto".
Durante esta evolução da interação dos programadores na periferia, a
atenção centrou-se cada vez mais na parte HTTP da camada de aplicação
(camada 7) do modelo de Network+ OSI. As gerações anteriores de
tecnologias de periferia centravam-se frequentemente nos endereços IP e
nas portas, que operam principalmente na camada de transporte (camada 4)
do modelo OSI. Permitir que os programadores tomem decisões de
encaminhamento numa API gateway com base em metadados HTTP, como
o encaminhamento baseado no caminho ou o encaminhamento baseado no
cabeçalho, proporcionou a oportunidade de uma funcionalidade mais rica.
Havia também uma tendência emergente para a criação de arquitecturas
mais pequenas baseadas em serviços, que utilizavam algumas das ideias
presentes no SOA original, mas reformuladas utilizando tecnologias e
protocolos de implementação mais leves. As organizações estavam a extrair
aplicações autónomas de finalidade única das suas bases de código
monolíticas existentes, e alguns destes monólitos actuavam como gateway
de API, ou forneciam funcionalidades semelhantes a gateways de API,
como o encaminhamento e a autenticação. Com a primeira geração de
gateways de API, era frequente que as preocupações funcionais e
multifuncionais, como roteamento, segurança e resiliência, fossem
realizadas tanto na borda quanto nos aplicativos e serviços.
2015 em diante: Gateways de API de segunda geração
Em meados da década de 2010, assistiu-se à ascensão da próxima geração
de arquitecturas modulares e orientadas para os serviços, com o conceito de
"microsserviços" a entrar firmemente no zeitgeist em 2015, em grande parte
graças a organizações "unicórnio" como a Netflix, a AWS e a Spotify, que
partilharam as suas experiências de trabalho com estes padrões de
arquitetura. Além de os sistemas de back-end serem decompostos em
serviços mais numerosos e mais pequenos, os programadores também
estavam a adotar tecnologias de contentores baseadas no Linux LXC. O
Docker foi lançado em março de 2013 e o Kubernetes seguiu-se-lhe com
uma versão v1.0 em julho de 2015. A Netflix lançou seu gateway de API
baseado em JVM, o Zuul, em meados de 2013. O Zuul suportava a
descoberta de serviços para serviços de backend dinâmicos e também
permitia que scripts Groovy fossem injetados em tempo de execução para
modificar dinamicamente o comportamento. Esse gateway também
consolidou muitas preocupações transversais em um único componente de
borda, como autenticação, teste (lançamentos canários), limitação de taxa e
derramamento de carga, e observabilidade. O Zuul foi um gateway de API
revolucionário no espaço de microsserviços e, desde então, evoluiu para
uma segunda versão, e o Spring Cloud Gateway foi construído sobre ele.
Com a crescente adoção do Kubernetes e o lançamento de código aberto do
Envoy Proxy em 2016 pela equipe de engenharia da Lyft, muitos gateways
de API foram criados em torno dessa tecnologia, incluindo o Ambassador
Edge Stack (construído com base no CNCF Emissary-ingress), o Contour e
o Gloo Edge. Isso impulsionou ainda mais a inovação no espaço do
gateway de API, com a funcionalidade de espelhamento de Kong oferecida
pela próxima geração de gateways e outros gateways sendo lançados, como
Traefik, Tyk e outros.
CONFUSÃO NA CLOUD: GATEWAYS DE API, PROXIES
DE BORDAE CONTROLADORES DE ENTRADA
Como Christian Posta observou em sua postagem no blog "API
Gateways Are Going Through an Identity Crisis", há alguma confusão
sobre o que é um gateway de API em relação às tecnologias proxy que
estão sendo adotadas no domínio da computação em nuvem. De modo
geral, nesse contexto, um gateway de API permite alguma forma de
gerenciamento de APIs, desde uma funcionalidade simples do tipo
adaptador operando na camada de aplicação (camada 7 do OSI) que
fornece preocupações transversais fundamentais, até o gerenciamento
completo do ciclo de vida da API. Os proxies de borda são proxies de
tráfego de uso mais geral ou proxies reversos que operam nas camadas
de rede e transporte (camadas OSI 3 e 4, respetivamente), fornecem
preocupações transversais básicas e tendem a não oferecer
funcionalidade específica da API. "Controladores de entrada" são uma
tecnologia específica do Kubernetes que controla o tráfego que entra em
um cluster e como esse tráfego é tratado.
Os utilizadores-alvo da segunda geração de API gateways eram, em grande
medida, os mesmos que os da primeira geração, mas com uma separação
mais clara das preocupações e um maior enfoque no self-service do
programador. A passagem da primeira para a segunda geração de API
gateways assistiu a uma maior consolidação dos requisitos funcionais e
multifuncionais implementados na gateway. Embora se tenha tornado
amplamente aceite que os microsserviços devem ser construídos em torno
da ideia defendida por James Lewis e Martin Fowler de "smart endpoints e
dumb pipes", a adoção de pilhas de linguagens poliglotas significa que
surgiram "gateways de microsserviços" (mais pormenores na próxima
secção) que ofereciam funcionalidades transversais de uma forma agnóstica
em termos de linguagem.
Taxonomia atual do API Gateway
Como pode ser o caso com a terminologia na indústria de desenvolvimento
de software, muitas vezes não há um acordo exato sobre o que define ou
classifica um gateway de API. Há um amplo acordo em relação à
funcionalidade que esta tecnologia deve fornecer, mas diferentes segmentos
da indústria têm diferentes requisitos e, portanto, diferentes pontos de vista,
para um gateway de API. Isto levou ao surgimento e discussão de vários
subtipos de gateway de API. Nesta secção do capítulo, irá explorar a
taxonomia emergente de gateways de API e aprender sobre os seus
respectivos casos de utilização, pontos fortes e fracos.
Gateways empresariais tradicionais
O gateway de API empresarial tradicional é normalmente destinado ao caso
de uso de exposição e gerenciamento de APIs voltadas para o negócio. Esse
gateway também é frequentemente integrado a uma solução completa de
gerenciamento do ciclo de vida da API, pois esse é um requisito essencial
ao liberar, operar e monetizar APIs em escala. A maioria dos gateways
nesse espaço pode oferecer uma edição de código aberto, mas normalmente
há uma forte tendência de uso para a versão comercial/núcleo aberto do
gateway.
Estas gateways requerem normalmente a implementação e o funcionamento
de serviços dependentes, tais como armazenamentos de dados. Estas
dependências externas têm de ser executadas com elevada disponibilidade
para manter o funcionamento correto da gateway, o que deve ser tido em
conta nos custos de funcionamento e nos planos de DR/BC.
Microsserviços/Micro Gateways
O principal caso de utilização de um gateway de API de microsserviços, ou
gateway de micro API, é encaminhar o tráfego de entrada para APIs e
serviços de back-end. Em comparação com os gateways empresariais
tradicionais, não existem normalmente muitas funcionalidades para a gestão
dos ciclos de vida das APIs. Estes tipos de gateways estão frequentemente
disponíveis e com todas as funcionalidades como código aberto ou são
oferecidos como uma versão leve de um gateway empresarial tradicional.
Tendem a ser implantados e operados como componentes autónomos e,
muitas vezes, utilizam a plataforma subjacente (por exemplo, Kubernetes)
para a gestão de qualquer estado interno, como dados do ciclo de vida da
API, contagens de limitação de taxa e gestão de contas de consumidores da
API. Como os gateways de microsserviços são normalmente construídos
usando tecnologia de proxy moderna como o Envoy, as capacidades de
integração com service meshes (especialmente aquelas construídas usando a
mesma tecnologia de proxy) são normalmente boas.
Gateways de malha de serviço
O gateway de entrada ou de API incluído numa rede de serviços é
normalmente concebido para fornecer apenas a funcionalidade principal de
encaminhamento do tráfego externo para a rede. Por este motivo, carecem
frequentemente de algumas das funcionalidades empresariais típicas, como
a integração abrangente com soluções de autenticação e de fornecedores de
identidade, bem como a integração com outras funcionalidades de
segurança, como um WAF.
Este tipo de gateway também está implicitamente acoplado à malha de
serviço associada (e aos requisitos operacionais) e, por isso, se ainda não
estiveres a planear a implementação de uma malha de serviço, então esta
não é provavelmente uma boa primeira escolha de gateway de API.
Comparação de tipos de API Gateway
A Tabela 3-3 destaca a diferença entre os três tipos de gateway de API mais
amplamente implantados em seis critérios importantes.
Tabela 3-3. Comparação entre gateway de API empresarial, de
microsserviços e de malha de serviços
Gateway de API
Caso de empresarial Gateway de API de Gateway de rede de
utilização tradicional microsserviços serviços
Objetivo primário Expõe, compõe e gere Expõe, compõe e gere Expõe serviços internos
APIs empresariais serviços empresariais dentro da malha.
internas e serviços internos.
associados.
Funcionalidade de A equipa de gestão da A equipa de serviço A equipa de serviço
publicação API ou a equipa de regista/actualiza o regista/actualiza a malha
serviço regista/actualiza gateway através de e o gateway através de
o gateway através da código declarativo como código declarativo como
API de administração parte do processo de parte do processo de
(em organizações implementação. implementação.
maduras, isto é
conseguido através de
pipelines de entrega).
Monitorização Centra-se na Concentra-te no Concentra-te na
administração e nas programador, por plataforma, por exemplo,
operações, por exemplo, exemplo, latência, utilização, saturação,
mede as chamadas API tráfego, erros, saturação. erros.
por consumidor,
comunica erros (por
exemplo, 5XX interno).
Tratamento e Tratamento de erros L7 Tratamento de erros L7 Tratamento de erros L7
depuração de (por exemplo, página de (por exemplo, página de (por exemplo, página de
problemas erro personalizada). erro personalizada, erro personalizada ou
Para a resolução de failover ou carga útil). carga útil). Para a
problemas, executa a Para problemas de resolução de problemas,
gateway/API com depuração, configura configura uma
registo adicional e uma monitorização mais monitorização mais
problema de depuração detalhada e ativa o detalhada e/ou utiliza o
no ambiente de teste. sombreamento de "tapping" de tráfego para
tráfego e/ou o canarying ver e depurar a
para recriar o problema. comunicação específica
serviço-a-serviço.
Gateway de API
Caso de empresarial Gateway de API de Gateway de rede de
utilização tradicional microsserviços serviços
Testes Operar vários ambientes Permite o Facilita o
para QA, preparação e encaminhamento encaminhamento canário
produção. Testes de canário e o lançamento para testes dinâmicos.
integração escuro para testes
automatizados e dinâmicos. Utiliza os
implantação de API testes de contrato para a
fechada. Usar o gestão de actualizações.
versionamento de API
orientado ao
consumidor para
compatibilidade e
estabilidade (por
exemplo, semver).
Desenvolvimento Implanta o gateway Implementa o gateway Implanta a malha de
local localmente (via script localmente através da serviços localmente
de instalação, Vagrant plataforma de através da plataforma de
ou Docker) e tenta orquestração de serviços orquestração de serviços
mitigar as diferenças de (por exemplo, contentor (por exemplo,
infraestrutura com a ou Kubernetes). Kubernetes).
produção. Usa
estruturas de simulação
e stubbing de gateway
específicas do idioma.
Experiência do IU de administração Orientado por IaC ou IaC ou orientado para a
utilizador baseada na Web, portal CLI, com um portal de CLI, com um catálogo de
do desenvolvedor e desenvolvimento serviços limitado.
catálogo de serviços. simples e um catálogo
de serviços.
Estudo de caso: Evolução do sistema de
conferências utilizandoum gateway de API
Nesta seção do capítulo , aprenderá a instalar e configurar um gateway de
API para rotear o tráfego diretamente para o serviço Attendee que foi
extraído do sistema de conferência monólito. Isso demonstrará como é
possível usar o popular padrão "strangler fig",4 que é abordado com mais
detalhes em "Strangler Fig", para evoluir seu sistema de um monólito para
uma arquitetura baseada em microsserviços ao longo do tempo, extraindo
gradualmente partes de um sistema existente em serviços implantáveis e
executáveis de forma independente. A Figura 3-9 apresenta uma visão geral
da arquitetura do sistema de conferência com a adição de uma porta de
entrada API.
Figura 3-9. Usa um gateway de API para rotear para um novo serviço Attendee executado
independentemente do monólito
Muitas organizações iniciam essa migração extraindo serviços, mas fazem
com que a aplicação monolítica execute o roteamento e outras
preocupações transversais para os serviços executados externamente. Essa é
muitas vezes a escolha mais fácil, pois o monólito já tem que fornecer essa
funcionalidade para funções internas. No entanto, isso leva a um
acoplamento apertado entre o monólito e os serviços, com todo o tráfego
fluindo através da aplicação monolítica e a cadência de configuração
determinada pela frequência de implantação do monólito. Do ponto de vista
da gestão do tráfego, tanto o aumento da carga na aplicação monolítica
como o aumento do raio de explosão se esta falhar significam que o custo
operacional pode ser elevado. E estar limitado na atualização da informação
de encaminhamento ou na configuração transversal devido a um comboio
de lançamento lento ou a uma implementação falhada pode impedir a
iteração em velocidade. Por este motivo, geralmente não recomendamos a
utilização do monólito para encaminhar o tráfego desta forma,
particularmente se planear extrair muitos serviços numa escala de tempo
relativamente curta.
Desde que o gateway seja implementado para estar altamente disponível e
que os programadores tenham acesso direto (self-service) para gerir o
encaminhamento e a configuração, a extração e a centralização do
encaminhamento de aplicações e as preocupações transversais para um
gateway de API proporcionam segurança e rapidez. Vamos agora analisar
um exemplo prático de implementação de um gateway de API no sistema
de conferências e utilizá-lo para encaminhar para o novo serviço Attendee.
Instalando o Ambassador Edge Stack no Kubernetes
Como estás a implantar o sistema de conferência num cluster Kubernetes,
podes facilmente instalar um gateway de API usando as abordagens padrão
nativas do Kubernetes, como aplicar a configuração YAML ou usar Helm,
além de usar utilitários de linha de comando. Por exemplo, o gateway de
API do Ambassador Edge Stack pode ser instalado usando Helm. Depois de
implantares e configurares este gateway de API, podes facilmente adquirir
uma certificação TLS da LetsEncrypt seguindo o tutorial de configuração
do Host.
Com o gateway da API a funcionar e a fornecer uma ligação HTTPS, a
aplicação do sistema de conferência já não precisa de se preocupar em
terminar as ligações TLS ou em ouvir várias portas. Da mesma forma, a
autenticação e a limitação da taxa também podem ser facilmente
configuradas sem ter de reconfigurar ou implementar a sua aplicação.
Configuração de mapeamentos de caminhos de URL
para serviços de back-end
Tu podes agora usar um Ambassador Edge Stack Mapping Custom
Resource para mapear a raiz do teu domínio para o serviço
"conferencesystem" que escuta na porta 8080 e corre no namespace
"legacy" dentro do cluster Kubernetes. O metadata fornece um nome para o
Mapping, e o prefixo determina o caminho (a raiz "/" neste caso) que é
mapeado para o serviço alvo (com o formato service-
[Link]:port). Aqui está um exemplo:
---
apiVersion: [Link]/v3alpha1
kind: Mapping
metadata:
name: legacy-conference
spec:
hostname: "*"
prefix: /
rewrite: /
service: [Link]
Outro mapeamento pode ser adicionado para encaminhar qualquer tráfego
enviado para o caminho "/attendees" para o novo ("nextgen") microsserviço
de participantes que foi extraído do monólito. As informações incluídas no
mapeamento devem parecer familiares do exemplo anterior. Aqui, é
especificado um rewrite que "reescreve" o caminho prefix
correspondente nos metadados do URL antes de fazer a chamada para o
serviço Attendee de destino. Isso faz com que pareça ao serviço Attendee
que a solicitação foi originada com o caminho "/", eliminando efetivamente
a parte "/attendees" do caminho.
---
apiVersion: [Link]/v3alpha1
kind: Mapping
metadata:
name: legacy-conference
spec:
hostname: "*"
prefix: /attendees
rewrite: /
service: [Link]
Este padrão de criação de mapeamentos adicionais à medida que cada novo
microsserviço é extraído da aplicação legada pode continuar. Os prefixos
correspondentes podem ser aninhados (por
exemplo,/attendees/affiliation) ou usar expressões regulares
(por exemplo,/attendees/^[a-z].*").Eventualmente, a aplicação
legada torna-se uma pequena concha com apenas um punhado de funções, e
todas as outras funcionalidades são tratadas por microsserviços, cada um
com seu próprio mapeamento.
Configuração de mapeamentos usando roteamento
baseado em host
A maioria dos gateways da API também te permite realizar roteamento
baseado em host (por exemplo, host:
[Link]). Isso pode ser útil se você
precisar criar um novo domínio ou subdomínio para hospedar os novos
serviços. Um exemplo disso usando o Ambassador Edge Stack Mappings é
mostrado aqui:
---
apiVersion: [Link]/v3alpha1
kind: Mapping
metadata:
name: attendees-host
spec:
hostname: "[Link]"
prefix: /
service: [Link]
Muitos gateways de API modernos também suportam o encaminhamento
com base em caminhos ou cadeias de consulta. Quaisquer que sejam os seus
requisitos e as limitações da sua infraestrutura atual, deve ser capaz de
encaminhar facilmente tanto a sua aplicação existente como novos serviços.
EVITA O ENCAMINHAMENTO EM CARGAS ÚTEIS DE
PEDIDOS
Alguns gateways de API permitirão o roteamento com base no payload ou no corpo de uma
solicitação, mas isso geralmente deve ser evitado por dois motivos: primeiro, isso geralmente vaza
informações específicas de domínio altamente acopladas na configuração do gateway de API (por
exemplo, um payload geralmente está em conformidade com um esquema/contrato que pode ser
alterado na aplicação, com o qual o gateway precisará ser sincronizado), E segundo, pode ser
computacionalmente caro (e demorado) desserializar e analisar uma grande carga útil para extrair
as informações necessárias para roteamento.
Implantação de gateways de API:
Entendendo egerenciando falhas
Independentemente do padrão de implantação e do número de gateways
envolvidos em um sistema, um gateway de API normalmente está no
caminho crítico de muitas, se não de todas, as solicitações de usuários que
entram no seu sistema. Uma interrupção de um gateway implantado na
borda normalmente resulta na indisponibilidade de todo o sistema. E uma
interrupção de um gateway implantado mais a montante normalmente
resulta na indisponibilidade de algum subsistema central. Por esse motivo,
os tópicos de compreensão e gerenciamento de falhas de um gateway de
API são de vital importância.
API Gateway como um ponto único de falha
Em um sistema standard baseado na Web, o primeiro ponto único de falha
óbvio é normalmente o DNS. Embora este seja muitas vezes gerido
externamente, não há como evitar o facto de que, se falhar, o seu site ficará
indisponível. Os pontos únicos de falha seguintes serão normalmente os
balanceadores de carga globais e regionais da camada 4 e, dependendo da
localização e configuração da implementação, os componentes de
segurança, como a firewall ou o WAF.
Quanto maior for a funcionalidade da gateway, maior será o risco envolvido
e maior será o impacto de uma interrupção. Como uma gateway de API está
frequentemente envolvida numa versão de software, a configuração também
é continuamente actualizada. É fundamental ser capaz de detetar e resolver
problemas e mitigar quaisquer riscos.
DESAFIA OS PRESSUPOSTOS COM PONTOS ÚNICOS
DE FALHA DE SEGURANÇA
Dependendo do produto, da implementação e da configuração, alguns componentes de segurança
podem "falhar em aberto", ou seja, se o componente falhar, o tráfego será simplesmente
transferido para componentes a montante ou para o backend. Para alguns cenários em que a
disponibilidade é o objetivo mais importante, isso é desejado, mas para outros (por exemplo,
sistemas financeiros ou governamentais), isso provavelmente não é. Não deixe de desafiar as
suposições em sua configuração de segurança atual.
Detetar e assumir os problemas
A primeira etapa na deteção de problemas é garantir que recolhe e tem
acesso aos sinais apropriados do seu sistema de monitorização - ou seja,
dados de métricas, registos e rastreios. Qualquer sistema crítico deve ter
uma equipa claramente definida que o possua e seja responsável por
quaisquer problemas. As equipas devem comunicar os objectivos de nível
de serviço (SLOs), que podem ser codificados em acordos de nível de
serviço (SLAs) para clientes internos e externos.
LEITURA ADICIONAL: OBSERVABILIDADE, ALERTAS E
SRE
Se o conceito de observabilidade é novo para ti, recomendamos que aprendas mais sobre o método
de utilização, saturação e erros (USE) de Brendan Gregg, o método de taxa, erros e duração
(RED) de Tom Wilkie e os quatro sinais dourados de monitorização da Google. Se quiseres saber
mais sobre os objectivos e processos organizacionais associados, o livroGoogle Site Reliability
Engineering (SRE) é altamente recomendado.
Resolução de incidentes e problemas
Em primeiro lugar e acima de tudo, cada API gateway que opera no seu
sistema precisa de um proprietário que seja responsável se algo correr mal
com o componente. Numa organização mais pequena, isto pode ser os
programadores ou a equipa SRE que também são responsáveis pelos
serviços subjacentes. Numa organização maior, isto pode ser uma equipa de
infraestrutura dedicada. Como um gateway de API está no caminho crítico
dos pedidos, uma parte desta equipa proprietária deve estar de prevenção,
conforme apropriado (pode ser 24/7/365). A equipa de prevenção enfrentará
então a tarefa complicada de resolver o problema o mais rapidamente
possível, mas também de recolher informações suficientes (ou localizar e
colocar em quarentena sistemas e configurações) para saber o que correu
mal.
Após qualquer incidente, a organização deve esforçar-se por realizar uma
autópsia sem culpa e documentar e partilhar todas as aprendizagens. Esta
informação não só pode ser utilizada para evitar que o problema se repita,
como também pode ser muito útil para os engenheiros que estão a aprender
o sistema e para as equipas externas que lidam com tecnologias ou desafios
semelhantes.5
Mitigar os riscos
Qualquer componente que esteja no caminho crítico para lidar com as
solicitações dos usuários deve ter a maior disponibilidade possível em
relação ao custo e à complexidade operacional. Os arquitetos de software e
os líderes técnicos lidam com soluções de compromisso; esse tipo é um dos
mais desafiadores. No mundo dos gateways de API, a alta disponibilidade
geralmente começa com a execução de várias instâncias. Com instâncias
locais/co-lo, isso se traduz na operação de vários dispositivos de hardware
(redundantes), idealmente espalhados por locais separados. Na Cloud, isto
traduz-se em conceber e executar a instância do API gateway em várias
zonas de disponibilidade/centros de dados e regiões. Se for implementado
um equilibrador de carga (global) em frente das instâncias do API gateway,
este deve ser configurado adequadamente com verificações de saúde e
processos de failover que devem ser testados regularmente. Isto é
especialmente importante se as instâncias do API gateway forem
executadas nos modos de funcionamento ativo/passivo ou líder/nó.
Deves garantir que o processo de ativação pós-falha do balanceador de
carga para o gateway de API satisfaz todos os teus requisitos em relação à
continuidade do serviço. Os problemas mais comuns que ocorrem durante
os eventos de ativação pós-falha incluem
Problemas de gestão do estado do cliente utilizador, como o estado do
backend não ser migrado corretamente, o que provoca a falha de
sessões fixas
Desempenho fraco, uma vez que os clientes não são redireccionados
com base em considerações geográficas (por exemplo, os utilizadores
europeus são redireccionados para a costa oeste dos EUA quando está
disponível um centro de dados da costa leste)
Falha em cascata não intencional, como um componente de eleição de
líder defeituoso que resulta num impasse, o que faz com que todos os
sistemas backend se tornem indisponíveis
Armadilhas comuns na implementação do
API Gateway
Já viste que nenhuma tecnologia é uma bala de prata, mas, continuando
com o tema dos clichés tecnológicos, pode acontecer que quando se tem um
martelo tecnológico, tudo tende a parecer um prego.
Loopback do gateway da API
Assim como todas as armadilhas comuns, a implementação deste padrão
geralmente começa com boas intenções. Quando uma organização tem
apenas alguns serviços, isso normalmente não justifica a instalação de um
service mesh. No entanto, um subconjunto da funcionalidade do service
mesh é frequentemente necessário, particularmente a descoberta de
serviços. Uma implementação fácil é rotear todo o tráfego através do
gateway de borda ou API, que mantém o diretório oficial de todos os locais
de serviço. Nesta fase, o padrão se parece um pouco com um diagrama de
rede "hub and spoke". Os desafios se apresentam de duas formas: primeiro,
quando todo o tráfego de serviço para serviço está deixando a rede antes de
entrar novamente pelo gateway, isso pode apresentar problemas de
desempenho, segurança e custo (os fornecedores de Cloud geralmente
cobram pelo tráfego de saída e de zona de indisponibilidade); e segundo,
esse padrão não escala além de um punhado de serviços, pois o gateway
fica sobrecarregado e se torna um gargalo, tornando-se um verdadeiro ponto
único de falha. Esse padrão também pode adicionar complexidade à
observabilidade, pois vários ciclos podem dificultar a compreensão do que
aconteceu com cada chamada.
Qualquer tráfego externo, como solicitações de usuários, está sendo
corretamente encaminhado para os serviços de destino pelo gateway da
API. No entanto, como a aplicação herdada descobre a localização do
serviço Attendee? Muitas vezes, a primeira abordagem é encaminhar todas
as solicitações de volta através do gateway endereçável publicamente (por
exemplo, a aplicação herdada faz chamadas
[Link]/attendeesEm vez disso, a
aplicação herdada deve utilizar algum tipo de mecanismo interno de
descoberta de serviços e manter todos os pedidos internos dentro da
Network+. No próximo capítulo, aprenderás mais sobre como utilizar uma
malha de serviços para implementar este mecanismo.
API Gateway como um ESB
A grande maioria dos gateways de API suportam a extensão de sua
funcionalidade out-of-the-box através da criação de plug-ins ou módulos. O
NGINX suportava módulos Lua, que o OpenResty e o Kong capitalizaram.
O Envoy Proxy originalmente suportava extensões em C, e agora filtros
WebAssembly. E já discutimos como a implementação original do gateway
de API Zuul da Netflix suportava extensão através de scripts Groovy em
"2015 em diante: Gateways de API de segunda geração". Muitos dos casos
de uso realizados por esses plug-ins são extremamente úteis, como authn/z,
filtragem e logging. No entanto, pode ser tentador colocar a lógica de
negócios nesses plug-ins, que é uma maneira de acoplar altamente seu
gateway com seu serviço ou aplicativo. Isso leva a um sistema
potencialmente frágil, em que uma alteração em um único plug-in repercute
em toda a organização ou adiciona atrito adicional durante o lançamento,
em que o serviço de destino e o plug-in precisam ser implantados em
sincronia.
Tartarugas (API Gateways) até ao fundo
Se um gateway de API é bom, mais deve ser melhor, certo? É comum
encontrar vários gateways de API implantados no contexto de uma grande
organização, muitas vezes de forma hierárquica, ou em uma tentativa de
segmentar redes ou departamentos. As intenções são tipicamente boas: seja
para fornecer encapsulamento para linhas internas de negócios, ou para uma
separação de preocupações com cada gateway (por exemplo, "este é o
gateway de segurança de transporte, este é o gateway de registro..."), "A
armadilha comum surge quando o custo da mudança é demasiado elevado -
por exemplo, tem de se coordenar com um grande número de equipas de
gateway para lançar uma simples atualização de serviço, há problemas de
compreensão ("a quem pertence a funcionalidade de rastreio?") ou o
desempenho é afetado, uma vez que cada salto de rede incorre naturalmente
num custo .
Seleção de um API Gateway
Agora que aprendeste sobre a funcionalidade fornecida por um gateway de
API, a história da tecnologia e como um gateway de API se enquadra na
arquitetura geral do sistema, segue-se a pergunta de 1 milhão de dólares:
como selecionar um gateway de API para incluir na tua pilha?
Identificação de requisitos
Um dos primeiros passos de qualquer novo projeto de entrega de software
ou de infraestrutura é a identificação dos respectivos requisitos. Isto pode
parecer óbvio, mas é demasiado fácil distrairmo-nos com tecnologia
brilhante, marketing mágico ou boa documentação de vendas!
Pode consultar a secção anterior "Porquê utilizar um API Gateway?" deste
capítulo para explorar com mais pormenor os requisitos de alto nível que
deve considerar durante o processo de seleção. É importante fazer perguntas
que se concentrem nos pontos problemáticos actuais e também no seu
roteiro futuro.
Construir versus comprar
Uma discussão comum ao selecionar um gateway de API é o dilema
"construir versus comprar". Isso não é exclusivo desse componente de um
sistema de software, mas a funcionalidade oferecida por meio de um
gateway de API faz com que alguns engenheiros gravitem em torno disso -
que eles poderiam construir isso "melhor" do que os fornecedores
existentes, ou que sua organização é de alguma forma "especial" e se
beneficiaria de uma implementação personalizada. Em geral, acreditamos
que o componente de gateway de API está suficientemente bem
estabelecido para que seja melhor adotar uma implementação de código
aberto ou uma solução comercial em vez de construir a sua própria.
Apresentar o caso de construir versus comprar com tecnologia de entrega de
software poderia levar um livro inteiro e, por isso, nesta secção apenas
queremos destacar alguns desafios comuns:
Subestimação do custo total de propriedade (TCO)
Muitos engenheiros desconsideram o custo da engenharia de uma
solução, os custos de manutenção contínua e os custos operacionais
contínuos.
Não pensar no custo de oportunidade
A menos que sejas um fornecedor de Cloud ou de plataforma, é
altamente improvável que um gateway de API personalizado te
proporcione uma vantagem competitiva. Pode fornecer mais valor aos
seus clientes criando algumas funcionalidades mais próximas da sua
proposta de valor global.
Não ter conhecimento das soluções técnicas actuais dos produtos
Tanto o espaço dos componentes de plataforma de código aberto como
os comerciais evoluem rapidamente, e pode ser difícil mantermo-nos
actualizados. No entanto, esta é uma parte essencial do papel de um
líder técnico.
Diretrizes ADR: Seleção de um API Gateway
A Tabela 3-4 apresenta uma série de diretrizes ADR fundamentais que
podem ser utilizadas para o ajudar a decidir qual o API gateway a
implementar na sua organização ou projeto atual.
Tabela 3-4. Diretrizes do ADR: Seleção de uma lista de verificação de
gateway de API
Decisão Como devemos abordar a seleção de um gateway de API para a nossa
organização?
Pontos de discussão Identificámos e demos prioridade a todos os nossos requisitos associados à
seleção de um gateway de API?
Identificámos as soluções tecnológicas actuais que foram implementadas
neste espaço dentro da organização?
Conhecemos todos os constrangimentos da nossa equipa e da organização?
Já explorámos o nosso roteiro futuro em relação a esta decisão?
Calculámos honestamente os custos de "construir versus comprar"?
Explorámos o panorama tecnológico atual e estamos cientes de todas as
soluções disponíveis?
Consultámos e informámos todas as partes interessadas envolvidas na nossa
análise e tomada de decisões?
Recomendações Concentra-te especialmente nos teus requisitos para reduzir o acoplamento
API/sistema, simplificar o consumo, proteger as APIs da utilização excessiva
e abusiva, compreender como as APIs estão a ser consumidas, gerir as APIs
como produtos e rentabilizar as APIs.
As principais perguntas a fazer incluem: existe um gateway de API em uso?
Uma coleção de tecnologias foi montada para fornecer funcionalidade
semelhante (por exemplo, balanceador de carga de hardware combinado com
um aplicativo monólito que executa autenticação e roteamento no nível do
aplicativo)? Quantos componentes compõem atualmente sua pilha de borda
(por exemplo, WAF, LB, cache de borda, etc.)?
Concentra-se nos níveis de competências tecnológicas da sua equipa, na
disponibilidade de pessoas para trabalhar num projeto de gateway de API, nos
recursos e no orçamento disponíveis, etc.
É importante identificar todas as alterações de planeamento, novas
caraterísticas e objectivos actuais que possam ter impacto na gestão do tráfego
e nas outras funcionalidades que um gateway de API fornece.
Calcula o custo total de propriedade (TCO) de todas as implementações
actuais do tipo API gateway e potenciais soluções futuras.
Consulta analistas de renome, relatórios de tendências e análises de produtos
para compreenderes todas as soluções disponíveis atualmente.
A seleção e implementação de um gateway de API terá impacto em muitas
equipas e indivíduos. Não te esqueças de consultar os programadores, o QA, o
conselho de revisão da arquitetura, a equipa da plataforma, a InfoSec, , etc.
Resumo
Neste capítulo, aprendeste o que é um gateway de API e também exploraste
o contexto histórico que levou à evolução das funcionalidades atualmente
fornecidas por este componente essencial em qualquer pilha de software
baseada na Web:
Aprendeste como um gateway de API é uma ferramenta muito útil
para a migração e evolução de sistemas e puseste mãos à obra sobre
como utilizar um gateway de API para encaminhar para o serviço
Attendee que foi extraído do caso de utilização do sistema de
conferências.
Exploraste a taxonomia atual das API gateways e os seus modelos de
implementação, o que te permitiu pensar em como gerir potenciais
pontos únicos de falha numa arquitetura em que todo o tráfego de
utilizadores é encaminhado através de uma edge gateway.
Com base nos conceitos de gestão do tráfego na extremidade (entrada)
dos sistemas, aprendeste sobre a comunicação serviço-a-serviço e
como evitar armadilhas comuns, como a implementação de um
gateway de API como um barramento de serviços empresariais (ESB)
menos funcional.
A combinação de todo este conhecimento equipou-o com os principais
pontos de reflexão, restrições e requisitos necessários para fazer uma
escolha eficaz ao selecionar um gateway de API para os seus casos de
utilização actuais.
Tal como acontece com a maioria das decisões que um arquiteto de
software ou líder técnico tem de tomar, não existe uma resposta correta
distinta, mas muitas vezes podem existir algumas más soluções a
evitar.
Agora que já exploraste a funcionalidade que as API gateways fornecem
para gerir o tráfego de entrada norte-sul e as APIs relacionadas, o próximo
capítulo irá explorar o papel das service meshes para gerir o tráfego
serviço-a-serviço leste-oeste.
1 O livro de Cindy Sridharan, Distributed Systems Observability, da O'Reilly, é um excelente
manual para aprenderes mais sobre o tópico da observabilidade.
2 Vê, por exemplo, os cabeçalhos b3 do OpenZipkin.
3 Exemplos incluem o Apigee Edge e o 3Scale.
4 A opinião de Martin Fowler sobre StranglerFigApplication.
5 Se és novo neste espaço, o sítio Web " Learning from Incidents " é um ponto de partida
fantástico.
Capítulo 4. Service
Mesh:Gestão de tráfego de
serviço para serviço
Este trabalho foi traduzido com recurso a IA. Agradecemos o teu feedback e comentários:
translation-feedback@[Link]
No capítulo anterior, explorou a forma de expor as suas APIs e gerir o
tráfego de entrada associado dos utilizadores finais e de outros sistemas
externos de uma forma fiável, observável e segura, utilizando um gateway
de API. Agora vai aprender a gerir o tráfego para APIs internas, ou seja,
comunicação serviço-a-serviço, com objetivos semelhantes.
A um nível fundamental, as implementações de service mesh fornecem
funcionalidades para o encaminhamento, a observação e a segurança do
tráfego para a comunicação serviço-a-serviço. Vale a pena dizer que mesmo
esta escolha de tecnologia não é uma escolha fácil; como em todas as
decisões de arquitetura, há soluções de compromisso; não existe tal coisa
como um almoço grátis quando estás a desempenhar o papel de arquiteto!
Neste capítulo, irá desenvolver o estudo de caso, extraindo a funcionalidade
de tratamento de sessões do sistema de conferência legado para um novo
serviço Session voltado para o interior. Ao fazê-lo, irá aprender sobre os
desafios de comunicação introduzidos pela criação ou extração de novos
serviços e APIs que são implementados e executados juntamente com o
sistema de conferência monólito existente. Todas as técnicas de
gerenciamento de API e tráfego que você explorou no capítulo anterior
serão aplicadas aqui e, portanto, sua inclinação natural pode ser usar um
gateway de API para expor o novo serviço Session. No entanto, dados os
requisitos, isso provavelmente resultaria em uma solução abaixo do ideal. É
aqui que o padrão service mesh e as tecnologias associadas podem fornecer
uma abordagem alternativa.
O Service Mesh é a única solução?
Praticamente todas as aplicações de software baseadas na Web precisam de
fazer chamadas do tipo serviço-para-serviço, mesmo que se trate apenas de
uma aplicação monólita que interage com uma base de dados. Por este
motivo, há muito que existem soluções para gerir este tipo de comunicação.
A abordagem mais comum consiste em utilizar uma biblioteca específica da
linguagem, como uma biblioteca do kit de desenvolvimento de software
(SDK) ou um controlador de base de dados. Estas bibliotecas mapeiam as
chamadas baseadas na aplicação para pedidos de API de serviço e também
gerem o tráfego correspondente, normalmente através da utilização de
protocolos HTTP ou TCP/IP. Como a conceção das aplicações modernas
adoptou arquitecturas orientadas para os serviços, o espaço problemático
das chamadas serviço-a-serviço expandiu-se. É um requisito muito comum
que um serviço tenha de chamar a API de outro serviço para satisfazer um
pedido do utilizador. Para além de fornecer um mecanismo de
encaminhamento do tráfego, normalmente também é necessário ter
fiabilidade, observabilidade e segurança.
Como você aprenderá ao longo deste capítulo, tanto uma solução baseada
em biblioteca quanto em service mesh pode, muitas vezes, satisfazer seus
requisitos de comunicação serviço-a-serviço. Temos visto uma rápida
adoção de service meshes, particularmente dentro de um contexto
corporativo, e à medida que o número de consumidores e provedores
aumenta, é muitas vezes a opção mais escalável, sustentável e segura. Por
causa disso, focamos este capítulo principalmente no padrão service mesh.
Orientações: Deves adotar o Service Mesh?
A Tabela 4-1 fornece uma série de Diretrizes ADR para te ajudar a decidir
se deves adotar a tecnologia service mesh na tua organização.
Tabela 4-1. Diretriz ADR: Orientações para malhas ou bibliotecas de
serviços
Decisão Deves utilizar uma rede de serviços ou uma biblioteca para encaminhar o
tráfego de serviços?
Pontos de discussão Utilizas uma única linguagem de programação na tua organização?
Necessita apenas de um simples encaminhamento serviço-a-serviço para
comunicação do tipo REST ou RPC?
Tens requisitos multifuncionais que requerem funcionalidades mais
avançadas, como autenticação, autorização ou limitação de taxas?
Já tens uma solução implementada ou existe um mandato de toda a
organização que obriga a que todo o tráfego seja encaminhado através de
determinados componentes da tua rede?
Recomendações Se a sua organização exigir a utilização de uma única linguagem ou estrutura
de programação, pode normalmente tirar partido das bibliotecas ou
mecanismos específicos da linguagem para a comunicação serviço-a-serviço.
Utiliza sempre a solução mais simples para as tuas necessidades, tendo em
conta o futuro imediato e as necessidades conhecidas.
Se tiveres requisitos multifuncionais avançados, particularmente entre
serviços que utilizam diferentes linguagens de programação ou pilhas de
tecnologia, uma rede de serviços pode ser a melhor escolha.
Efectua sempre a devida diligência na tua organização relativamente a
mandatos, soluções e componentes existentes.
Estudo de caso: Extrair a funcionalidade das
sessões para um serviço
Para o estudo de caso da próxima evolução do nosso sistema de
conferências, centrar-te-ás nos pedidos dos proprietários de conferências
para apoiar uma nova funcionalidade essencial: Ver e gerir as sessões de
conferência de um participante através da aplicação móvel.
Trata-se de uma alteração importante que justificaria a criação de um ADR.
O quadro 4-2 apresenta um exemplo de ADR que poderia ter sido proposto
pela equipa de engenharia proprietária do sistema de conferência.
Tabela 4-2. ADR501 Separação de sessões do sistema de conferência
antigo
Estado Proposta
Contexto A equipa de marketing acredita que o envolvimento dos participantes na
conferência aumentará se estes puderem ver os detalhes e indicar o seu
interesse nas sessões da conferência através da aplicação móvel. A equipa de
marketing também quer poder ver quantos participantes estão interessados em
cada sessão.
Decisão A partir de agora, o componente "Sessão" será dividido num serviço
autónomo, o que permitirá o desenvolvimento da API em relação ao serviço
"Sessão" e a invocação da API a partir do serviço de conferência antigo.
Consequências Quando um utilizador quiser ver, adicionar ou remover sessões em que está
interessado numa conferência, o serviço Attendee terá de chamar o serviço
Session. Quando um administrador da conferência quiser ver quem está a
participar em cada sessão, o serviço Session terá de chamar o serviço
Attendee para determinar quem está a participar em cada sessão. O serviço
Session pode tornar-se um ponto único de falha na arquitetura e poderemos ter
de tomar medidas para atenuar o potencial impacto da execução de um único
serviço Session. Uma vez que a visualização e a gestão das sessões pelos
participantes aumentam drasticamente durante um evento de conferência em
direto, teremos também de ter em conta grandes picos de tráfego e,
potencialmente, um ou mais serviços Session a ficarem sobrecarregados ou a
funcionarem de forma degradada.
O modelo C4 que mostra a alteração arquitetónica proposta é apresentado
na Figura 4-1.
Figura 4-1. Modelo C4 que mostra a extração do serviço Session do sistema de conferência
Observe que, embora o novo serviço Session não precise ser exposto
externamente, é possível atender facilmente aos requisitos de roteamento e
confiabilidade declarados no ADR anterior, expondo esse serviço por meio
do gateway da API e configurando o sistema legado e o serviço Attendee
para chamar esse novo serviço por meio do endereço externo do gateway.
No entanto, esse seria um exemplo do antipadrão "loopback de gateway de
API" que você aprendeu em "Armadilhas comuns de implementação de
gateway de API". Esse antipadrão pode fazer com que o tráfego destinado
internamente saia da sua rede, o que tem implicações de desempenho,
segurança e custo (do fornecedor da Cloud). Vamos agora explorar como
uma malha de serviço pode ajudá-lo a atender aos seus novos requisitos,
evitando esse antipadrão .
O que é o Service Mesh?
Fundamentalmente, "service mesh" é um padrão para gerenciar toda a
comunicação serviço-a-serviço (ou aplicativo-aplicativo) dentro de um
sistema de software distribuído. Há muita sobreposição entre os padrões
service mesh e API gateway, sendo que as principais diferenças são duas.
Primeiro, as implementações do service mesh são otimizadas para lidar com
o tráfego serviço-a-serviço, ou leste-oeste, dentro de um cluster ou data
center. Segundo, seguindo isso, o originador da comunicação é tipicamente
um serviço interno (um pouco) conhecido, em vez de um dispositivo do
usuário ou um sistema executado externamente aos seus aplicativos.
SERVICE MESH NÃO É UMA REDE MESH
A rede mesh de serviços é não deve ser confundida com a rede mesh, que é uma topologia de rede
de nível inferior. A rede mesh está a tornar-se cada vez mais prevalecente no contexto da Internet
das Coisas (IoT) e também para a implementação de infra-estruturas de comunicações móveis em
cenários remotos ou difíceis (como a assistência em caso de catástrofe). As implementações da
rede mesh de serviços assentam em protocolos e topologias de rede existentes.
O padrão service mesh foca-se em fornecer gestão de tráfego (routing),
resiliência, observabilidade e segurança para a comunicação serviço-a-
serviço. Não te preocupes se ainda não ouviste falar muito sobre este
padrão, pois foi apenas em 2016 que a equipa da Buoyant cunhou o termo
para explicar a funcionalidade da sua tecnologia Linkerd.1 Isso, em
combinação com a introdução de outras tecnologias relacionadas, como a
Istio patrocinada pelo Google, levou à rápida adoção do termo "service
mesh" nos domínios da computação em Cloud, DevOps e arquitetura.
Tal como um gateway de API, um service mesh é implementado com dois
componentes fundamentais de alto nível: um plano de controlo e um plano
de dados. Num service mesh, estes componentes são sempre implementados
separadamente. O plano de controlo é onde os operadores interagem com o
service mesh e definem as rotas, as políticas e a telemetria necessária. O
plano de dados é o local onde ocorre todo o trabalho especificado no plano
de controlo e onde os pacotes de rede são encaminhados, as políticas são
aplicadas e a telemetria é emitida.
Se tomarmos como exemplo a configuração do tráfego serviço-a-serviço
dentro de um cluster Kubernetes, um operador humano definirá primeiro o
roteamento e a política usando a configuração de recursos personalizados -
por exemplo, em nosso estudo de caso, especificando que o serviço
Attendee pode chamar o serviço Session - e, em seguida, "aplicará" isso ao
cluster por meio de uma ferramenta de linha de comando, como kubectl, ou
pipeline de entrega contínua. Um aplicativo controlador de malha de
serviço em execução no cluster Kubernetes atua como o plano de controle,
analisando essa configuração e instruindo o plano de dados - normalmente
uma série de proxies "sidecar" em execução ao lado de cada um dos
serviços Attendee e Session - para executar isso.
MALHA DE SERVIÇO SIDECARS E PROXIES
No contexto de um service mesh, é frequente veres os termos "sidecars"
e "proxies" utilizados indistintamente. No entanto, isto não é
tecnicamente correto, uma vez que "sidecar" é um padrão de utilização
geral que é tipicamente implementado utilizando um proxy dentro de
um service mesh. Por conseguinte, qualquer utilização da palavra
"sidecar" deve também incluir o postfixo "proxy" (por exemplo,
"sidecar proxy"). O padrão sidecar é inspirado no sidecar da
motocicleta e consiste em segregar as funcionalidades de uma aplicação
ou serviço em uma série de processos separados que são executados
dentro da mesma rede e do mesmo espaço de nomes de processo. Na
arquitetura de software, um sidecar é anexado a uma aplicação pai e
estende/melhoria suas funcionalidades de uma forma frouxamente
acoplada. Este padrão permite que você adicione uma série de
capacidades à sua aplicação sem usar bibliotecas específicas de
linguagem ou outras técnicas. Você aprenderá mais sobre a evolução
deste padrão dentro das implementações de service mesh em "Evolução
do Service Mesh".
Todo o tráfego de serviço para serviço dentro do cluster Kubernetes é
roteado através dos proxies sidecar, normalmente de forma transparente
(sem que os aplicativos subjacentes reconheçam que um proxy está
envolvido), o que permite que todo esse tráfego seja roteado, observado e
protegido conforme necessário. Um exemplo de topologia dos serviços e do
plano de controle de malha de serviço e plano de dados é mostrado na
Figura 4-2.
Figura 4-2. Topologia dos serviços e plano de controlo e plano de dados de um service mesh
(utilizando o Istio como exemplo)
Qual é a funcionalidade de um Service
Mesh?
Em nível de rede, um proxy de malha de serviço atua como um proxy
completo, aceitando todo o tráfego de entrada de outros serviços e também
iniciando todas as solicitações de saída para outros serviços. Isso inclui
todas as chamadas de API e outras solicitações e respostas. Ao contrário de
um gateway de API, o mapeamento de um plano de dados de malha de
serviço para um serviço é normalmente um para um, o que significa que um
proxy de malha de serviço não agrega chamadas em vários serviços. Uma
rede de serviços fornece funcionalidades transversais, como a verificação
do utilizador, a limitação da taxa de pedidos e os tempos limite/retenções, e
pode fornecer métricas, registos e dados de rastreio para apoiar a
implementação da observabilidade no sistema. Esta é exatamente a
funcionalidade de que necessitamos para desenvolver o nosso estudo de
caso, extraindo o serviço Session e chamando-o a partir do sistema de
conferências antigo e do serviço Attendee.
AS MALHAS DE SERVIÇO USAM PROXIES
COMPLETOS PARA INTERCETAR TODO O TRÁFEGO
DE SERVIÇO
É comum que todos os proxies de serviço em malha operem como
"proxies completos", pois precisam observar e manipular todo o tráfego
que flui através da malha. Em contraste com um meio proxy, um proxy
completo lida com toda a comunicação entre o cliente e o servidor. Uma
diferença fundamental é que um proxy completo mantém duaspilhas de
rede distintas - uma no lado do cliente e outra no lado do servidor - e
faz proxy completo em ambos os lados. Com o proxy no meio de todas
as comunicações, é possívelmanipular, descartar, observar e fazer o que
for necessário para o tráfego em ambos os lados e em ambas as
direções. Esse poder e flexibilidade vêm, é claro, com uma solução de
compromisso, pois um proxy completo requer mais recursos e
potencialmente introduz mais sobrecarga/latência nas comunicações.
Embora menos comum em comparação com um gateway de API, algumas
malhas de serviços fornecem caraterísticas adicionais que permitem aos
programadores gerir o ciclo de vida de uma API. Por exemplo, um catálogo
de serviços associado pode ajudar na integração e gestão dos
programadores que utilizam as APIs de serviços, ou um portal de
programadores fornecerá a administração de contas e o controlo de acesso.
Algumas malhas de serviços também fornecem auditoria de políticas e
gestão de tráfego para cumprir os requisitos de governação empresarial .
Onde é implantado um Service Mesh?
Uma rede de serviços é implementada numa rede interna ou num cluster. Os
sistemas ou redes de grandes dimensões são normalmente geridos através
da implementação de várias instâncias de uma rede de serviços, muitas
vezes com cada rede única a abranger um segmento de rede ou um domínio
empresarial.
A MALHA DE SERVIÇO É IMPLANTADA NA BORDA?
Embora implantado dentro de um cluster, um service mesh pode expor
pontos de extremidade dentro de uma zona desmilitarizada de rede
(DMZ), ou para sistemas externos, ou redes ou clusters adicionais. Isso
é frequentemente implementado usando um proxy que é chamado de
"gateway de malha", "gateway de terminação" ou "gateway de
trânsito"."Esses tipos de gateways externos normalmente não fornecem
o nível de funcionalidade normalmente encontrado em um gateway de
API voltado para o exterior. Há algum debate sobre se o gerenciamento
de tráfego envolvendo esses gateways de malha de serviço é norte-sul
ou leste-oeste, e isso pode afetar os requisitos e as políticas de
segurança necessárias, etc.
A Figura 4-3 apresenta um exemplo de topologia de rede em malha de
serviço.
Figura 4-3. Uma topologia típica de service mesh, implantada em dois clusters (com setas sólidas
mostrando o tráfego de service mesh)
Como é que um Service Mesh se integra com
outras tecnologias de Network+?
Uma pilha de rede moderna pode ter muitas camadas, especialmente
quando se trabalha com tecnologias Cloud, em que a virtualização e o
sandboxing ocorrem em vários níveis. Uma malha de serviço deve
funcionar em harmonia com essas outras camadas de rede, mas os
desenvolvedores e operadores também precisam estar cientes de possíveis
interações e conflitos.A Figura 4-4 mostra a interação entre a infraestrutura
de rede física (e virtualizada), uma pilha de rede típica e uma malha de
serviço.
Figura 4-4. Modelo OSI mostrando que uma malha de serviço opera entre as camadas 3 e 7
Por exemplo, ao implantar aplicativos em um cluster Kubernetes, um
Serviço pode localizar e endereçar outro Serviço dentro do mesmo cluster
por meio de um nome prescrito que mapeia para um endereço IP. Políticas
fundamentais de segurança de controle de tráfego podem ser implementadas
com NetworkPolicies, que controla o tráfego no nível do endereço IP
e da porta (camada OSI 3 ou 4), e controles de política adicionais são
frequentemente fornecidos pelo plug-in Container Networking Interface
(CNI) de um cluster.2
As malhas de serviço podem substituir a resolução e o encaminhamento
padrão de endereços IP para serviço da CNI e também fornecer
funcionalidade adicional. Isso inclui encaminhamento transparente entre
clusters, aplicação de segurança de camada 3/4 e 7 (como identidade e
autorização do usuário), balanceamento de carga de camada 7 (que é útil se
você estiver usando o protocolo keepalive multiplexado como gRPC ou
HTTP/2) e observabilidade no nível de serviço a serviço e em toda a pilha
de rede.
Porquê utilizar uma rede de serviços?
De uma forma semelhante a decidir porque deve implementar um gateway
de API na sua arquitetura existente, determinar porque adotar um service
mesh é um tópico multifacetado. É necessário equilibrar os ganhos e custos
de implementação a curto prazo com os requisitos de manutenção a longo
prazo. Existem muitas preocupações transversais relacionadas com a API
que pode ter para cada um ou todos os seus serviços internos, incluindo a
gestão do ciclo de vida do produto (lançamento incremental de novas
versões de um serviço), fiabilidade, suporte de comunicação multilingue,
observabilidade, segurança, manutenção e extensibilidade.
Esta secção do capítulo dá-te uma visão geral dos principais problemas que
uma malha de serviço pode resolver, tais como:
Permitir um controlo fino do encaminhamento de serviços, da
fiabilidade e da gestão do tráfego
Melhora a observabilidade das chamadas interserviços
Aplica a segurança, incluindo encriptação de transporte, autenticação
eautorização
Apoia os requisitos de comunicação multifuncional numa variedade
delínguas
Gestão separada do tráfego de entrada e de serviço a serviço
Controlo detalhado do encaminhamento, fiabilidade e
gestão do tráfego
Roteamento de tráfego com um sistema distribuído baseado em
microsserviços pode ser mais desafiador do que parece à primeira vista.
Normalmente, haverá várias instâncias de um serviço implantado em um
ambiente com o objetivo de melhorar o desempenho (balanceamento de
carga entre os serviços) e a confiabilidade (fornecendo redundância). Além
disso, muitas plataformas de infraestrutura modernas são construídas em
"hardware de commodity" que se manifesta como recursos de computação
efêmeros que podem desligar, reiniciar ou desaparecer a qualquer momento;
e isso significa que a localização de um serviço pode mudar no dia a dia (ou
minuto a minuto!).
É claro que pode empregar as tecnologias de encaminhamento e as técnicas
associadas que aprendeu no Capítulo 3. O desafio aqui é que existem
normalmente muitos mais serviços internos e APIs em comparação com o
número de APIs externas que são expostas pelas suas aplicações, e o ritmo
de mudança com os sistemas internos e as suas APIs e funcionalidades
correspondentes é frequentemente muito mais elevado. Por conseguinte, o
custo operacional aumentaria drasticamente se implantasse um gateway de
API em frente de cada serviço interno, tanto no que diz respeito aos
recursos de computação necessários como aos custos de manutenção
humana.
Encaminhamento transparente e normalização do nome do
serviço
Fundamentalmente, roteamento é o processo de seleção de um caminho
para o tráfego em uma rede ou entre ou através de várias redes. Dentro de
aplicativos da Web, o roteamento no nível da rede tem sido normalmente
tratado dentro da pilha TCP/IP e da infraestrutura de rede associada (na
camada 3/4 do modelo OSI). Isso significa que apenas o endereço IP e a
porta do destino e do originador da conexão são necessários. Antes da
Cloud, e muitas vezes com centros de dados no local, os endereços IP dos
serviços internos são frequentemente fixos e bem conhecidos. Embora o
DNS seja amplamente utilizado para mapear nomes de domínio para
endereços IP, ainda é o caso de aplicações e serviços herdados utilizarem
endereços IP codificados. Isto significa que quaisquer alterações à
localização de um serviço requerem uma reimplantação de todos os
serviços que chamam este serviço.
Com a adoção da Cloud e a natureza efémera da nossa infraestrutura que a
acompanha, os endereços IP das instâncias de computação e os seus
serviços correspondentes mudam regularmente. Isto, por sua vez, significa
que se codificarmos os endereços IP e de porta, estes terão de ser alterados
com frequência. À medida que as arquitecturas baseadas em microsserviços
se tornaram mais populares, a dor da reimplementação aumentou em
relação ao número de serviços dentro de uma aplicação. Os primeiros
utilizadores de microsserviços criaram soluções para ultrapassar isto,
implementando diretórios ou registos externos de "descoberta de serviços"
que contêm um mapeamento dinâmico de nomes de serviços para endereços
IP e portas.3
Os service meshes podem lidar com essa pesquisa dinâmica do nome do
serviço para o local, externamente ao serviço e também de forma
transparente, sem a necessidade de modificação do código, reimplantações
ou reinicializações. Outro benefício de um service mesh é que ele pode
normalizar a nomenclatura entre ambientes usando a "consciência do
ambiente" em combinação com a configuração armazenada externamente
ao aplicativo. Por exemplo, um service mesh implantado em "produção"
reconhecerá que está sendo executado nesse ambiente. A malha de serviço
mapeará de forma transparente o nome do serviço em nível de código
sessions-service para o local específico do ambiente AWS-us-
east-1a/prod/sessions/v2, procurando o local em um registro de
serviço (que pode ser integrado à malha ou executado externamente). O
mesmo código implantado no ambiente de teste com uma malha de serviço
configurada adequadamente irá rotear sessions-service para
internal-staging-server-a/stage/sessions/v3.
Fiabilidade
A natureza efémera da computação moderna e dos ambientes de cluster traz
desafios relacionados com a fiabilidade, para além das alterações de
localização. Por exemplo, cada serviço tem de lidar corretamente com
problemas de comunicação com outro serviço com o qual está a interagir.
Você aprenderá mais sobre "As 8 Falácias da Computação Distribuída" em
breve, mas os problemas a serem observados neste contexto incluem a
interrupção da conexão de um serviço, um serviço que se torna
temporariamente indisponível ou um serviço que responde lentamente.
Esses desafios podem ser tratados no código usando padrões de
confiabilidade bem conhecidos, como novas tentativas, timeouts,
disjuntores, anteparos e fallbacks. O livro Release It! Design and Deploy
Production-Ready Software, agora em sua segunda edição, fornece um guia
abrangente de exploração e implementação. No entanto, como explorarás
com mais profundidade em "Suportar a comunicação multifuncional entre
linguagens", tentar implementar esta funcionalidade no código
normalmente leva a um comportamento inconsistente, especialmente em
diferentes linguagens e plataformas.
Dependendo da implementação, um service mesh também pode detetar
problemas e partilhar esta informação através do mesh, permitindo que cada
serviço dentro do mesh tome as decisões apropriadas sobre como
encaminhar o tráfego - por exemplo, se a latência de resposta de um serviço
estiver a aumentar, todos os serviços que chamem o serviço alvo podem ser
instruídos a iniciar as suas acções de recurso.
Para o estudo de caso, uma malha de serviço permitirá definir como lidar
com quaisquer falhas ao comunicar com o novo serviço Session. Imagina
que vários milhares de participantes num evento acabaram de assistir à
apresentação da conferência da manhã e querem ver o seu horário para o
dia. Este pico súbito de tráfego para o serviço Session pode resultar num
comportamento degradado. Para a maioria dos casos de utilização,
definirias tempos limite e novas tentativas adequados, mas também podes
definir uma ação de interrupção de circuito que desencadeia um
comportamento da aplicação. Por exemplo, se uma chamada de API do
serviço Attendee para o serviço Session para obter o horário da sessão
diária de um participante falhar repetidamente, podes acionar um disjuntor
na malha do serviço que falha rapidamente todas as chamadas para este
serviço (para permitir que o serviço recupere). Muito provavelmente, na
aplicação móvel, lidarias com esta falha "recuando" para apresentar todo o
horário da sessão da conferência em vez de um horário pessoal .
Encaminhamento avançado de tráfego: Modelação,
policiamento, divisão e espelhamento
Desde o boom das empresas ponto-com, no final dos anos 90, as aplicações
web de consumo têm lidado cada vez mais com mais utilizadores e mais
tráfego. Os utilizadores também se tornaram mais exigentes, tanto no que
diz respeito ao desempenho como às funcionalidades oferecidas.
Consequentemente, a necessidade de gerir o tráfego para satisfazer as
necessidades de segurança, desempenho e lançamento de funcionalidades
tornou-se mais importante. Como aprendeu em "Como é que um API
Gateway se integra com outras tecnologias no Edge?", a borda da rede viu o
surgimento de appliances dedicados para atender a esses requisitos, mas
essa infraestrutura não era apropriada para ser implantada na frente de cada
serviço interno. Nesta seção do capítulo, você aprenderá mais sobre os
requisitos que se tornaram típicos para um aplicativo baseado em
microsserviços em relação à modelagem e ao policiamento do tráfego
interno.
Modelação do tráfego
Traffic shaping é uma técnica de gestão de largura de banda que atrasa parte
ou a totalidade do tráfego de rede de modo a corresponder a um perfil de
tráfego desejado. O traffic shaping é utilizado para otimizar ou garantir o
desempenho, melhorar a latência ou aumentar a largura de banda utilizável
para alguns tipos de tráfego, atrasando outros tipos. O tipo mais comum de
traffic shaping é o traffic shaping baseado em aplicações, em que as
ferramentas de fingerprinting são usadas primeiro para identificar
aplicações de interesse, que são então sujeitas a políticas de shaping. Com o
tráfego leste-oeste, um service mesh pode gerar ou monitorar as
fingerprints, como a identidade do serviço ou algum outro proxy para isso,
ou um cabeçalho de solicitação contendo metadados relevantes - por
exemplo, se uma solicitação foi originada de um usuário de camada livre de
aplicação de conferência ou de um cliente pagante.
Policiamento do tráfego
Policiamento de tráfego é o processo de monitorar o tráfego da rede para
verificar a conformidade com uma política ou contrato de tráfego e tomar
medidas para fazer cumprir esse contrato. O tráfego que viola uma política
pode ser descartado imediatamente, marcado como não conforme ou
deixado como está, dependendo da política administrativa. Essa técnica é
útil para evitar que um serviço interno com mau funcionamento cometa um
ataque de negação de serviço (DoS) ou para evitar que um recurso interno
crítico ou frágil fique excessivamente saturado com o tráfego (por exemplo,
um armazenamento de dados), Antes do advento das tecnologias de nuvem
e service meshes, o policiamento de tráfego dentro das redes internas
geralmente só era implementado dentro de um contexto empresarial usando
hardware especializado ou dispositivos de software, como um barramento
de serviços empresariais (ESB). A computação em nuvem e as redes
definidas por software (SDNs) tornaram as técnicas de policiamento de
tráfego mais fáceis de serem adotadas por meio do uso de grupos de
segurança (SGs) e listas de controle de acesso à rede (NACLs).
Ao gerir as comunicações este-oeste, os serviços dentro do limite da rede ou
do cluster podem ter conhecimento de um contrato de tráfego e podem
aplicar a modelação de tráfego internamente para garantir que a sua saída se
mantém dentro do contrato. Por exemplo, o serviço Attendee pode
implementar um limitador de taxa interno que impede chamadas excessivas
à API do serviço Session dentro de um período de tempo específico.
A malha de serviço permite o controlo granular da modelação, divisão e
espelhamento do tráfego, o que torna possível mudar ou migrar
gradualmente o tráfego de uma versão de um serviço alvo para outra. Em
"Estratégias de lançamento", veremos como esta abordagem pode ser
utilizada para facilitar a separação entre a construção e o lançamento de
estratégias de lançamento baseadas no tráfego.
Proporciona uma observabilidade transparente
Quando opera qualquer sistema distribuído, como uma aplicação baseada
em microsserviços, a capacidade de observar a experiência do utilizador
final e os componentes internos arbitrários é de importância vital para a
identificação de falhas e a depuração dos problemas correspondentes.
Historicamente, a adoção da monitorização em todo o sistema exigia a
integração de agentes ou bibliotecas de tempo de execução altamente
acoplados nas aplicações, o que exigia uma implementação de todas as
aplicações durante o lançamento inicial e todas as actualizações futuras.
Um service mesh pode fornecer parte da observabilidade necessária,
particularmente métricas de aplicação (L7) e de rede (L4), e fazê-lo de
forma transparente. Uma atualização correspondente de qualquer
componente de coleta de telemetria ou do próprio service mesh não deve
exigir uma reimplantação de todas as aplicações. É claro que há limitações
para a observabilidade que uma malha de serviço pode fornecer, e você
também deve instrumentar seus serviços usando métricas específicas do
idioma e bibliotecas emissoras de log. Por exemplo, em nosso estudo de
caso, a malha de serviço forneceria métricas sobre o número, a latência e a
taxa de erro das chamadas à API do serviço Session, e você também
decidiria registrar métricas específicas do negócio e KPIs das chamadas à
API.
Aplica a segurança: Segurança de transporte,
autenticaçãoe autorização
Em grande parte da mesma forma que a observabilidade, a segurança da
comunicação serviço-a-serviço tem sido historicamente implementada
utilizando bibliotecas específicas da linguagem. Estas abordagens altamente
acopladas apresentam as mesmas desvantagens e nuances. Por exemplo, a
implementação de encriptação ao nível do transporte numa rede interna é
um requisito relativamente comum, mas diferentes bibliotecas de linguagem
tratam a gestão de certificados de forma diferente, o que aumentou a carga
operacional da implementação e rotação de certificados. A gestão da
identidade do serviço (máquina) e do utilizador (humano) para autenticação
e autorização também era difícil em diferentes linguagens. Também era
frequentemente fácil contornar acidentalmente (ou deliberadamente)
qualquer implementação de segurança não incluindo as bibliotecas
necessárias.
Como o plano de dados de um service mesh está incluído no caminho de
qualquer tráfego dentro do sistema, é relativamente trivial impor o perfil de
segurança exigido. Por exemplo, o plano de dados do service mesh pode
gerenciar identidades de serviço (por exemplo, usando SPIFFE) e
certificados criptográficos, permitindo mTLS e autenticação e autorização
em nível de serviço. Isso nos permite implementar facilmente o mTLS em
nosso estudo de caso sem a necessidade de modificações no código.
Apoiar a comunicação interfuncional em várias línguas
À medida que cria ou extrai serviços dentro de uma aplicação baseada em
microsserviços e passa da comunicação dentro do processo para a
comunicação fora do processo, é necessário pensar em alterações no
encaminhamento, fiabilidade, observabilidade e segurança. A
funcionalidade necessária para lidar com isto pode ser implementada no
código da aplicação, por exemplo, como uma biblioteca. No entanto, se a
aplicação ou o sistema utilizar várias linguagens de programação - e uma
abordagem poliglota é bastante comum nos sistemas baseados em
microsserviços - isto significa que terá de implementar cada biblioteca para
cada linguagem utilizada. Como um service mesh é tipicamente
implementado usando o padrão sidecar, em que toda a comunicação do
serviço é encaminhada através de um proxy de rede externo ao serviço, mas
executado dentro do mesmo namespace de rede, a funcionalidade
necessária pode ser implementada uma vez dentro do proxy e reutilizada em
todos os serviços. Podes pensar nisto como "injeção de dependência de
infraestrutura". No nosso estudo de caso, isto permitir-nos-ia reescrever o
nosso serviço Attendee usando uma linguagem diferente (talvez para
satisfazer novos requisitos de desempenho) e ainda contar com os aspectos
multifuncionais da comunicação serviço-a-serviço a serem tratados de
forma consistente.
Separação da gestão do tráfego de entrada e de serviço
a serviço
Lembra-te de em "Estudo de Caso: De um modo geral, o tráfego norte-sul é
o tráfego que entra no seu sistema a partir de um local externo. O tráfego
leste-oeste transita internamente de sistema para sistema ou de serviço para
serviço. As definições podem tornar-se complicadas quando se aprofunda a
definição de "os seus sistemas"; por exemplo, esta definição estende-se a
sistemas concebidos e operados apenas pela sua equipa, pelo seu
departamento, pela sua organização ou por terceiros de confiança, etc.
Vários contribuintes para o espaço das API, incluindo Marco Palladino de
Kong, argumentaram que a utilização de norte-sul e este-oeste é em grande
parte irrelevante e é mais um problema da geração anterior de redes de
computadores, quando as fronteiras entre sistemas eram mais claras.
Exploraremos este argumento com mais pormenor no Capítulo 9, uma vez
que aborda a ideia de API como um produto (incluindo a gestão do ciclo de
vida da API) e a conetividade de serviços das camadas 7 e 4 (do modelo
OSI de rede). As diferenças entre as principais propriedades e caraterísticas
do tráfego de entrada e de serviço para serviço são apresentadas na Tabela
4-3.
Tabela 4-3. Diferenças entre propriedades de entrada e de serviço a serviço
Entrada (n/s) Serviço a serviço (e/w)
Fonte de tráfego Externo (utilizador, terceiros, Interno (dentro dos limites do fundo)
Internet)
Destino do tráfego API ou sítio Web público ou API de serviço ou domínio
orientado para a empresa
Autenticação "utilizador" (entidade do mundo "serviço" (entidade máquina) e "utilizador"
real) focado (entidade do mundo real)
Autorização funções de "utilizador" ou nível Identidade do "serviço" ou segmento de
de capacidade rede focado, e funções do "utilizador" ou
nível de capacidade
TLS Unidirecional, muitas vezes Mútuo, pode ser tornado obrigatório
imposta (por exemplo, (mTLS estrito)
atualização de protocolos)
Implementações API gateway, proxy invertido Malha de serviços, bibliotecas de
primárias aplicações
Proprietário Equipa de Equipa de plataforma/cluster/operações
principal gateway/networking/ops
Utilizadores Arquitectos, gestores de API, Desenvolvedores
organizacionais programadores
Como ilustrado, as propriedades e os requisitos associados à gestão dos dois
tipos de tráfego são muitas vezes bastante diferentes. Por exemplo, o
tratamento do tráfego externo do utilizador final destinado a uma API do
produto tem requisitos fundamentalmente diferentes do tratamento do
tráfego interno serviço-a-serviço destinado a uma API interna da empresa,
do domínio ou do componente. Na prática, isto significa que os planos de
controlo de uma API gateway e de um service mesh têm de oferecer
capacidades diferentes para suportar a configuração dos respectivos planos
de dados. Por exemplo, no nosso estudo de caso, a equipa de
desenvolvimento do serviço Session pode querer especificar que o serviço
só pode ser chamado pela aplicação de conferência antiga e pelo serviço
Attendee, ao passo que a equipa do serviço Attendee não especificaria quais
os sistemas externos que podem ou não chamar a API pública - isto seria da
responsabilidade da equipa de gateway ou de rede associada.
Esta diferença entre a gestão de chamadas de API de entrada e de serviço
para serviço pode ser melhor compreendida se comparar a evolução e a
utilização da tecnologia de gateway de API, conforme explorado em "Uma
história moderna dos gateways de API", com a evolução da tecnologia de
service mesh, conforme descrito na secção seguinte .
Evolução do Service Mesh
Embora o termo "service mesh" tenha sido cunhado em 2016, várias das
primeiras organizações "unicórnio", como Twitter, Netflix, Google e
Amazon, estavam criando e usando tecnologias relacionadas em suas
plataformas internas desde o final dos anos 2000 e início dos anos 2010.
Por exemplo, o Twitter criou seu framework Finagle RPC baseado em
Scala, que foi aberto em 2011. A Netflix criou e lançou suas bibliotecas
compartilhadas de microsserviços baseadas em Java "OSS" em 2012,
incluindo Ribbon, Eureka e Hystrix.4 Mais tarde, a equipa da Netflix lançou
o sidecar Prana para permitir que os serviços não baseados em JVM
tirassem partido destas bibliotecas. A criação das bibliotecas Finagle e a
adoção de sidecars acabaram por dar origem ao Linkerd, indiscutivelmente
o primeiro service mesh baseado em sidecar e também um projeto inicial no
CNCF quando esta fundação foi formada. A Google seguiu rapidamente o
exemplo lançando o service mesh Istio que se baseou no projeto Envoy
Proxy que tinha surgido da equipa de engenharia da Lyft.
Numa reviravolta que parece ser o círculo completo da indústria, as
capacidades do service mesh estão a ser empurradas de volta para as
bibliotecas partilhadas, como estamos a ver com o gRPC, ou adicionadas ao
kernel do SO. Esta evolução pode ser vista na Figura 4-5. Embora o
desenvolvimento e a utilização de muitos destes componentes e plataformas
anteriores estejam agora obsoletos, é útil fazer uma rápida visita à sua
evolução, uma vez que esta destaca vários desafios e limitações da
utilização do padrão service mesh, alguns dos quais ainda permanecem.
Figura 4-5. Evolução da tecnologia service mesh
História e motivações iniciais
Nos anos 90, Peter Deutsch e outros da Sun Microsystems compilaram
"The 8 Fallacies of Distributed Computing" (As 8 Falácias da Computação
Distribuída), em que enumeram os pressupostos que os engenheiros tendem
a fazer quando trabalham com sistemas distribuídos:
A rede é fiável
A latência é zero
A largura de banda é infinita
A rede é segura
A topologia não se altera
Existe um administrador
O custo de transporte é zero
A rede é homogénea
Peter e a sua equipa afirmam que estas falácias "provam ser todas falsas a
longo prazo e todas causam grandes problemas e experiências de
aprendizagem dolorosas".
IGNORA AS FALÁCIAS DA COMPUTAÇÃO DISTRIBUÍDA
POR TUA CONTA E RISCO!
Como as "8 Falácias da Distribuição da Computação" foram cunhadas nos anos 90, é tentador
pensar nelas como uma relíquia da computação. No entanto, isso seria um erro! Tal como muitas
das outras leis e padrões de computação intemporais derivados dos anos 70 e 80, as questões
permanecem as mesmas, mesmo com as mudanças tecnológicas. Ao trabalhares na função de
arquiteto, deves lembrar constantemente às tuas equipas que muitos dos desafios de Network+
capturados nestas falácias se mantêm actuais e deves conceber os sistemas em conformidade!
À medida que os sistemas distribuídos e as arquiteturas de microsserviços
se tornaram populares na década de 2010, muitos inovadores no espaço,
como James Lewis, Sam Newman e Phil Calçado, perceberam a
importância de construir sistemas que reconhecessem e compensassem
essas falácias além da funcionalidade fornecida nas pilhas de rede padrão.
Com base no conjunto inicial de "Pré-requisitos de microsserviços" de
Martin Fowler, Phil criou os "Pré-requisitos de microsserviços de Calçado"
e incluiu o "RPC padronizado" como um pré-requisito-chave que
encapsulava muitas das lições práticas que ele havia aprendido com as
falácias da computação distribuída. No seu último post de blogue de 2017,
Phil afirmou que "embora a pilha TCP/IP e o modelo geral de rede
desenvolvido há muitas décadas ainda sejam uma ferramenta poderosa para
fazer com que os computadores falem uns com os outros, as arquitecturas
mais sofisticadas [baseadas em microsserviços] introduziram outra camada
de requisitos que, mais uma vez, têm de ser cumpridos pelos engenheiros
que trabalham nessas arquitecturas."5
Padrões de implementação
Embora a implementação mais difundida de service meshes atualmente
utilize o modelo de implantação "sidecar" baseado em proxy, esse nem
sempre foi o caso. E pode não ser o caso no futuro. Nesta seção do capítulo,
você aprenderá como os padrões de implementação de service mesh
evoluíram até agora e explorará o que o futuro pode reservar.
Bibliotecas
Embora muitos líderes técnicos tenham percebido a necessidade de uma
nova camada de funcionalidade de rede dentro dos sistemas baseados em
microsserviços, eles entenderam que a implementação dessas tecnologias
não seria trivial. Eles também reconheceram que muito esforço seria
repetido, tanto dentro quanto entre as organizações. Isso levou ao
surgimento de estruturas de rede focadas em microsserviços e bibliotecas
compartilhadas que poderiam ser construídas uma vez e reutilizadas,
primeiro em uma organização e, mais tarde, com código aberto paraum
consumo mais amplo.
No post do blogue acima mencionado, Phil Calçado comentou que mesmo a
funcionalidade central de rede, como a descoberta de serviços e a
interrupção de circuitos, era difícil de implementar corretamente, o que
levou à criação de bibliotecas grandes e sofisticadas, como a Finagle do
Twitter e a pilha OSS da Netflix, que se tornaram muito populares como
forma de evitar reescrever a mesma lógica em todos os serviços e também
como projectos para concentrar esforços partilhados na garantia da
correção. Algumas organizações mais pequenas assumiram o encargo de
escrever as bibliotecas e ferramentas de rede necessárias, mas o custo era
tipicamente elevado, especialmente a longo prazo. Por vezes, este custo era
explícito e claramente visível - por exemplo, o custo dos engenheiros
afectos a equipas dedicadas à construção de ferramentas. Mas, mais
frequentemente, a verdadeira despesa era difícil de quantificar totalmente,
uma vez que se manifesta como o tempo necessário para os novos
programadores aprenderem soluções proprietárias, recursos necessários
para a manutenção operacional ou outras formas de retirar tempo e energia
do trabalho nos produtos virados para o cliente.
Phil também observou que a utilização de bibliotecas que expõem a
funcionalidade através de ligações linguísticas ou de um SDK limitava as
ferramentas, os tempos de execução e as linguagens que podes utilizar para
os teus microsserviços. As bibliotecas para microsserviços são muitas vezes
escritas para uma plataforma específica, seja uma linguagem de
programação ou um tempo de execução como a JVM. Se utilizares
plataformas diferentes da suportada pela biblioteca, é muito provável que
tenhas de portar o código para a nova plataforma, com os teus custos a
aumentarem em relação ao número de linguagens.
BIBLIOTECAS SERVICE MESH E O PREÇO DO
POLIGLOTA
Muitas organizações adotam uma abordagem poliglota para codificar aplicações e usam uma
variedade de linguagens, escolhendo a mais apropriada para um serviço a fim de cumprir os
requisitos. Por exemplo, usando Java para serviços de negócios de longa duração, Go para
serviços de infraestrutura e Python para trabalho de ciência de dados. Se adotar a abordagem
baseada em bibliotecas para implementar uma malha de serviços, terá de estar ciente de que terá
de construir, manter e atualizar todas as suas bibliotecas em simultâneo para evitar problemas de
compatibilidade ou proporcionar uma experiência de programador abaixo do ideal para algumas
linguagens. Também pode encontrar diferenças subtis entre implementações em plataformas de
linguagens ou erros que apenas afectam um tempo de execução específico.
Carros laterais
No início dos anos 2010, muitos engenheiros estavam a adotar a abordagem
da programação poliglota, e não era incomum para uma única organização
ter serviços escritos em várias linguagens que foram implantados na
produção. O desejo de escrever ou manter uma biblioteca que lidava com
todas as abstrações de rede necessárias levou à criação de bibliotecas que
eram executadas externamente a um serviço como processos autónomos.
Em 2013, o Airbnb escreveu sobre "Synapse and Nerve", sua
implementação de código aberto de um sidecar de descoberta de serviços.
Um ano depois, a Netflix introduziu o Prana, um sidecar que expôs uma
interface HTTP para aplicações não-JVM se integrarem com o resto do
ecossistema OSS da Netflix para descoberta de serviços, circuit breaking e
muito mais. O conceito central aqui era que um serviço não se conectava
diretamente às suas dependências downstream, mas em vez disso todo o
tráfego passava pelo sidecar Prana que adicionava de forma transparente a
abstração de rede e os recursos desejados.
À medida que a utilização do estilo de arquitetura de microsserviços
aumentou, assistimos ao aparecimento de uma nova vaga de proxies
suficientemente flexíveis para se adaptarem a diferentes componentes de
infraestrutura e requisitos de comunicação. O primeiro sistema amplamente
conhecido neste espaço foi o Linkerd, criado pela Buoyant e baseado na sua
experiência de engenharia de ter trabalhado na plataforma de
microsserviços do Twitter. Logo depois, a equipe de engenharia da Lyft
anunciou o Envoy Proxy, que seguiu um princípio semelhante e foi
rapidamente adotado pelo Google em sua malha de serviços Istio. Ao usar o
padrão sidecar, cada um dos seus serviços terá um processo proxy
complementar que é executado de forma autônoma ao lado do seu
aplicativo. Esse sidecar normalmente compartilha o mesmo namespace de
processo, arquivo e rede, e garantias de segurança específicas são
fornecidas (por exemplo Dado que os serviços comunicam entre si apenas
através do proxy sidecar, acabamos por ter uma implementação semelhante
ao diagrama da Figura 4-6.
Figura 4-6. Proxies de malha de serviço formando uma abstração de rede de nível superior
Tal como referido por Phil Calçado e William Morgan da Buoyant, o aspeto
mais poderoso desta integração de proxies sidecar é que te afasta de pensar
nos proxies como componentes isolados e passa a reconhecer a rede que
formam como algo valioso em si mesmo.
Em meados da década de 2010, as organizações começaram a mover suas
implantações de microsserviços para tempos de execução mais sofisticados,
como Apache Mesos (com Marathon), Docker Swarm e Kubernetes, e as
organizações começaram a usar as ferramentas disponibilizadas por essas
plataformas para implementar um service mesh. Isso levou a um
afastamento do uso de um conjunto de proxies independentes trabalhando
isoladamente, como vimos com empresas como Synapse e Nerve, em
direção ao uso de um plano de controle centralizado. Se olharmos para este
padrão de implementação usando uma visão de cima para baixo, podemos
ver que o tráfego do serviço ainda flui de proxy para proxy diretamente,
mas o plano de controlo conhece e pode influenciar cada instância de proxy.
O plano de controlo permite que os proxies implementem funcionalidades
como o controlo de acesso e a recolha de métricas que requerem
cooperação e coordenação entre serviços, como mostra a Figura 4-7.
Figura 4-7. Controlo e coordenação do plano de dados de uma rede em malha de serviços
A abordagem baseada em sidecar é o padrão mais comum atualmente em
uso e, provavelmente, uma boa escolha para o nosso sistema de
conferências. Os principais custos da implementação de uma rede de
serviços baseada em sidecar estão relacionados com a instalação inicial e a
manutenção operacional contínua e também com os recursos necessários
para executar todos os sidecars - uma vez que as nossas necessidadesde
escalabilidade são atualmente modestas, não devemos precisar de grandes
quantidades de poder de computação para executar os proxies sidecar.
O CUSTO DE GERIR SIDECARS À ESCALA
Muitas das soluções populares de service mesh atuais exigem que você adicione e execute um
contêiner sidecar de proxy, como Envoy, Linkerd-proxy ou NGINX, para cada serviço ou
aplicativo em execução no cluster. Mesmo em um ambiente relativamente pequeno com, digamos,
20 serviços, cada um executando cinco pods espalhados por três nós, você terá 100 contêineres de
proxy em execução. Por menor e mais eficiente que seja a implementação do proxy, a duplicação
dos proxies afetará os recursos.
Dependendo da configuração do service mesh, a quantidade de memória usada por cada proxy
pode aumentar em relação ao número de serviços com os quais ele precisa se [Link]
Singhal escreveu sobre suas experiências configurando o Istio para reduzir o consumo de cerca de
1 GB por proxy para 60-70 MB cada, o que é muito mais razoável. No entanto, mesmo em um
ambiente pequeno e imaginário com 100 proxies em três nós, essa configuração otimizada ainda
requer aproximadamente 2 GB por nó.
Bibliotecas gRPC sem proxila
Em uma evolução que parece ter completado o círculo, o Google Cloud
começou a promover o "proxyless gPRC" no início de 2021, onde as
abstrações de rede são mais uma vez movidas para uma biblioteca
específica de linguagem (embora uma biblioteca mantida pelo Google e
uma grande comunidade OSS). Estas bibliotecas gRPC estão incluídas em
cada serviço e actuam como plano de dados dentro da malha de serviços.
As bibliotecas requerem acesso a um plano de controlo externo para
coordenação, como o serviço Google Traffic Diretor. O Traffic Diretor
utiliza "APIs xDS" de código aberto para configurar diretamente as
bibliotecas gRPC dentro das aplicações.6 Estas aplicações gRPC actuam
como clientes xDS, ligando-se ao plano de controlo global do Traffic
Diretor, que permite o encaminhamento global, o equilíbrio de carga e a
ativação pós-falha regional para casos de utilização de rede de serviços e de
equilíbrio de carga. O Traffic Diretor suporta mesmo um modo de
funcionamento "híbrido", incluindo implementações que incorporam
serviços baseados em proxy sidecar e serviços sem proxy, como se mostra
na Figura 4-8.
Figura 4-8. Exemplo de diagrama de rede de serviços que utilizam sidecars e comunicação proxyless
Como o nosso sistema de conferências utiliza APIs REST para além das
APIs gRPC, isto excluiria atualmente esta opção de implementação de uma
rede de serviços. Se a nossa utilização de APIs REST a nível interno for
descontinuada, ou se as bibliotecas gRPC forem melhoradas para oferecer
suporte a comunicações não baseadas em gRPC, a utilização desta
abordagem poderá ser reavaliada.
O FUTURO DO SERVICE MESH É PROXYLESS?
Como diz o cliché popular, embora a história não se repita, muitas
vezes rima. Muitos dos benefícios e limitações da abordagem proxyless
são semelhantes aos da utilização de bibliotecas específicas de uma
língua. A equipa do Google Cloud referiu os seguintes casos de
utilização como exemplos de quando a implementação proxyless do
serviço pode ser benéfica:
Eficiência de recursos numa rede de serviços em grande escala:
poupa recursos ao não executar processos secundários adicionais
Aplicações gRPC de elevado desempenho: reduz os saltos e a
latência da rede
Malha de serviços para ambientes onde não é possível
implementar proxies sidecar: por exemplo, um segundo processo
não pode ser executado ou um sidecar não pode manipular a pilha
de rede necessária
Migra de uma rede de serviços com proxies para uma rede sem
proxies
Não tem carro lateral: Implementações do kernel do sistema
operativo (eBPF)
Outra alternativa emergente de implementação do service mesh é baseada
em empurrar as abstrações de rede necessárias de volta para o próprio
kernel do sistema operacional (SO). Isso se tornou possível graças ao
surgimento e à ampla adoção do eBPF, uma tecnologia de kernel que
permite que programas personalizados sejam executados em sandbox
dentro do kernel. Os programas eBPF são executados em resposta a eventos
no nível do SO, dos quais existem milhares que podem ser anexados. Esses
eventos incluem a entrada ou saída de qualquer função no espaço do kernel
ou do usuário, ou "pontos de rastreamento" e "pontos de sondagem" e - o
que é importante para o service mesh - a chegada de pacotes de rede. Como
há apenas um kernel por nó, todos os contêineres e processos em execução
em um nó compartilham o mesmo kernel. Se você adicionar um programa
eBPF a um evento no kernel, ele será acionado independentemente do
processo que causou esse evento, esteja ele em execução em um contêiner
de aplicativos ou diretamente no host. Isso deve remover quaisquer
tentativas potenciais de contornar o service mesh, acidentalmente ou não.
O projeto Cilium baseado em eBPF fornece os recursos para proteger e
observar a conetividade de rede entre cargas de trabalho de contêineres. O
Cilium traz esse modelo "sidecarless" para o mundo do service mesh. O uso
do Cilium pode reduzir a latência entre as chamadas de serviço, pois
algumas funcionalidades podem ser fornecidas pelo kernel sem a
necessidade de executar um salto de rede para um proxy sidecar.7 Assim
como o modelo sidecar convencional, o Cilium suporta a execução de um
plano de dados de malha de serviço usando uma única instância do Envoy
Proxy por nó, reduzindo o uso de recursos. A Figura 4-9 mostra como dois
serviços podem se comunicar usando o Cilium e um único Envoy Proxy por
nó.
Figura 4-9. Usando Cilium, eBPF e um único Envoy Proxy por nó para implementar a
funcionalidade de service mesh
Taxonomia da malha de serviços
A Tabela 4-4 destaca a diferença entre os três estilos de implementação da
malha de serviço, conforme discutido na secção anterior.
Tabela 4-4. Comparação das malhas de serviço baseadas em biblioteca,
proxy e SO/kernel
Baseado em
Caso de bibliotecas (e Sidecars, baseados Baseado no
utilização "proxyless") em proxy SO/kernel
Suporte de Bibliotecas de Independente de idioma, Suporte a nível de SO,
idioma/plataforma linguagem única, com amplo suporte de independente da
independente de plataforma linguagem
plataforma
Mecanismo de Empacota e executa Executa uma aplicação Corre como parte do
tempo de execução dentro da aplicação paralela num processo kernel do SO, com
separado acesso total ao espaço do
utilizador e do kernel
Atualização dos Requer a reconstrução e Requer a redistribuição Requer
componentes da a reimplantação de toda dos componentes do atualização/correção do
malha de serviço a aplicação sidecar (muitas vezes, o programa do kernel
tempo de inatividade
pode ser nulo)
Observabilidade Percebe completamente Apenas informações Apenas informações
a aplicação e o tráfego, sobre o tráfego, a sobre o tráfego, a
com a capacidade de propagação do contexto propagação do contexto
propagar facilmente o requer um suporte requer um suporte
contexto linguístico ou um shim linguístico ou um shim
Modelo de ameaça O código da biblioteca Os Sidecars partilham A aplicação interage
à segurança é executado como parte normalmente o processo diretamente com o SO
da aplicação e o espaço de nomes da através de syscalls
rede com a aplicação
Estudo de caso: Usando um Service Mesh
para roteamento, observabilidade e
segurança
Nesta seção do capítulo, explorarás vários exemplos concretos de como
usar um service mesh para implementar os requisitos comuns de
roteamento, observação e segmentação segura (via autorização) do tráfego
de serviço para serviço. Todos esses exemplos usarão o Kubernetes, pois
essa é a plataforma mais comum na qual os service meshes são
implantados, mas os conceitos demonstrados se aplicam a todas as
plataformas e infraestruturas para as quais cada service mesh oferece
suporte. Embora seja recomendável escolher e adotar apenas uma
implementação de service mesh na pilha de tecnologia do seu aplicativo,
demonstraremos a configuração do sistema de conferência usando três
service meshes diferentes, apenas para fins educacionais.
Roteamento com o Istio
Istio pode ser instalado no teu cluster Kubernetes com a ferramenta istioctl.
O principal pré-requisito para usar o Istio é habilitar a injeção automática
dos sidecars de proxy em todos os serviços que estão em execução no seu
cluster. Isso pode ser feito da seguinte forma:
$ kubectl label namespace default istio-injection=enabled
Com a injeção automática configurada, os dois principais recursos
personalizados com os quais você trabalhará são VirtualServices e
DestinationRules.8 Um VirtualService define um conjunto de regras de
roteamento de tráfego a serem aplicadas quando um host é endereçado - por
exemplo, [Link] Uma DestinationRule define políticas que se
aplicam ao tráfego destinado a um serviço após o roteamento ter ocorrido.
Essas regras especificam a configuração para balanceamento de carga, o
tamanho do pool de conexões do sidecar e as configurações de deteção de
outlier para detetar e expulsar hosts não saudáveis do pool de
balanceamento de carga.
Por exemplo, para permitir o encaminhamento para os serviços Session e
Attendee no estudo de caso, podes criar os seguintes VirtualServices:
---
apiVersion: [Link]/v1alpha3
kind: VirtualService
metadata:
name: sessions
spec:
hosts:
- sessions
http:
- route:
- destination:
host: sessions
subset: v1
---
apiVersion: [Link]/v1alpha3
kind: VirtualService
metadata:
name: attendees
spec:
hosts:
- attendees
http:
- route:
- destination:
host: attendees
subset: v1
As DestinationRules seguintes também podem ser criadas. Observa como a
DestinationRule dos participantes especifica duas versões do serviço; esta é
a base para permitir o encaminhamento canário para a nova versão v2 do
serviço:
---
apiVersion: [Link]/v1alpha3
kind: DestinationRule
metadata:
name: sessions
spec:
host: sessions
subsets:
- name: v1
labels:
version: v1
---
apiVersion: [Link]/v1alpha3
kind: DestinationRule
metadata:
name: attendees
spec:
host: attendees
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
Com o Istio instalado e os VirtualServices e DestinationRules anteriores
configurados, você pode começar a rotear o tráfego e as chamadas de API
entre os serviços Attendee e Session. É realmente muito fácil começar,
embora a configuração e a manutenção do Istio em um ambiente de
produção possam ser mais complicadas. O Istio cuidará do roteamento e
também gerará telemetria relacionada a cada conexão. Vamos aprender
mais sobre observabilidade usando a malha de serviços Linkerd.
Observar o tráfego com o Linkerd
Tu podes instalar o Linkerd num cluster Kubernetes seguindo as instruções
"Getting Started". As funcionalidades de telemetria e monitorização do
Linkerd são activadas automaticamente, sem que seja necessário fazer
quaisquer alterações de configuração à instalação predefinida. Estas
funcionalidades de observabilidade incluem:
Registo de métricas de topo ("douradas") (volume de pedidos, taxa de
sucesso e distribuições de latência) para tráfego HTTP, HTTP/2 e
gRPC
Registo de métricas ao nível do TCP (bytes de entrada/saída, etc.) para
outro tráfego TCP
Relatórios de métricas por serviço, por par chamador/calouro ou por
rota/caminho (com perfis de serviço)
Gera gráficos de topologia que mostram a relação entreserviços em
tempo de execução
Amostragem de pedidos em direto e a pedido
Podes consumir estes dados de várias formas:
Através do Linkerd CLI, por exemplo, com linkerd viz stat e linkerd
viz routes
Através do painel Linkerd e de painéis Grafana pré-construídos
Diretamente da instância integrada do Prometheus do Linkerd
Para teres acesso às funcionalidades de observabilidade do Linkerd, só
precisas de instalar a extensão viz e abrir o painel de controlo utilizando o
teu browser local:
linkerd viz install | kubectl apply -f -
linkerd viz dashboard
Isso fornece acesso a gráficos de serviço que mostram o fluxo de tráfego.
Na Figura 4-10, podes ver o tráfego a fluir através da malha, desde a
aplicação Web até aos serviços de livros e autores.
Figura 4-10. Usando o Linkerd viz para observar o fluxo de tráfego entre os serviços
Também podes ver as métricas de tráfego de primeira linha utilizando os
dashboards Grafana pré-construídos, como mostrado na Figura 4-11.
Figura 4-11. Exibindo os painéis do Linkerd viz Grafana
O uso de uma malha de serviço para fornecer observabilidade em seus
aplicativos é útil durante o desenvolvimento e a produção. Embora você
sempre deva automatizar a deteção de tráfego inválido de serviço para
serviço na produção, também é possível usar essa ferramenta de
observabilidade de malha de serviço para identificar quando APIs ou
serviços internos estão sendo chamados incorretamente. Vamos agora
explorar o uso da política para especificar exatamente quais serviços podem
se comunicar uns com os outros na malha de serviço usando HashiCorp's
Consul.
Segmentação de rede com o Consul
Podes instalar e configurar o Consul como uma malha de serviço dentro de
um cluster Kubernetes, seguindo o guia "Getting Started with Consul
Service Mesh for Kubernetes". Antes dos microsserviços, a autorização da
comunicação interserviço era aplicada principalmente usando regras de
firewall e tabelas de roteamento. O Consul simplifica o gerenciamento da
autorização interserviço com intenções que permitem definir permissões de
comunicação serviço a serviço por nome de serviço.
As intenções controlam quais serviços podem se comunicar entre si e são
aplicadas pelo proxy sidecar nas conexões de entrada. A identidade do
serviço de entrada é verificada por seu certificado de cliente TLS, e o
Consul fornece a cada serviço uma identidade codificada como um
certificado TLS. Esse certificado é usado para estabelecer e aceitarconexões
de e para outros serviços.9 O proxy sidecar então verifica se existe uma
intenção que autoriza o serviço de entrada a se comunicar com o serviço de
destino. Se o serviço de entrada não estiver autorizado, a conexão será
encerrada.
Uma intenção tem quatro partes:
Serviço de origem
Especifica o serviço que inicia a comunicação. Pode ser o nome
completo de um serviço ou "*" para se referir a todos os serviços.
Serviço de destino
Especifica o serviço que recebe a comunicação. Este será o "upstream"
(serviço) que configuraste na tua definição de serviço. Pode ser o nome
completo de um serviço ou também "*" para se referir a todos os
serviços.
Autorização
Define se a comunicação entre a origem e o destino é permitida. Pode
ser definido para permitir ou negar.
Descrição
Campo de metadados opcional para associar uma descrição a uma
intenção.
A primeira intenção que vais criar altera a política "permitir tudo", em que
todo o tráfego é permitido, a menos que seja negado em regras específicas,
para uma política "negar tudo", em que todo o tráfego é negado e apenas
são activadas ligações específicas:
apiVersion: [Link]/v1alpha1
kind: ServiceIntentions
metadata:
name: deny-all
spec:
destination:
name: '*'
sources:
- name: '*'
action: deny
Depois de definir a política padrão como negar tudo, é possível autorizar o
tráfego entre o serviço legado do sistema de conferência, o serviço Attendee
e o serviço Session, definindo um CRD ServiceIntentions para cada
interação de serviço necessária. Por exemplo:
---
apiVersion: [Link]/v1alpha1
kind: ServiceIntentions
metadata:
name: legacy-app-to-attendee
spec:
destination:
name: attendee
sources:
- name: legacy-conf-app
action: allow
---
apiVersion: [Link]/v1alpha1
kind: ServiceIntentions
metadata:
name: legacy-app-to-sessions
spec:
destination:
name: sessions
sources:
- name: legacy-conf-app
action: allow
---
apiVersion: [Link]/v1alpha1
kind: ServiceIntentions
metadata:
name: attendee-to-sessions
spec:
destination:
name: sessions
sources:
- name: attendee
action: allow
---
apiVersion: [Link]/v1alpha1
kind: ServiceIntentions
metadata:
name: sessions-to-attendee
spec:
destination:
name: attendee
sources:
- name: sessions
action: allow
A aplicação desta configuração ao cluster Kubernetes irá permitir que estas
interações - e apenas estas interações serviço-a-serviço - sejam processadas
conforme necessário. Quaisquer outras interações serão impedidas e a
chamada ou pedido de API será rejeitado.
Para além das intenções do Consul, o projeto Open Policy Agent (OPA) é
uma escolha popular para implementar uma funcionalidade semelhante
numa rede de serviços. Podes encontrar um exemplo de utilização do OPA
para configurar a política serviço-a-serviço no Istio na "Documentação do
tutorial do OPA".
Agora que já exploraste um exemplo de configuração que será aplicado à
medida que evoluímos o sistema de conferência, vamos concentrar-nos na
execução e gestão da implementação da malha de serviço propriamente
dita.
Implantação de uma malha de serviço:
Entendendo egerenciando falhas
Independentemente do padrão de implantação e do número de instâncias em
execução em um sistema ou rede, um service mesh normalmente está no
caminho crítico de muitas, se não de todas, as solicitações de usuários que
passam pelo seu sistema. Uma interrupção de uma instância do service
mesh em um cluster ou rede normalmente resulta na indisponibilidade de
todo o sistema dentro do raio de alcance dessa rede. Por esse motivo, é de
vital importância aprender os tópicos de compreensão e gerenciamento de
falhas.
Service Mesh como um ponto único de falha
Um service mesh está muitas vezes no hot path de todo o tráfego, o que
pode ser um desafio em relação à fiabilidade e ao failover. Obviamente,
quanto mais funcionalidades estiverem presentes no service mesh, maior é o
risco envolvido e maior é o impacto de uma falha. Como um service mesh é
frequentemente usado para orquestrar o lançamento de serviços de
aplicativos, a configuração também é atualizada continuamente. É
fundamental poder detetar e resolver problemas e mitigar quaisquer riscos.
Muitos dos pontos discutidos em "API Gateway como ponto único de
falha" podem ser aplicados para entender e gerenciar falhas no service
mesh.
Desafios comuns da implementação do
Service Mesh
Como as tecnologias de rede de serviços são mais recentes em comparação
com as tecnologias de gateway de API, alguns dos desafios comuns de
implementação ainda não foram descobertos e partilhados amplamente. No
entanto, há um conjunto essencial de antipadrões a evitar.
Service Mesh como ESB
Com o surgimento de plug-ins de service mesh ou filtros de tráfego e
tecnologias de suporte como o Web Assembly (Wasm), é cada vez mais
tentador pensar em service meshes como oferecendo funcionalidades
semelhantes às do ESB, como transformação e tradução de carga útil. Por
todas as razões já discutidas ao longo deste livro, desencorajamos
fortemente a adição de funcionalidades comerciais ou o acoplamento de
muitos "smarts" com a plataforma ou infraestrutura.
Service Mesh como Gateway
Como muitas implementações de service mesh do fornecem alguma forma
de gateway de entrada, temos visto organizações que desejam adotar um
gateway de API, mas, em vez disso, optam por implantar um service mesh e
usar apenas a funcionalidade do gateway. A motivação faz sentido, pois os
engenheiros da organização percebem que em breve desejarão adotar uma
funcionalidade semelhante à do service mesh, mas seu maior problema é
gerenciar o tráfego de entrada. No entanto, a funcionalidade fornecida pela
maioria dos gateways de service mesh não é tão rica em comparação com
um gateway de API completo. Também é muito provável que te depares
com os custos de instalação e operacionais da execução de um service mesh
sem obteres nenhum dos benefícios.
Demasiadas camadas de Network+
Vimos algumas organizações fornecerem um rico conjunto de abstrações e
recursos de rede que atenderão aos requisitos atuais de comunicação serviço
a serviço, mas as equipes de desenvolvimento não sabem disso ou se
recusam a adotá-lo por algum motivo. À medida que as equipes de
desenvolvimento tentam implementar um service mesh sobre as tecnologias
de rede existentes, surgem problemas adicionais, como incompatibilidades
(por exemplo tecnologias de rede existentes que retiram cabeçalhos),
aumento da latência (devido a vários saltos de proxy) ou funcionalidade
implementada várias vezes na pilha de rede (por exemplo, interrupção de
circuitos que ocorre tanto na malha de serviço como na pilha de rede de
nível inferior). Por este motivo, recomendamos sempre que todas as equipas
envolvidas coordenem e colaborem com a malha de serviço soluções.
Seleção de uma malha de serviço
Agora que aprendeste sobre a funcionalidade fornecida por um service
mesh, a evolução do padrão e das tecnologias e como um service mesh se
enquadra na arquitetura geral do sistema, segue-se uma questão
fundamental: como selecionar um service mesh para ser incluído no
conjunto de tecnologias da tua aplicação?
Identificação de requisitos
Tal como foi discutido em relação à seleção de um gateway de API, um dos
passos mais importantes em qualquer novo projeto de infraestrutura é a
identificação dos requisitos relacionados. Isto pode parecer óbvio, mas
tenho a certeza que te lembras de uma altura em que foste distraído por
tecnologia brilhante, marketing mágico ou boa documentação de vendas!
Pode consultar a secção anterior "Porquê utilizar uma rede de serviços?"
deste capítulo para explorar com mais pormenor os requisitos de alto nível
que deve considerar durante um processo de seleção de uma rede de
serviços. É importante fazer perguntas que se centrem nos pontos
problemáticos actuais e também no seu roteiro futuro.
Construir versus comprar
Em comparação com a decisão de construir ou comprar um gateway de
API, as discussões relacionadas com o service mesh têm menos
probabilidade de serem realizadas antecipadamente, especialmente em
organizações que têm sistemas herdados ou legados. Isso pode ser
parcialmente atribuído ao fato de o service mesh ser uma categoria de
tecnologia relativamente nova, mais do que uma pilha LAMP), as
implementações parciais de um service mesh estarão espalhadas por toda a
organização - por exemplo, com alguns departamentos usando bibliotecas
específicas de linguagem, outros usando um ESB e alguns usando gateways
de API simples ou proxies simples para gerenciar o tráfego interno.
Em geral, se decidiste adotar o padrão service mesh, acreditamos que é
tipicamente melhor adotar e padronizar uma implementação de código
aberto ou uma solução comercial em vez de construir a tua própria solução.
Apresentar o caso de construir versus comprar com tecnologia de entrega de
software poderia levar um livro inteiro e, por isso, nesta secção apenas
queremos destacar alguns desafios comuns:
Subestimação do custo total de propriedade (TCO)
Muitos engenheiros desconsideram o custo da engenharia de uma
solução, os custos de manutenção contínua e os custos operacionais
contínuos.
Não pensar no custo de oportunidade
A menos que sejas um fornecedor de Cloud ou de plataformas, é
altamente improvável que uma malha de serviços personalizada te
proporcione uma vantagem competitiva. Em vez disso, podes oferecer
mais valor aos teus clientes criando funcionalidades alinhadas com a tua
proposta de valor principal.
Custos operacionais
Não compreende o custo de integração e operacional de manter várias
implementações diferentes que resolvem os mesmos problemas.
Toma consciência das soluções técnicas
Tanto o espaço dos componentes de plataforma de código aberto como
os comerciais evoluem rapidamente e pode ser difícil manter-se
atualizado. No entanto, manter-se atento e informado é uma parte
essencial do papel de um líder técnico.
Lista de verificação: Seleção de uma rede de serviços
A lista de verificação na Tabela 4-5 destaca as principais decisões que tu e a
tua equipa devem considerar quando decidem implementar o padrão service
mesh e quando escolhem as tecnologias relacionadas.
Tabela 4-5. Diretriz ADR: Seleção de uma lista de verificação da rede de
serviços
Decisão Como devemos abordar a seleção de uma rede de serviços para a nossa
organização?
Pontos de discussão Identificámos e demos prioridade a todos os nossos requisitos associados à
seleção de uma rede de serviços?
Identificámos as soluções tecnológicas actuais que foram implementadas
neste espaço dentro da organização?
Conhecemos todos os constrangimentos da nossa equipa e da organização?
Já explorámos o nosso roteiro futuro em relação a esta decisão?
Calculámos honestamente os custos de "construir versus comprar"?
Explorámos o panorama tecnológico atual e estamos cientes de todas as
soluções disponíveis?
Consultámos e informámos todas as partes interessadas envolvidas na nossa
análise e tomada de decisões?
Recomendações Concentra-te especialmente nos teus requisitos para reduzir o acoplamento
interno API/sistema, simplificar o consumo, proteger as APIs da utilização
excessiva e abusiva, compreender como as APIs estão a ser consumidas e
gerir as APIs como produtos.
As principais perguntas a fazer incluem: existe uma rede de serviços em
utilização? Foi reunida uma coleção de tecnologias para fornecer uma
funcionalidade semelhante; por exemplo, os programadores criaram
bibliotecas de comunicação serviço-a-serviço ou a equipa de
plataformas/SREs implementou proxies sidecar?
Concentra-te nos níveis de competências tecnológicas da tua equipa, na
disponibilidade das pessoas para trabalharem num projeto de malha de
serviço, nos recursos e no orçamento disponíveis, etc.
É importante identificar todas as alterações planeadas, novas caraterísticas e
objectivos actuais que possam ter impacto na gestão do tráfego interno e
noutras funcionalidades fornecidas por uma rede de serviços.
Calcula o custo total de propriedade (TCO) de todas as implementações
actuais de service meshlike e potenciais soluções futuras.
Consulta analistas de renome, relatórios de tendências e análises de produtos
para compreenderes todas as soluções disponíveis atualmente.
A seleção e implementação de uma rede de serviços terá impacto em muitas
equipas e indivíduos. Não te esqueças de consultar as equipas de
desenvolvimento, QA, o conselho de revisão da arquitetura, a equipa da
plataforma, InfoSec, etc.
Resumo
Neste capítulo, aprendeste o que é um service mesh e exploraste a
funcionalidade, os benefícios e os desafios que a adoção deste padrão e das
tecnologias associadas proporciona:
Fundamentalmente, o "service mesh" é um padrão para gerir todas as
comunicações serviço-a-serviço num sistema de software distribuído.
Ao nível da rede, um proxy service mesh actua como um proxy
completo, aceitando todo o tráfego de entrada de outros serviços e
iniciando também todos os pedidos de saída para outros serviços.
Os sistemas ou redes de grandes dimensões são normalmente geridos
através da implementação de várias instâncias de um service mesh,
muitas vezes com cada mesh individual a abranger um segmento de
rede ou um domínio empresarial.
Um service mesh pode expor endpoints dentro de uma zona
desmilitarizada (DMZ) da rede, ou a sistemas externos, ou a redes ou
clusters adicionais, mas isto é frequentemente implementado
utilizando um gateway de "entrada", "terminação" ou "trânsito".
Existem muitas preocupações transversais relacionadas com a API que
podes ter para cada um ou todos os teus serviços internos, incluindo:
gestão do ciclo de vida do produto (lançamento incremental de novas
versões de um serviço), fiabilidade, suporte de comunicação
multilingue, observabilidade, segurança, manutenção e extensibilidade.
Uma rede de serviços pode ajudar com tudo isto.
Um service mesh pode ser implementado utilizando bibliotecas
específicas da linguagem, proxies sidecar, estruturas de comunicação
sem proxys (gRPC) ou tecnologias baseadas no kernel, como o eBPF.
O componente mais vulnerável de uma rede de serviços é,
normalmente, o plano de controlo, que deve ser protegido,
monitorizado e executado como um serviço altamente disponível.
Os antipadrões de utilização da rede de serviços incluem: rede de
serviços como ESB, rede de serviços como gateway e utilização de
demasiadas camadas de rede.
Optar por implementar uma malha de serviço e selecionar a tecnologia
para o fazer são decisões de tipo 1. É necessário efetuar pesquisas,
analisar os requisitos e conceber uma estrutura adequada.
Se decidiste adotar o padrão service mesh, acreditamos que,
normalmente, é melhor adotar e normalizar uma implementação de
código aberto ou uma solução comercial do que construir a tua própria
solução.
Independentemente da sua decisão de adotar um service mesh, é importante
considerar as operações externas e internas e a segurança das suas APIs.
Este é o foco da próxima secção deste livro.
1 O projeto Linkerd surgiu da tecnologia Finagle do Twitter, que foi criada para fornecer uma
estrutura de comunicação para os programadores que criam aplicações distribuídas do Twitter.
O Linkerd evoluiu agora para um projeto graduado da Cloud Native Computing Foundation
(CNCF).
2 Podes aprender mais sobre os conceitos de rede do Kubernetes através dos documentos
oficiais: Service, NetworkPolicies, e Container Networking Interface (CNI).
3 O SmartStack da Airbnb foi uma das primeiras implementações da descoberta de serviços de
microsserviços externos.
4 Deves ter em atenção que a estrutura Finagle RPC e as bibliotecas Netflix OSS estão agora
obsoletas e não são recomendadas para utilização em sistemas de produção modernos.
5 Podes aprender mais através destes sites para "Microsserviços Pré-requisitos" de Fowler ,
"Microsserviços Pré-requisitos de Calçado", e o blog do Phil "Pattern: Service Mesh" do Phil.
6 Podes saber mais sobre o Traffic Diretor e o protocolo xDS inspirado no Envoy Proxy através
dos respectivos sites de documentação.
7 Sabe mais sobre este assunto em "Como o eBPF vai resolver a Malha de Serviço - Adeus
Sidecars".
8 Podes saber mais sobre VirtualServices e DestinationRules através dos documentos do Istio.
9 A identidade é codificada no certificado TLS em conformidade com o documento de
identidade SPIFFE X.509, que permite aos serviços Connect estabelecer e aceitar ligações com
outros sistemas compatíveis com SPIFFE.
Parte III. Operações e
segurança da API
Nesta secção, vais explorar os desafios de operar e proteger um sistema
orientado para API.
O Capítulo 5 aborda a implantação e o lançamento de APIs usando um ciclo
de vida de API. Também exploraremos tópicos de observabilidade e como
as plataformas opinativas podem ajudar a reduzir problemas com
arquiteturas distribuídas.
O Capítulo 6 explora a modelação de ameaças para APIs e como pensar
como alguém que tenta agir maliciosamente contra as suas APIs.
O Capítulo 7 examina o uso de autenticação e autorização para proteger
APIs.
Capítulo 5. Implantando e
liberando APIs
Este trabalho foi traduzido com recurso a IA. Agradecemos o teu feedback e comentários:
translation-feedback@[Link]
Neste capítulo, começaremos a juntar as informações sobre como passar do
design, construção e teste para a execução no ambiente de destino.
Considere o estudo de caso do sistema de conferência que apresentámos na
Introdução: tínhamos uma interface de utilizador única e uma aplicação do
lado do servidor. A implementação de uma atualização para o servidor ou
para a interface de utilizador implicaria provavelmente algum tempo de
inatividade. É provável que as acções de implementação e de lançamento
estejam fortemente acopladas e possivelmente inseparáveis. Também pode
ter demorado algum tempo a reverter as alterações se ocorresse um
problema com a implementação. Vamos explorar algumas opções para o
sistema de conferência antigo, para além de analisar como um acoplamento
mais flexível entre a IU e os componentes do servidor proporciona mais
opções para a implementação e o lançamento.
A introdução da gestão de tráfego oferece-lhe opções para separar a
implementação e o lançamento. Neste capítulo, vamos explorar esta questão
com mais pormenor e analisar as opções do sistema de conferência
disponíveis para a implementação de alterações. Terá de considerar a forma
como o versionamento da API afecta as opções para modelar lançamentos
no sistema de conferência.
As arquiteturas de APIs são, por natureza, desacopladas, e é importante
garantir que as métricas, os logs e os rastreamentos corretos estejam
disponíveis para realizar um lançamento bem-sucedido. Analisaremos os
tipos de considerações para métricas e como elas ajudam nos lançamentos e
no gerenciamento de incidentes/solução de problemas.
A introdução de camadas adicionais de infraestrutura, como proxies, exige
decisões sobre o armazenamento em cache e a propagação de cabeçalhos.
Exploraremos essas considerações e por que você pode escolher uma
plataforma opinativa.
Separação entre implantação e liberação
É importante que entendas a diferença entre deployment e release para tirar
o máximo proveito deste capítulo. O deployment envolve levar uma
funcionalidade até a produção, porque agora tens um processo em execução
no teu sistema. Embora deployed, a nova funcionalidade não está ativa ou
executada por interações com o sistema de produção. Existem diferentes
formas de conseguir esta separação e irás explorá-las brevemente. O
lançamento envolve a ativação da nova funcionalidade de forma controlada,
permitindo-te controlar o risco da introdução da nova funcionalidade. O
Radar Tecnológico da Thoughtworks tem uma excelente explicação da
diferença entre implantação e lançamento:
A implementação da Entrega Contínua continua a ser um desafio para
muitas organizações, e continua a ser importante destacar técnicas úteis,
como a dissociação da implantação do lançamento. Recomendamos que
uses estritamente o termo Implantação quando te referes ao ato de
implantar uma alteração nos componentes da aplicação ou na
infraestrutura. O termo Release deve ser usado quando uma alteração de
recurso é liberada para os usuários finais, com um impacto nos negócios.
Usando técnicas como alternância de recursos e lançamentos obscuros,
podemos implantar alterações em sistemas de produção com mais
frequência sem liberar recursos. Implantações mais frequentes reduzem o
risco associado à mudança, enquanto os stakeholders de negócio mantêm
o controle sobre quando as funcionalidades são liberadas para os usuários
finais.
—Radar de Tecnologia da Thoughtworks 2016
Uma vantagem de avançar para uma arquitetura baseada em API é que a
natureza desacoplada permite que as equipas libertem rapidamente as
alterações. Para concretizar este benefício, é importante considerar que os
mecanismos para garantir que o acoplamento entre sistemas se mantém
baixo e que o risco de os lançamentos resultarem numa falha é minimizado.
AVISO
Vimos equipas que mudaram para uma arquitetura baseada em API sem separar a implementação
e o lançamento. Isto pode funcionar para serviços altamente acoplados, mas rapidamente coloca
pressão e tempo de inatividade em vários serviços se os lançamentos tiverem de ser coreografados
por muitas equipas. Iremos explorar mais adiante neste capítulo como pode utilizar o
versionamento de API e ciclos de vida para ajudar a evitar isto.
Estudo de caso: Marcação de caraterísticas
Para considerar efetivamente como separar a implantação e o lançamento,
começaremos com o estudo de caso do sistema de conferência legado. Este
é um lugar útil para começar, pois nos permitirá modelar uma arquitetura
evolutiva de forma agradável, onde podemos controlar a taxa de mudança
para a nova infraestrutura que apresentamos até agora no livro. A Figura 5-
1 mostra como o sistema legado para participantes e o banco de dados
conviverão lado a lado com o serviço modernizado baseado em API.
Usando sinalizadores de recursos, o controlador agora pode tomar uma
decisão no nível do código sobre a execução da consulta no serviço de API
interno ou externo.
Figura 5-1. Diagrama de contentor da aplicação de conferência para participantes e sinalizadores
de funcionalidades
Quando a equipa (ou o proprietário do produto) estiver pronta para ativar a
funcionalidade, pode ativar a funcionalidade, o que faz com que a aplicação
execute um ramo diferente do código. A granularidade pode ser a nível de
cada utilizador, ou mais grosseira, como simplesmente ativar uma opção
específica globalmente. Segue-se um exemplo de pseudocódigo da popular
ferramenta de sinalização de funcionalidades Java LaunchDarkly, em que os
detalhes do utilizador estão na loja moderna:
LDUser user = new LDUser("jim@[Link]");
boolean newAttendeesService =
[Link]("[Link]", user,
false);
if (newAttendeesService) {
// Retrieves the attendee from the modern store
}
else {
// Retrieves the attendee from the legacy store
}
Seguindo esta abordagem, é possível migrar um pequeno lote de
utilizadores para o novo sistema e testar se a funcionalidade continua a
funcionar para o conjunto de utilizadores. Se alguma coisa correr mal
durante a migração, o interrutor pode simplesmente ser reposto, ou então a
implementação continua até atingir 100% de migração. Tal como outros
serviços transversais à aplicação, uma falha no serviço de marcação de
funcionalidades seria catastrófica se não fosse gerida corretamente e
constituiria um potencial ponto único de falha. A degradação graciosa
utilizando o último valor conhecido numa cache ou fornecendo valores
predefinidos pode ajudar a atenuar este efeito.
AVISO
Os sinalizadores de caraterísticas ajudam a facilitar a separação entre a implementação e o
lançamento do código. Tens de limpar os sinalizadores de caraterísticas e criar sempre
sinalizadores de caraterísticas com nomes únicos. Quando a migração estiver concluída, o código
do sinalizador de caraterísticas deve ser completamente removido. Para veres um exemplo de
sinalizadores de caraterísticas que correram mal devido a esta questão, basta olhares para a Knight
Capital, onde a reutilização de um sinalizador de caraterísticas e uma implementação falhada
acabaram por custar milhares de dólares por segundo, até uma eventual perda de 460 milhões de
dólares.
Gestão do tráfego
Uma das vantagens da mudança para uma arquitetura baseada em API é que
podemos iterar rapidamente e implementar novas alterações no nosso
serviço Attendee. Também temos o conceito de tráfego e encaminhamento
estabelecido para a parte modernizada da arquitetura, o que torna possível
manipular o tráfego em dois locais: na entrada do gateway da API ou nas
construções definidas na malha de serviço para modelar o tráfego.
Para Kubernetes e sistemas baseados em malha de serviço, a implantação se
parece mais ou menos com as seguintes etapas:
1. Cria um pull request das alterações necessárias à aplicação e, assim
que o pull request for aprovado e fundido, inicia automaticamente a
construção da implementação.
2. O pipeline de construção cria uma nova imagem utilizando o Docker
ou a Open Container Initiative.
3. Empurra a nova imagem para o registo do contentor.
4. Aciona uma nova implantação da imagem no ambiente de destino.
Por padrão, o Kubernetes substituirá o deployment em execução por um
novo deployment. Mais adiante neste capítulo, veremos técnicas para fasear
o lançamento de um novo pod para separar ativamente o deployment e o
release. Uma vez que o deployment está no lugar, o trabalho de implantar o
código está agora completo, e um conjunto diferente de instruções segue
para a configuração de release do sistema em execução. A configuração
também pode tervários estágios, e este é um mecanismo que podemos usar
para definir diferentes estratégias de lançamento. Antes de mergulharmos
na exploração de como estruturar o lançamento para gerenciamento de
tráfego, vale a pena explorar os tipos de lançamentos que você pode ter
dentro de um sistema de API .
Estudo de caso: Modelagem de liberações
no sistema de conferências
Em "Semantic Versioning" (semver), discutimos a ideia de diferentes
estratégias de versão associadas a APIs. Ao considerar lançamentos, pode
ser útil associar as ideias do semver a um ciclo de vida da API.
Ciclo de vida da API
O espaço da API está a evoluir rapidamente, mas uma das representações
mais claras do ciclo de vida das versões vem das normas da API do PayPal,
agora arquivadas. Uma abordagem para modelar o ciclo de vida é
apresentada no Quadro 5-1.
Tabela 5-1. Ciclo de vida da API (adaptado das normas da API do PayPal)
Planeado A exposição de uma API do ponto de vista tecnológico é bastante simples, no
entanto, uma vez exposta e em produção, tem vários consumidores de API
que precisam de ser geridos. A fase de planeamento consiste em anunciar que
está a construir uma API e em recolher feedback inicial sobre a conceção e a
forma da API junto dos consumidores. Isto permite uma discussão sobre a
API e o âmbito, permitindo incluir quaisquer decisões de conceção iniciais.
Beta Envolve o lançamento de uma versão da nossa API para que os utilizadores
comecem a integrá-la; no entanto, isto é geralmente para efeitos de feedback e
de melhoria da API. Nesta fase, o produtor reserva-se o direito de quebrar a
compatibilidade, porque não se trata de uma API com versões. Isto ajuda a
obter feedback rápido dos consumidores sobre a conceção da API antes de se
estabelecer uma estrutura. Uma ronda de feedback e alterações permite ao
produtor evitar ter muitas versões principais no início do tempo de vida da
API.
Vive A API está agora versionada e ativa em produção. Quaisquer alterações a
partir deste momento serão alterações versionadas. Só deve existir uma API
ativa, que marca a combinação de versão maior/menor mais recente. Sempre
que é lançada uma nova versão, a API ativa atual passa para obsoleta.
Depreciado Quando uma API é obsoleta, continua a poder ser utilizada, mas não deve ser
objeto de novos desenvolvimentos significativos.
Quando uma versão menor de uma nova API é lançada, uma API só será
depreciada por um curto período de tempo, até que a validação da nova API
em produção seja concluída. Depois de a nova versão ser validada com
sucesso, uma versão menor passa a ser retirada, uma vez que a nova versão é
compatível com as versões anteriores e pode lidar com os mesmos recursos
que a API anterior.
Quando é lançada uma versão principal da API, a versão mais antiga torna-se
obsoleta. É provável que isso aconteça durante semanas ou meses, uma vez
que deve ser dada uma oportunidade aos consumidores para migrarem para a
nova versão. É provável que haja comunicação com os consumidores, um guia
de migração e um acompanhamento das métricas e da utilização da API
obsoleta.
Reformado A API foi retirada da produção e já não está acessível.
Com o versionamento semântico combinado com o ciclo de vida da API, o
consumidor só precisa de ter conhecimento da versão principal da API. As
versões secundárias e de correção serão recebidas sem necessidade de
actualizações do lado do consumidor e não quebrarão a compatibilidade. Ao
considerar o ciclo de vida da API e o que pode controlar através da gestão
de tráfego, pode começar a analisar os tipos de alterações e a considerar a
forma mais adequada de lançar novas versões de APIs.
Mapeamento das estratégias de lançamento para o ciclo
de vida
As grandes alterações são as mais impactantes para os consumidores da
API. Para poderem utilizar a nova versão do software, os consumidores têm
de atualizar ativamente o seu software que interage com a API. Tal como
definido no ciclo de vida, isto significa que temos de executar
simultaneamente uma versão ativa e uma versão obsoleta da API durante
um período de tempo significativo para permitir que os consumidores
actualizem e migrem. Uma forma de o fazer é adicionar a versão no URL:
GET /v1/attendees
A adição da versão é prática e facilmente visível para o consumidor. No
entanto, não faz parte do recurso e, em alguns grupos, é considerado não
RESTful. Uma abordagem alternativa é ter um cabeçalho que descreva a
versão principal que terá impacto no encaminhamento na entrada do cluster:
GET /attendees
Version: v1
Para este tipo de alterações, é possível implementar uma nova versão menor
da API sem aceitar tráfego de produção e, em seguida, utilizar uma
estratégia de lançamento para introduzir a nova versão. Este tipo de
alteração não exigiria quaisquer alterações de código por parte do
consumidor. As alterações de correção seguem um padrão semelhante, uma
vez que não alteram de todo a forma da especificação da API. Para que este
tipo de lançamento transparente seja possível, vale a pena considerar a
adição de controlos extra no processo de construção para garantir que não
são introduzidas acidentalmente alterações de rutura.
Em "OpenAPI Specification and Versioning", demos uma olhada no uso do
openapi-diff para destacar as mudanças entre as especificações. No
caso de a especificação não ser compatível com versões anteriores, a
construção deve falhar e evitar que uma mudança de rutura entre na
arquitetura sem uma substituição consciente no lugar. A maioria dos
lançamentos contra uma API serão pequenas mudanças ou mudanças de
patches onde o acoplamento frouxo é uma preocupação primária para o
produtor e o consumidor.
Se o consumidor e o produtor estiverem fortemente acoplados, pertencerem
à mesma equipa e se moverem sempre em conjunto, o controlo de versões e
o ciclo de vida da API não serão críticos. Nesta situação, é importante
considerar uma estratégia de lançamento que permita o lançamento de
ambos os componentes em conjunto e o tráfego seja controlado na entrada.
Normalmente, os modelos azul-verde funcionam bem neste cenário e
iremos analisar este mais detalhadamente em "Estratégias de lançamento".
Diretriz ADR: Separa o lançamento da implantação com
gestão de tráfego e sinalizadores de recursos
O guia ADR na Tabela 5-2 é útil quando se considera como criar um ADR
para separar a liberação da implantação.
Tabela 5-2. Diretriz ADR: Separa o lançamento da implantação com a
gestão de tráfego e a orientação de sinalização de caraterísticas
Decisão Como é que separas o lançamento da implementação?
Pontos de discussão É possível separar a implementação e o lançamento nos sistemas existentes
que estão atualmente em funcionamento?
Qual é o grau de acoplamento entre o consumidor e o produtor no sistema?
Tens um pipeline de construção onde é possível aplicar os requisitos de
acoplamento flexível das APIs geridas pelo tráfego, garantindo que a
compatibilidade é testada?
Recomendações Começa por trabalhar na separação entre a implementação e o lançamento do
software existente. Isto ajudará a permitir uma arquitetura evolutiva e uma
simplificação do sistema existente.
Se a empresa nunca utilizou a sinalização de caraterísticas antes, certifica-te
de que revês as práticas recomendadas e evitas as armadilhas associadas às
sinalizações.
Sem uma análise cuidadosa, os sinalizadores de caraterísticas podem tornar-se
um ponto único de falha.
Analisa o tipo de acoplamento entre APIs na arquitetura e decide a estratégia
de lançamento correta para a situação.
Na próxima secção, exploraremos os diferentes tipos de estratégias de
libertação de disponíveis.
Estratégias de libertação
Depois de ter separado adequadamente a implementação e o lançamento,
pode agora considerar mecanismos para controlar o lançamento progressivo
de funcionalidades. É importante escolher uma estratégia de lançamento
que permita reduzir o risco na produção. A redução do risco é conseguida
através da realização de um teste ou experiência com uma pequena fração
do tráfego e da verificação do resultado. Quando o resultado é bem
sucedido, liberta todo o tráfego. Algumas estratégias são mais adequadas a
determinados cenários do que outras e requerem diferentes graus de
serviços e infra-estruturas adicionais. Vamos explorar algumas opções que
são populares na infraestrutura baseada em API.
Lançamentos Canários
Uma versão canary1 Na Figura 5-2, a fase anterior mostra a porta de
ligação, a conferência antiga na versão 1.0 e o serviço Attendee na v1.0. Na
fase de implantação, é implantada uma nova v1.1 do serviço Attendee e, no
momento da liberação, podemos começar a direcionar parte do tráfego para
o serviço v1.1.
Figura 5-2. Implantação do serviço Attendee usando uma abordagem canário
No Kubernetes, a divisão de tráfego pode ser alcançada introduzindo um
novo pod em um serviço; explorarás essa ideia com mais detalhes em
"Estudo de caso: Realizando Rollouts com Argo Rollouts". É muito difícil
controlar uma pequena porcentagem - ou seja, se você quiser 1%, precisará
executar 99 pods v1 e 1 pod v2. Para a maioria das situações, isso seria
impraticável.
Por exemplo, uma nova versão, v1.1, de um serviço pode ser implementada
juntamente com a original, v1.0. A mudança de tráfego permite-te testar ou
lançar o teu novo serviço, encaminhando inicialmente apenas uma pequena
percentagem do tráfego do utilizador, digamos 1%, para a v1.1 e, em
seguida, ao longo do tempo, transferindo todo o teu tráfego para o novo
serviço. Isto permite-lhe monitorizar o novo serviço e procurar problemas
técnicos, como o aumento da latência ou das taxas de erro, e também
procurar um impacto comercial desejado, como um aumento nos principais
indicadores de desempenho, como o rácio de conversão do cliente ou o
valor médio da caixa de compras. A divisão do tráfego permite-lhe executar
testes A/B ou multivariados, dividindo o tráfego destinado a um serviço-
alvo entre várias versões do serviço. Por exemplo, pode dividir o tráfego em
50/50 entre a v1.0 e a v1.1 do serviço-alvo e ver qual tem melhor
desempenho durante um período de tempo específico.
Como uma malha de serviço está envolvida em toda a comunicação
serviço-a-serviço, é possível implementar estas técnicas de lançamento e
experimentação em qualquer serviço da aplicação. Por exemplo, é possível
lançar uma nova versão do serviço Session que implemente o
armazenamento em cache interno do horário de uma sessão de conferência
dos participantes.
SEPARA A IMPLANTAÇÃO E O LANÇAMENTO: CANÁRIO
PARA TODAS AS COISAS
Com o aumento da Entrega Progressiva, e também dos requisitos avançados da Entrega Contínua
antes disso, ter a capacidade de separar a implantação e a liberação de um serviço (e a API
correspondente) é uma técnica poderosa. A capacidade de liberar serviços canários ou executar
testes A/B pode fornecer uma vantagem competitiva para o seu negócio, tanto na redução dos
riscos de uma má liberação quanto na compreensão dos requisitos do seu cliente de forma mais
eficaz. Aprenderás mais sobre isso no Capítulo 9.
Quando apropriado, as versões canárias são uma excelente opção, uma vez
que a percentagem de tráfego exposta ao canário é altamente controlada. A
solução de compromisso é que o sistema deve ter uma boa monitorização
para poder identificar rapidamente um problema e reverter, se necessário (o
que pode ser automatizado). Os canários têm a vantagem adicional de
apenas uma única nova instância ser criada; em estratégias como a blue-
green, é necessária uma segunda pilha completa de serviços. Isto pode
poupar custos e a complexidade operacional de executar dois ambientes em
paralelo.
Espelhamento de tráfego
Além de usar a divisão de tráfego para executar experimentos, você
também pode usar o espelhamento de tráfego para copiar ou duplicar o
tráfego e enviá-lo para um local adicional ou uma série de locais.
Frequentemente, com o espelhamento de tráfego, os resultados das
solicitações duplicadas não são retornados ao serviço de chamada ou ao
usuário final. Em vez disso, as respostas são avaliadas fora da banda para
correção, como a comparação dos resultados gerados por um serviço
refatorado e existente, ou uma seleção de propriedades operacionais é
observada à medida que uma nova versão de serviço lida com a solicitação,
como latência de resposta ou CPU necessária.
A utilização do espelhamento de tráfego permite-lhe "lançar às escuras" ou
"lançar às escuras" serviços, em que um utilizador não tem conhecimento
da nova versão, mas pode observar internamente o efeito pretendido. A
principal diferença é a capacidade de espelhar o tráfego, que durante a fase
de experimentação/lançamento duplica o pedido para o serviço v1.1 dos
participantes. Na Figura 5-3, as fases anterior e de implementação são
idênticas ao lançamento canário; frequentemente, a implementação escura é
referida como um canário especializado.
Figura 5-3. Implantação do serviço Attendee usando uma abordagem de espelhamento de tráfego
A implementação do espelhamento de tráfego na extremidade dos sistemas
tem-se tornado cada vez mais popular ao longo dos anos, e agora uma
malha de serviço permite que isto seja implementado de forma eficaz e
consistente em todos os serviços internos. Continuando com o exemplo do
lançamento de uma nova versão do serviço Attendee que implementa o
caching interno, o lançamento obscuro deste serviço permitir-lhe-ia avaliar
o desempenho operacional do lançamento, mas não o impacto comercial .
Azul-verde
Blue-green é geralmente implementado em um ponto da arquitetura que usa
um roteador, gateway ou balanceador de carga, atrás do qual fica um
ambiente azul completo e um ambiente verde. O ambiente azul atual
representa o ambiente ativo atual e o ambiente verde representa a próxima
versão da pilha. O ambiente verde é verificado antes da mudança para o
tráfego ativo e, quando entra em funcionamento, o tráfego é transferido do
azul para o verde. O ambiente azul está agora "desligado", mas se for
detectado um problema, é possível reverter rapidamente a situação. A
alteração seguinte passaria do verde para o azul, oscilando da primeira
versão em diante.
Na Figura 5-4, o serviço de conferência legado e o serviço Attendee estão
ambos na v1.0 e representam o nosso modelo azul. Durante a
implementação, pretendemos implementar o serviço de conferência legado
v1.1 e os Attendees v1.1 em conjunto, criando um ambiente verde. Durante
o passo de lançamento, a configuração é actualizada para direcionar o
gateway para o ambiente verde.
Figura 5-4. Implantação do serviço Attendee usando uma abordagem azul-verde
O Blue-green funciona bem devido à sua simplicidade e, para os serviços
acoplados, é uma das melhores opções de implementação. Também é mais
fácil gerir os serviços persistentes, embora seja necessário ter cuidado no
caso de um rollback. Também requer o dobro do número de recursos para
poder executar o cold em paralelo com o atual ambiente ativo .
Estudo de caso: Realização de rollouts com
o Argo Rollouts
As estratégias discutidas agregam muito valor, mas o lançamento em si é
uma tarefa que você não gostaria de gerenciar manualmente. É aqui que
uma ferramenta como o Argo Rollouts é valiosa para demonstrar
praticamente algumas das preocupações discutidas. Usando o Argo, é
possível definir uma CRD de lançamento que representa a estratégia que
você pode adotar para lançar um novo canário da sua v1.2 da API Attendee.
Uma Definição de Recurso Personalizado (CRD) permite que o Argo
estenda a API do Kubernetes para oferecer suporte ao comportamento de
lançamento. As CRDs são um padrão popular com o Kubernetes e
permitem que o usuário interaja com uma API com a extensão para oferecer
suporte a diferentes recursos.
No YAML de configuração a seguir, estamos executando cinco pods da API
Attendee e especificando uma abordagem canária para lançar o novo
recurso. Ao acionar o lançamento, 20% dos pods serão trocados pela nova
versão. A sintaxe {} na pausa diz ao Argo para aguardar a confirmação do
usuário antes de continuar:
apiVersion: [Link]/v1alpha1
kind: Rollout
metadata:
name: attendees
spec:
replicas: 5
strategy:
canary:
steps:
- setWeight: 20
- pause: {}
- setWeight: 40
- pause: {duration: 10}
- setWeight: 60
- pause: {duration: 10}
- setWeight: 80
- pause: {duration: 10}
revisionHistoryLimit: 2
selector:
matchLabels:
app: attendees-api
template:
metadata:
labels:
app: attendees-api
spec:
containers:
- name: attendees
image: jpgough/attendees:v1
Depois de instalar o Argo em nosso cluster e aplicar a configuração
anterior, o cluster terá cinco pods do serviço Attendee versão 1 em
execução. Um recurso muito bom do Argo é que o painel ajuda a visualizar
claramente o status atual do lançamento.A Figura 5-5 mostra o ponto inicial
do lançamento, executando cinco pods do serviço attendees v1.
Figura 5-5. Ponto de partida do Argo Rollouts
Executa o seguinte comando para introduzir o canário v1.2 na plataforma:
kubectl argo rollouts set image attendees
attendees=jpgough/attendees:v1.2
A Figura 5-6 mostra que o lançamento está na primeira etapa da estratégia,
com um peso de 20% agora definido para o canário para os participantes
v1.2. Como a interface do usuário demonstra, o lançamento está agora na
etapa de pausa, aguardando que a promoção manual seja acionada para
continuar o lançamento, seja a partir da interface do usuário ou da linha de
comando.
Figura 5-6. Canário Argo Rollouts
Neste exemplo simples, exploraste apenas o nível Kubernetes; no entanto, é
possível integrar totalmente as funcionalidades do service mesh para
controlar os lançamentos. Também é possível integrar com gateways de
entrada, como o NGINX e o Ambassador, para coordenar a gestão do
tráfego com o lançamento. Ferramentas como o Argo tornam os
lançamentos e os lançamentos baseados no tráfego bastante convincentes.
Além das etapas de promoção manual exploradas neste passo a passo,
também é possível conduzir a promoção com base na análise de métricas. A
seguir, um exemplo de um AnalysisTemplate que usa métricas do
Prometheus para observar a taxa de sucesso da implantação de um canário.
Essa etapa de análise pode ser representada na definição Rollout,
permitindo que o lançamento avance se os critérios de sucesso forem
atendidos:
apiVersion: [Link]/v1alpha1
kind: AnalysisTemplate
metadata:
name: success-rate
spec:
args:
- name: service-name
- name: prometheus-port
value: 9090
metrics:
- name: success-rate
successCondition: result[0] >= 0.95
provider:
prometheus:
address: "[Link]
{{[Link]-port}}"
A taxa de sucesso é uma métrica bastante simples; no entanto, há situações
em que as APIs falham que não são indicativas de uma falha na
infraestrutura, mas sim do pedido do cliente. Vamos explorar alguns dos
princípios-chave que são importantes de uma perspetiva de API que pode
utilizar para operar a fábrica e também informar as suas estratégias de
implementação .
Monitorização do sucesso e identificação de
falhas
Considera o estudo de caso do sistema de conferências antigo na Introdução
e como procederias para investigar um problema numa única aplicação. Um
único serviço tem um único ficheiro de registo para rastrear os pedidos e o
processamento pela aplicação. Separar vários serviços, como o serviço
Attendee, resulta num aumento da complexidade operacional. O maior
número de saltos entre os serviços introduz um potencial de falha e
encontrar manualmente o que correu mal torna-se rapidamente difícil.
Três pilares da observabilidade
Orientado por API arquitecturas são desacopladas e, sem o suporte
adequado, são complexas para raciocinar e resolver problemas. A
observabilidade fornece transparência no seu sistema, fornecendo uma
compreensão completa do que está a acontecer em todos os momentos. A
observabilidade é melhor descrita pelos três pilares, um mínimo operacional
necessário para raciocinar sobre a arquitetura distribuída:
Asmétricas são uma medida capturada em intervalos regulares que
representam um elemento importante para a saúde geral da plataforma.
As métricas podem estar em diferentes níveis na plataforma, e a
liberdade de estrutura significa que uma plataforma pode determinar
quais métricas são importantes para capturar. Por exemplo, uma
plataforma Java pode optar por capturar a utilização da CPU, o
tamanho atual do heap e o tempo de pausa da coleta de lixo (para citar
alguns).
Os registos são detalhes granulares do processamento de um
determinado componente e, muitas vezes, a qualidade dos registos está
intimamente ligada à aplicação ou ao componente de infraestrutura que
os emite. O formato dos registos influencia significativamente a
utilidade da pesquisa e do processamento dos dados de registo, com o
registo estruturado a facilitar uma melhor pesquisa e recuperação de
dados relevantes.
Os rastreios são essenciais quando se muda para uma arquitetura
distribuída, permitindo o rastreio de cada pedido através de todos os
componentes com os quais se interage na arquitetura. Por exemplo, se
um pedido falhar, o rastreio permitir-lhe-á localizar rapidamente o
componente exato da arquitetura que está a falhar. O rastreio funciona
adicionando um cabeçalho único o mais próximo possível da origem
do pedido; este cabeçalho é propagado em todo o processamento
subsequente de um determinado pedido. Se o contexto do pedido
passar para um tipo diferente de infraestrutura (por exemplo, uma fila),
o cabeçalho único será registado no envelope da mensagem.
Podes encontrar uma introdução mais detalhada em Distributed Systems
Observability (O'Reilly) de Cindy Sridharan.
AVISO
Implementar os três pilares em toda a plataforma não é suficiente. Em "Lendo os Sinais",
abordaremos como utilizar os três pilares da observabilidade para operar a infraestrutura
envolvida com uma plataforma de API.
Para os três pilares da observabilidade, o projeto OpenTelemetry é o melhor
lugar para começar. O projeto fornece um padrão aberto na Cloud Native
Computing Foundation (CNCF), evitando a dependência de fornecedores e
facilitando a maior compatibilidade possível. Embora os padrões de
métricas e rastreamento tenham sido criados e sejam estáveis, o registro é
um problema um pouco mais difícil de resolver (devido à vasta gama de
diferentes emissores possíveis), mas também é coberto pelo projeto
OpenTelemetry .
Métricas importantes para APIs
Considerando quais métricas são importantes para uma plataforma de API é
uma decisão-chave que ajudará a descobrir interrupções antecipadamente e,
possivelmente, até mesmo evitá-las. Você pode medir e reunir uma ampla
gama de métricas diferentes, mas algumas métricas também dependerão da
sua plataforma. Métricas de Taxa, Erro, Duração (RED) são frequentemente
observadas como uma abordagem para medir arquiteturas de serviço
baseadas em tráfego. Parte do apelo é que essas métricas fornecem uma boa
visão geral do que está acontecendo em um determinado momento. A taxa
mostra quantas solicitações por segundo um serviço está processando (ou
throughput), quais erros são retornados e a duração (ou latência) de cada
solicitação. No mundo da Engenharia de Confiabilidade de Sites (SRE),
essas métricas nos ajudam a derivar os Quatro Sinais deOuro - latência,
tráfego, erros e saturação.
Por exemplo, todos os erros de uma API são causados por um serviço na
cadeia de pedidos? Para APIs, o contexto do erro é realmente importante -
por exemplo, um erro de intervalo 5xx é importante, pois destaca uma falha
causada por um componente ou serviço de infraestrutura. Um erro 4xx não
é um problema de serviço e é mais um problema do cliente, mas podes
simplesmente ignorar este código de erro? Uma série de erros 403
Forbidden pode indicar que um ator malicioso está a tentar aceder a dados a
que não tem direito. Este é um exemplo de como o contexto é crítico, e o
tempo gasto a investigar que métricas são importantes leva o raciocínio da
API para além das métricas RED.
Métricas importantes devem estar associadas a alertas, para garantir que se
pode lidar rapidamente com os problemas (ou problemas futuros). É
necessário ter cuidado ao definir alertas para evitar falsos positivos. Por
exemplo, se for gerado um alerta em caso de pouca ou nenhuma atividade,
este pode ser acionado em feriados ou fins de semana. Ter este tipo de alerta
programado apenas para o horário comercial principal pode ajudar, ou
talvez associá-lo ao número atual de logins no site.
No nosso estudo de caso do sistema de conferência, os seguintes exemplos
seriam considerados métricas importantes a captar:
O número de pedidos de participantes por minuto.
O objetivo de nível de serviço (SLO) para os participantes é a latência
média das respostas. Se a latência começar a desviar-se
significativamente, pode ser o primeiro sinal de um problema.
O número de 401s do sistema CFP pode indicar um comprometimento
do fornecedor ou um token roubado.
Mede a disponibilidade e o tempo de funcionamento do serviço
Attendee.
Utiliza a memória e a CPU das aplicações.
O número total de participantes no sistema .
Lê os sinais
Até agora discutimos a observabilidade e porque é importante, juntamente
com o objetivo de cada pilar. Analisámos algumas métricas chave para
APIs, mas também acrescentámos um aviso de que a implementação por si
só ou métricas sem contexto não é suficiente. Mencionámos a ideia de
capturar métricas da aplicação em execução, como o tempo de recolha de
lixo. O aumento do tempo gasto na recolha de lixo pode ser um sintoma
precoce de que a sua aplicação está prestes a falhar. As recolhas de lixo
normalmente gastam tempo a fazer pausas nas aplicações, o que, por sua
vez, resulta em atrasos nos pedidos e pode ter impacto na latência. Detetar
isto precocemente é o equivalente a um motor de um carro que faz um
barulho estranho; ainda funciona, mas algo não está bem.
Para ler os sinais, estabelecer uma expetativa ou linha de base é realmente
útil e, em seguida, medir dentro desse intervalo e alertar quando estiver fora
do intervalo pode ajudar a detetar um problema. O próximo passo seria
observar a métrica real da latência da API que está sendo afetada - o
equivalente à luz de verificação do motor que está aparecendo agora.
Quanto mais cedo você puder ler os sinais de um problema potencial,
menor será a probabilidade de haver um problema que afete o cliente. Se
ambas as medidas forem ignoradas, a aplicação acabará caindo, deixando a
equipe lutando para consertá-la.
Compreender o software e a ligação com as principais métricas ajuda a criar
uma plataforma operacional madura com identificação precoce e,
esperemos, resolução de problemas. Nas arquitecturas distribuídas, as falhas
são inevitáveis e, num cenário de interrupção, os rastreios seriam o primeiro
ponto de contacto para descobrir a causa principal. Já vimos demorar horas
a descobrir a causa de um problema sem ferramentas como o rastreio, com
os programadores transformados em detectives a analisar os registos para
tentar encontrar pistas sobre o "culpado". Se a primeira vez for quando todo
o tráfego da API não estiver a funcionar, vai ser stressante (e possivelmente
com impacto no negócio ).
Decisões de aplicação para lançamentos de
software eficazes
As arquitecturas distribuídas introduzem novos desafios e considerações
para o lançamento de software e requerem alterações ao nível da aplicação.
Nesta secção, irá explorar alguns dos problemas ao lançar numa arquitetura
distribuída e como resolvê-los.
Cache de respostas
Cache de respostas pode ser um problema real quando se trata de
componentes de aplicativos, em particular gateways e proxies. Considere o
seguinte cenário. Tentamos efetuar um lançamento canário do serviço
Attendee e tudo parece estar a correr bem, pelo que prosseguimos com o
lançamento de todos os novos serviços. No entanto, o serviço que chama
GET/attendees estava a utilizar um proxy, que agora é devolvido,
produzindo 500s em todo o lado. Acontece que o resultado em cache estava
a mascarar o facto de o nosso novo software estar avariado.
Para evitar o armazenamento em cache dos resultados, é importante definir
um cabeçalho no cliente que faz o pedido GET, ou seja, o cabeçalho do
pedido GET, Cache-Control: no-cache, no-
storeEventualmente, a cache expirará e obteremos um estado consistente.
Propagação de cabeçalho ao nível da aplicação
Todos os serviços da API que encerram um pedido de API e criam um
pedido para outro serviço precisam de copiar cabeçalhos do pedido
encerrado para o novo pedido. Por exemplo, quaisquer cabeçalhos
relacionados com o rastreio ou a observabilidade precisam de ser
adicionados ao pedido a jusante para garantir que o rastreio distribuído é
observado.
Para os cabeçalhos de autenticação e autorização, é importante ter uma
opinião sobre o que pode ser enviado com segurança a jusante. Por
exemplo, encaminhar um cabeçalho de autenticação pode fazer com que um
serviço seja capaz de se fazer passar por outro serviço ou utilizador,
causando problemas. Um token de suporte OAuth2, no entanto, é seguro
para enviar a jusante (desde que o transporte seja seguro).
Registo para auxiliar a depuração
As coisas vão dar errado em uma arquitetura distribuída! Muitas vezes, ser
capaz de ver que uma solicitação chegou a um serviço é realmente valioso,
especialmente se você não considerar o cache. É útil pensar em logs em
dois tipos diferentes: diário e diagnóstico. Um diário permite a captura de
transações/eventos importantes dentro do sistema e é usado com
moderação. Um exemplo de um evento de diário é a receção de uma nova
mensagem para processar e o resultado desse [Link] diagnósticos estão
mais preocupados com falhas no processamento e quaisquer erros
inesperados fora de um evento baseado em diário. Como parte do registo
estruturado, pode adicionar um campo para representar o tipo de registo,
permitindo um acesso rápido apenas a diários ou a diagnósticos completos.
Considera uma plataforma de opinião
Muitas vezes não há uma decisão consciente sobre a abordagem a adotar
em relação às decisões que abordámos nesta secção, o que pode levar a
trabalho repetido ou a abordagens inconsistentes. Uma opção para resolver
este problema é criar uma equipa de plataforma e desenvolver uma
plataforma de opinião. A plataforma de opinião tomaria decisões-chave
sobre a forma de resolver problemas como parte da plataforma técnica,
evitando a necessidade de todos os programadores implementarem as
mesmas funcionalidades da plataforma.
Para que as plataformas opinativas sejam bem-sucedidas, precisam de
melhorar o caminho para a produção, tendo em conta o DevOps e outros
factores-chave necessários para operar na plataforma. Isto é muitas vezes
referido como o caminho pavimentado ou o caminho dourado para a
produção. Criar uma plataforma que as equipas de desenvolvimento
queiram utilizar e que facilite a resolução de problemas empresariais terá
uma probabilidade muito maior de adoção. É importante lembrar que a
criação de opiniões cria restrições, pelo que existe uma solução de
compromisso entre a liberdade do programador e as aplicações que
funcionam como esperado dentro de uma organização.
Diretrizes ADR: Plataformas de opinião
A escolha de criar uma plataforma de opinião é mais bem sucedida quando
os criadores da plataforma estão envolvidos no processo de conceção. Na
diretriz da Tabela 5-3, explora os pontos a considerar e a importância de
envolver os criadores para criar uma plataforma de opinião bem sucedida.
Tabela 5-3. Diretriz ADR: Plataformas de opinião
Decisão Deves adotar uma plataforma opinativa para as tuas implementações e
lançamentos?
Pontos de discussão Quais são as nossas linguagens de desenvolvimento de software na
organização? É possível centrarmo-nos em alguns para viver dentro da
plataforma de opiniões?
A organização está configurada de forma a que possas capacitar os
programadores como clientes e gerir a plataforma de opinião como um
produto interno?
Quais são as restrições ou caraterísticas que vão acrescentar benefícios à
introdução de uma plataforma? Por exemplo, a monitorização e a
observabilidade devem ser caraterísticas fornecidas de imediato aos
programadores?
Como é que actualizas as recomendações da plataforma e ajudas a fornecer
alterações às equipas que já utilizam a plataforma?
Recomendações Considera os programadores como clientes do produto da plataforma e cria
um mecanismo que permita aos programadores darem o seu contributo.
As principais caraterísticas devem ser tão transparentes quanto possível para
os programadores (por exemplo, configura uma biblioteca para introduzir a
telemetria aberta).
As novas aplicações obtêm sempre as funcionalidades mais recentes da pilha.
No entanto, como é que garante que os utilizadores da plataforma existentes
podem aceder facilmente às funcionalidades mais recentes do ?
Resumo
Neste capítulo, apresentámos uma introdução à implementação e
distribuição de software numa arquitetura de API:
Um ponto de partida valioso é compreender a importância de separar a
implantação do lançamento. Nas aplicações existentes, a marcação de
funcionalidades é uma abordagem para configurar e ativar novas
funcionalidades ao nível do código.
A gestão do tráfego oferece uma nova oportunidade de utilizar o
encaminhamento do tráfego para modelar as libertações.
As versões principais, secundárias e de correção ajudam a separar o
estilo das opções de lançamento. As aplicações que têm uma API
fortemente acoplada podem utilizar uma estratégia diferente.
Revistaste as estratégias de lançamento e as situações em que se
aplicam, e viste como ferramentas como o Argo podem ajudar a
facilitar os lançamentos de forma eficaz.
O monitoramento e as métricas são uma importante medida de sucesso
em uma plataforma de API. Aprendeste uma cartilha sobre
observabilidade e porque é que a aplicação destas tecnologias é
fundamental para operar com sucesso uma plataforma de API.
Por fim, exploraste as decisões de aplicação para apoiar
implementações eficazes e o que os proprietários de plataformas
podem querer considerar quando pretendem obter consistência em toda
a fábrica.
Implementar e lançar APIs de forma eficaz é fundamental para uma
arquitetura orientada para APIs bem sucedida. No entanto, é importante
pensar nas ameaças à segurança que os sistemas de APIs enfrentarão e
considerar como mitigar eficazmente o risco. Este é o foco do Capítulo 6.
1 Nome dado aos canários que entravam primeiro nas minas de carvão para identificar
fatalmente a presença de gases perigosos.
Capítulo 6. Segurança
operacional: Modelagem de
ameaças para APIs
Este trabalho foi traduzido com recurso a IA. Agradecemos o teu feedback e comentários:
translation-feedback@[Link]
Nesta fase, exploraste todo o ciclo de vida da API, tendo em consideração a
conceção e os testes, as opções de implementação e as estratégias de
lançamento de APIs. A API de participantes pode parecer estar pronta para
ser exposta a sistemas externos. As APIs são rápidas de construir, difíceis
de conceber para compatibilidade futura e ainda mais difíceis de proteger. A
verdade é que os programadores e arquitectos se concentram na entrega de
funcionalidades e a segurança só é muitas vezes considerada no final do
projeto.
Neste capítulo, verá porque é que a segurança é importante e como é que
não ter uma segurança adequada pode prejudicar a sua reputação e ser
dispendioso. Aprenderá a examinar a arquitetura de um sistema para detetar
fraquezas de segurança e determinar as ameaças que podem ser encontradas
num ambiente de produção. Claro que não será capaz de identificar todas as
ameaças - os atacantes são desonestos e o cenário de ameaças evolui
continuamente - mas a competência crítica para os arquitectos é ser capaz
de "deslocar para a esquerda" o design e a implementação de preocupações
de segurança, tanto para eles próprios como para as equipas de
desenvolvimento mais alargadas.1 Quanto mais cedo considerar a segurança
no seu ciclo de vida de desenvolvimento de software (ou seja, quanto mais
à esquerda puder ser deslocada), de um modo geral, mais fácil e mais
rentável será a adaptação ao cenário de ameaças em evolução. Isto irá
ajudá-lo a tomar decisões informadas quando se envolver na conceção de
segurança para APIs.
Em "Aplica a segurança: Segurança de transporte, autenticaçãoe
autorização", analisámos como é possível proteger a comunicação dentro de
um plano de controlo ou sistema utilizando o mTLS. No entanto, quando
são introduzidos sistemas "externos" fora do alcance do plano de controlo, é
necessária uma nova abordagem.
Estudo de caso: Aplicando o OWASP à API
do participante
Tu iniciarás a tua viagem rumo à conceção de sistemas seguros com uma
introdução à modelação de ameaças. Em seguida, explorarás a forma de
realizar um exercício de modelação de ameaças, utilizando o serviço
Attendee e a API como exemplo, conforme apresentado na Figura 6-1.
Figura 6-1. A API do participante que será usada no exercício de modelagem de ameaças
Um componente central da modelagem de ameaças é a procura de possíveis
fraquezas de segurança, portanto, você explorará o Top 10 de segurança de
APIs do OWASP, que pode ser usado como fonte de inspiração ao procurar
problemas e como fonte de atenuações ao tentar lidar com as ameaças
encontradas. No final do capítulo, você entenderá o que é a modelagem de
ameaças e como pode aplicá-la a seus próprios projetos.2
O Open Web Application Security Project (OWASP) é uma fundação sem
fins lucrativos que trabalha para melhorar a segurança do software. O
projeto mais conhecido do OWASP é o OWASP Top 10; este projeto é uma
lista dos riscos de segurança mais críticos enfrentados pelas aplicações
Web. Em 2019, o OWASP produziu uma nova lista dos 10 principais - este
foi o API Security Top 10. A lista é baseada no trabalho de especialistas em
segurança que examinaram violações de segurança e programas de
recompensa por bugs, e os testadores de penetração também deram sua
opinião sobre o que deveria estar neste top 10. Esta não é uma lista
exaustiva de todas as ameaças que você enfrentará. No entanto, você deve
mantê-las em mente ao analisar como sua API pode ser explorada. Essas
listas são atualizadas periodicamente, por isso é importante procurar
alterações e atualizações no top 10 à medida que elas evoluem.
O risco de não proteger APIs externas
Embora a segurança se tenha tornado mais apelativa e tenha sido trazida
para a ribalta como tópico, tem lutado para ganhar a mesma popularidade
de tecnologias como a aprendizagem automática, os grandes dados e a
computação quântica,3 Para a maioria dos profissionais de software, a
segurança nem sempre está na primeira linha das suas mentes. Os
programadores estão concentrados na codificação de soluções empresariais,
as equipas SRE garantem que a fábrica está a funcionar e os proprietários
de produtos concentram-se no planeamento de novas funcionalidades
valiosas. A segurança é muitas vezes adiada e, se tiveres a sorte de ter uma
equipa de segurança, pode ser delegada a essa equipa. O valor percebido
pelo cliente não está (normalmente) nos controlos de segurança
implementados, mas sim no serviço que o teu sistema fornece.
Financeiramente, os impactos são enormes: "o custo médio de uma violação
cibernética para uma empresa de capital aberto foi de 116 milhões de
dólares" e o custo médio de uma violação de dados para uma organização
em 2021 foi de 4,24 milhões de dólares, um aumento de 10% em relação ao
ano anterior.
De seguida, apresentamos alguns exemplos de violações de segurança que
tiveram um custo enorme, tanto a nível financeiro como social:
Bases de dados vazam dados de 419 milhões de utilizadores
A violação de dados afecta 143 milhões de americanos
Violação de segurança expõe informações pessoais de 47 milhões de
utilizadores
Acordo de 17,5 milhões de dólares sobre violação de dados
106 milhões de registos de clientes roubados e uma multa de 80
milhões de dólares
Multa de 16,4 milhões de libras por falhas relacionadas com um
ciberataque
Os dois últimos artigos são interessantes, pois os reguladores emitiram
penalidades por violar as regras regulamentares ou não responder
adequadamente. É importante analisar o seu ambiente operacional para ver
quais são os requisitos existentes para a governança de dados do cliente.
Uma suposição justa dos usuários é que estão sendo tomadas medidas
adequadas para proteger sua privacidade e seus dados; caso contrário, sua
organização é responsável. Um desses requisitos regulamentares é o
Regulamento Geral sobre a Proteção de Dados (RGPD) de , que confere um
maior controlo aos indivíduos sobre as suas informações pessoais e que
pode acarretar graves sançõesfinanceiras se não for cumprido. Atualmente,
as maiores multas emitidas por violação do RGPD incluem a Amazon, com
uma multa de 636 milhões de libras, e o WhatsApp, com uma multa de 225
milhões de euros.
AVISO
A responsabilidade de uma organização vai para além das API e dos sistemas desenvolvidos pela
organização. Os produtos dos fornecedores e o software de código aberto apresentam desafios
reais se não forem cuidadosamente geridos. Assegure-se de que os produtos dos fornecedores são
mantidos com o mesmo padrão que manteria com os seus próprios padrões de desenvolvimento de
software. As vulnerabilidades do software de código aberto podem ser de grande alcance.
Assegurar que uma organização acompanha as Vulnerabilidades e Exposições Comuns (CVE) e é
capaz de reconstruir o software afetado é fundamental.
Modelação de ameaças 101
Modelação de ameaças é uma "técnica que podes utilizar para te ajudar a
identificar ameaças, ataques, vulnerabilidades e contramedidas que podem
afetar a tua aplicação". Para utilizar uma analogia do mundo real, se
estivesses a realizar um exercício de modelação de ameaças para a tua casa
ou apartamento, identificarias coisas como pontos de entrada (portas,
Windows) e se deste a chave da porta da frente a um vizinho. Esta
abordagem é benéfica, uma vez que só é possível mitigar os riscos de
segurança depois de as ameaças terem sido claramente identificadas, além
de ajudar a dar prioridade aos esforços para melhorar a segurança e evitar
esforços sem sentido ou teatro de segurança. Para continuar com o exemplo
da casa, não seria benéfico se gastasses uma grande quantia de dinheiro
numa porta da frente reforçada com aço, mas deixasses a chave debaixo do
capacho ou no vaso de flores do lado de fora.
A modelação de ameaças é um processo que deve ser integrado em todo o
ciclo de vida de desenvolvimento de software. Idealmente, é realizada no
início de um projeto e é continuamente revisitada à medida que o sistema e
a arquitetura evoluem. A boa notícia é que existem várias metodologias
bem definidas para a modelação de ameaças. Neste livro, utilizaremos a
metodologia STRIDE concebida por Praerit Garg e Loren Kohnfelder na
Microsoft. Aprenderá mais sobre esta metodologia mais adiante neste
capítulo.
Modelagem de ameaças de sistemas de software tem sido historicamente
realizada usando diagramas de fluxo de dados (DFDs).4 Os DFDs capturam
os aspectos dinâmicos (fluxo de dados) de um sistema, enquanto os
modelos C4 capturam principalmente os aspectos estáticos (estruturais) do
sistema. Os DFDs são simples de entender e centrados nos dados, o que
facilita a visualização de como os dados fluem pelo sistema. Os
componentes principais dos DFDs são:
Entidades externas
Estas são aplicações/serviços que não fazem parte do teu sistema. No
nosso caso, seria a aplicação móvel.
Processos
Uma aplicação/tarefa que está no nosso domínio, como o gateway da
API.
Armazéns de dados
Um local onde os dados são armazenados. No caso do estudo de caso,
seria a base de dados.
Fluxos de dados
Ligação que representa o fluxo de dados, como a aplicação móvel para
o gateway da API.
Limites
Um limite privilegiado ou de confiança para mostrar uma alteração nos
níveis de confiança. Um limite para o estudo de caso seria o limite da
Internet entre a aplicação móvel e o gateway da API.
Como parte de nossa modelagem de ameaças, criamos um DFD conforme
mostrado em na Figura 6-2.
Pensa como um atacante
Arquitectos e as equipas de desenvolvimento podem, por vezes, mostrar-se
relutantes em considerar as questões de segurança, pois acreditam que esta
é uma tarefa de uma equipa especializada. No entanto, quem melhor do que
as pessoas que concebem e constroem os principais componentes estruturais
de um sistema de software para identificar e compreender as potenciais
fraquezas? Os arquitectos e os especialistas em segurança podem então
colaborar na resolução destes problemas e trabalhar em conjunto para
explorar diferentes ângulos de ataque. A boa notícia é que, para realizar um
exercício de modelação de ameaças, não precisa de ser um especialista em
segurança, mas precisa de pensar como um atacante ou mau ator.
Por exemplo, quando estacionas o carro à noite, o que fazes com as chaves
do carro? Deixas as chaves no carro? Provavelmente não se o carro for
deixado na rua, mas podes fazê-lo se estiver numa garagem. Podes deixar as
chaves junto à porta da frente. No entanto, alguém pode usar um cabide
através da caixa de correio para levar as chaves ou, se for um carro sem
fios, o atacante pode usar a amplificação do sinal. Então, leva-as para cima?
E com o aumento dos sistemas de fecho eletrónico e dos imobilizadores,
coloca-as numa gaiola de Faraday? O que estás a fazer aqui é olhar para
uma situação e avaliar a ameaça e ponderar o risco. Agora precisas de
aplicar esta abordagem à conceção de sistemas de software, com uma
pequena ajuda das metodologias bem definidas existentes.
Como usar o modelo de ameaça
Tal como acontece com muitas metodologias no âmbito da conceção e
desenvolvimento de software, existem objectivos, abordagens e técnicas
bem definidos para a modelação de ameaças que os arquitectos e
engenheiros têm vindo a aperfeiçoar ao longo dos anos. A abordagem de
alto nível à modelação de ameaças é:
1. Identifica os teus objectivos - Cria uma lista dos objectivos comerciais
e de segurança. Mantém-nos simples (por exemplo, evitar o acesso não
autorizado).
2. Recolhe a informação certa - Gera uma conceção de alto nível do
sistema e assegura-te de que tens a informação certa. Para conseguires
compreender como é que os teus sistemas funcionam e trabalham em
conjunto, isto inclui ter as pessoas certas envolvidas na conversa.
3. Decompor o sistema - Decompõe o desenho de alto nível para que
possas começar a modelar as ameaças, o que pode exigir vários
modelos e diagramas.
4. Identificar ameaças - Procura sistematicamente ameaças aos teus
sistemas.
5. Avalia o risco das ameaças - Prioriza as ameaças para se concentrar
nas mais prováveis e, em seguida, identifica as atenuações para essas
ameaças prováveis.
6. Validar - Pergunta a ti próprio e à tua equipa se as alterações
introduzidas foram bem sucedidas. Deverás efetuar outra revisão?
Vamos agora explorar estes passos com mais pormenor, utilizando o estudo
de caso como o sistema em que pretendes realizar um exercício de
modelação de ameaças.
Etapa 1: Identificar os teus objectivos
O primeiro passo da modelação de ameaças é identificar os seus objectivos;
este é o motor para a realização da modelação de ameaças. Ao decidir os
objectivos para os seus próprios sistemas, deve concentrar-se nos objectivos
de segurança que está a tentar alcançar. Estes objectivos devem ser
provenientes de toda a organização e não apenas da sua equipa e das
equipas de InfoSec. Os objectivos de segurança são muitas vezes orientados
por objectivos comerciais, como evitar a fuga de dados para evitar ser
processado ou estar em conformidade com regulamentos como o GDPR. Se
estes forem apenas provenientes da tua área imediata, então não tens uma
imagem completa dos problemas mais importantes que a tua organização
enfrenta. Os teus objectivos para o serviço Attendee são preparar a API para
consumo externo por terceiros, garantindo que os OWASP Top 10 são
mitigados.
Passo 2: Recolhe as informações corretas
Uma vez que tens os objetivos em mente, o Passo 2 da modelagem de
ameaças é a aquisição de informações sobre como o sistema funciona. Com
a modelagem de ameaças, é necessário trazer especialistas em cada área do
sistema e bases de código ou produtos associados. Isto é para garantir que
compreendes como tudo funciona e que não são feitas suposições ocultas.
Para a API do Participante, isto exigirá trazer membros da equipa que
trabalham em todos os teus componentes; móvel, gateway, bases de dados e
serviço do Participante.
Passo 3: Decompõe o sistema
O terceiro passo do processo de modelação de ameaças é criar um diagrama
do sistema que mostre as interações dos componentes com o fluxo de
dados. As informações recolhidas de forma colaborativa são depois
utilizadas para criar os DFDs. A criação de diagramas pode ser morosa,
pelo que recomendamos a utilização de ferramentas de modelação de
ameaças dedicadas. Para o diagrama de fluxo de dados do estudo de caso,
apresentado na Figura 6-2, utilizámos a Microsoft Threat Modeling Tool,
embora existam outras ferramentas disponíveis.5
Figura 6-2. Diagrama de fluxo de dados
Etapa 4: Identificar as ameaças - Fazendo isto no teu
STRIDE
O quarto passo da modelação de ameaças consiste em analisar as ameaças
ao sistema. Quando se começa a analisar o diagrama de fluxo de dados, é
importante ter em mente os objectivos da modelação de ameaças, caso
contrário, pode ser tentador sair pela tangente.
A vantagem de usar a ferramenta dedicada de modelagem de ameaças da
Microsoft é que ela pode realizar algumas análises automatizadas para você
usando a metodologia STRIDE. A lista gerada não está completa, mas pode
ser usada como ponto de partida. A lista de ameaças geradas para nosso
Sistema de API de Participantes é vista na Figura 6-3. Nesse caso, a
ferramenta encontrou 27 ameaças potenciais.
Figura 6-3. Diagrama de fluxo de dados da análise de ameaças
O acrónimo STRIDE significa:6
Falsificação
Violação das informações de autenticação do utilizador. Neste caso, o
hacker obteve as informações pessoais do utilizador ou algo que lhe
permite repetir o procedimento de autenticação. As ameaças de
spoofing estão associadas à capacidade de um hacker astuto se fazer
passar por um utilizador ou recurso válido do sistema para obter acesso
ao sistema e, assim, comprometer a segurança do mesmo.
Adulteração
Modificar dados do sistema ou do utilizador com ou sem deteção. Uma
alteração não autorizada de informações armazenadas ou em trânsito, a
formatação de um disco rígido, um intruso malicioso que introduz um
pacote de rede indetetável numa comunicação e uma alteração
indetetável de um ficheiro sensível são ameaças de adulteração.
Repúdio
Um utilizador não fiável que executa uma operação ilegal sem poder ser
localizado. As ameaças de repúdio estão associadas a utilizadores
(maliciosos ou não) que podem negar um ato ilícito sem qualquer forma
de provar o contrário.
Divulgação de informações
Comprometer as informações privadas ou críticas para a empresa do
utilizador. As ameaças de divulgação de informações expõem as
informações a indivíduos que não as devem ver. A capacidade de um
utilizador ler um ficheiro ao qual não lhe foi concedido acesso, bem
como a capacidade de um intruso ler os dados enquanto estão em
trânsito entre dois computadores, são ambas ameaças de divulgação.
Note-se que esta ameaça difere de uma ameaça de falsificação na
medida em que aqui o criminoso obtém acesso à informação
diretamente em vez de ter de falsificar um utilizador legítimo.
Negação de serviço
Tornar o sistema temporariamente indisponível ou inutilizável, como os
ataques que podem forçar uma reinicialização ou reinício da máquina
do utilizador. Quando um atacante pode tornar temporariamente os
recursos do sistema (tempo de processamento, armazenamento, etc.)
indisponíveis ou inutilizáveis, temos uma ameaça de negação de
serviço. Devemos proteger-nos contra certos tipos de ameaças DoS para
melhorar a disponibilidade e fiabilidade do sistema. No entanto, alguns
tipos de ameaças DoS são muito difíceis de proteger, portanto, no
mínimo, devemos identificar e racionalizar essas ameaças.7
Elevação de privilégio
Um utilizador sem privilégios obtém acesso privilegiado e, assim, tem
acesso suficiente para comprometer completamente ou destruir todo o
sistema. O aspeto mais perigoso de tais ameaças é comprometer o
sistema de formas indetectáveis, através das quais o utilizador consegue
tirar partido dos privilégios sem o conhecimento dos administradores do
sistema. As ameaças de elevação de privilégios incluem as situações em
que um atacante tem mais privilégios do que os que lhe deveriam ser
concedidos, comprometendo completamente a segurança de todo o
sistema e causando danos extremos ao sistema. Neste caso, o atacante
penetrou efetivamente em todas as defesas do sistema e tornou-se parte
do próprio sistema de confiança, podendo fazer qualquer coisa.
Podes utilizar este acrónimo quando avalias o teu sistema em cada ponto da
tua arquitetura para ver que ameaças existem. Existem também outras
metodologias de modelação de ameaças que podem ser utilizadas.8
Ao observar o diagrama de fluxo de dados na Figura 6-2, é possível ver o
limite que existe entre o aplicativo cliente e o gateway de API. Um gateway
de API geralmente está localizado na borda da nossa rede e também pode
estar voltado para a Internet, como você aprendeu em "Onde é implantado
um gateway de API?". Você vai explorar várias ameaças diferentes
relacionadas ao gateway de API e aprender como isso pode ser usado para
proteger seu sistema contra muitas das vulnerabilidades comuns da API. Se
proteger o seu sistema no limite, os riscos podem ser reduzidos em todo o
sistema, mas nem sempre é esse o caso. Aprenderá mais sobre a mudança
da arquitetura zonal, em que o tráfego dentro do perímetro de segurança é
tratado de forma diferente do tráfego exterior, para modelos de confiança
zero, em que o tráfego é constantemente reautenticado, em "From Zonal
Architecture to Zero Trust".
Os objetivos de segurança do seu estudo de caso são bastante específicos: a
API do Participante deve ser preparada para consumo externo e, para isso,
garantiremos que cada processo mitigue os 10 principais problemas de
segurança da API da OWASP. Como esse é um objetivo direto, o DFD pode
ser usado para mapear os fluxos de dados para os problemas e
vulnerabilidades listados no site da OWASP. No entanto, normalmente, um
objetivo de modelação de ameaças pode ser algo como "Impedir a fuga de
dados de PII para estar em conformidade com o GDPR" ou "Fornecer
99,9% de disponibilidade para as APIs para cumprir as obrigações
contratuais". Este segundo objetivo pode não parecer estar relacionado com
a segurança, no entanto, deve manter o DoS na sua mente, uma vez que o
não cumprimento desta obrigação, mesmo quando sob um ataque DoS,
pode resultar numa penalização financeira.
Vamos agora rever o sistema e aplicar o STRIDE. Para destacar o OWASP
API Security Top 10, as ameaças serão agrupadas sob o valor STRIDE
aplicável. Isto serve para mostrar tanto a aplicação do STRIDE como o
OWASP API Security Top 10, juntamente com as suas mitigações. Quando
estiveres a identificar ameaças na tua própria arquitetura, recomenda-se que
apliques o STRIDE a cada processo e ligação - isto é conhecido como
STRIDE por elemento.
Falsificação
Spoofing é quando uma pessoa ou programa é capaz de se mascarar como
outra pessoa ou programa. Para mitigar isso, você vai querer autenticar
todos os pedidos que são feitos e garantir que eles são legítimos. Dentro do
Top 10 da API OWASP, um dos problemas de segurança é a Autenticação
de usuário quebrada. Isso está definitivamente relacionado à categoria de
spoofing, então você vai querer garantir que o fluxo de autenticação não
seja quebrado. Para saber mais sobre isso, "Autenticação" fornece
informações e um exemplo usando o estudo de caso.
Adulteração
Em seguida, em a metodologia STRIDE é a "adulteração", com o objetivo
de que os usuários ou clientes não possam modificar o sistema, a aplicação
ou os dados de forma não intencional. Por exemplo, não deve ser possível
que um mau ator possa modificar o serviço Attendee redirecionando o
tráfego destinado ao serviço Attendee para um local externo, ou atualizando
os dados do usuário participante de forma inadequada.
Injeção de carga útil
Injeção de carga útil ocorre quando um mau ator tenta injetar uma carga útil
maliciosa no pedido feito a uma API ou aplicação. Note-se que, no Top 10
de segurança da OWASP, isto está relacionado não só com a injeção de
SQL comummente conhecida, mas também com a injeção de qualquer
entrada de utilizador. No estudo de caso, pode tentar evitar ataques de
injeção no início da cadeia de tratamento de pedidos, utilizando o gateway
da API para validar que o pedido efectuado está em conformidade com um
contrato ou esquema definido. Qualquer pedido que não cumpra o contrato
pode ser recusado ou o tráfego correspondente pode ser rejeitado. Esta
abordagem é descrita em "Aplicação prática das especificações OpenAPI".
Cada vez mais, as especificações OpenAPI são utilizadas para validar
pedidos HTTP.
Vale a pena mencionar que, embora a validação de entrada seja valiosa
quando realizada no gateway da API, isso não significa que possas omitir a
validação e a sanitização de entrada adicionais nos serviços de backend;
confia, mas verifica!
Um exemplo disto para o serviço Attendee seria receber o seguinte pedido
POST com este exemplo de carga útil para criar um utilizador:
POST /attendees
{
"name": "Danny B",
"age": 35,
"profile": "Hax; DROP ALL TABLES; --"
}
A especificação OpenAPI para a API Attendee define que name deve
aceitar apenas letras, age aceita números inteiros positivos e profile
aceita letras, números e caracteres especiais no valor (porque é para o
usuário escrever um pouco sobre si mesmo). O gateway da API, que neste
caso está realizando a validação de entrada, inspecionará o payload e só o
deixará passar se a validação de entrada for bem-sucedida. Mesmo que a
validação de entrada seja aprovada, a API Attendee ainda deve sanitizar a
entrada para evitar um ataque. O serviço Attendee usaria instruções
preparadas ao se comunicar com o banco de dados. É importante ter várias
linhas de defesa caso uma delas falhe.
Atribuição em massa
Propriedades modificáveis que são delimitadas a entidades de banco de
dados são vulneráveis a alterações inadequadas. Elas podem ser exploradas
pela vulnerabilidade conhecida como atribuição em massa. Este é um caso
importante a ser considerado, particularmente se a sua aplicação subjacente
usa o padrão Active Record9 ou alguma forma de
serialização/desserialização automatizada de entidades da base de dados,
como é frequentemente fornecido por estruturas de mapeamento objeto-
relacional (ORM).
Vamos examinar um caso hipotético para a nossa API Attendee. Imagina
que existe uma propriedade chamada devices que é devolvida quando se
faz um pedido para um participante. Esta propriedade foi concebida para ser
uma lista externa só de leitura dos dispositivos que o participante utilizou
para se ligar à API, e só deve ser actualizada pelo código da aplicação do
participante.
Um mau ator faz um pedido GET para um participante
(/attendees/123456) e recebe a seguinte resposta:
{
"name": "Danny B",
"age": 35,
"devices": [
"iPhone",
"Firefox"
]
}
Agora, o mau ator emite um pedido PUT à API Attendee para atualizar o
atributo age e tenta também, de forma maliciosa, atualizar a lista
devices:
PUT /attendees/123456
{
"name": "Danny B",
"age": 36,
"devices": [
"vulnerableDevice"
]
}
Quaisquer dados na lista devices devem ser ignorados quando a entidade
é guardada na base de dados. A atribuição em massa é típica quando os
dados de entrada do cliente são delimitados a objectos internos sem pensar
nas repercussões, o que é muitas vezes uma consequência da exposição de
uma API de base de dados como uma API baseada na Web. No Capítulo 1,
as preocupações com a exposição de um modelo de dados subjacente são
discutidas do ponto de vista da usabilidade, o que fornece razões adicionais
para não o fazer.
Esta vulnerabilidade não é algo que possa ser resolvido ao nível do gateway
da API; em vez disso, deve ser protegida dentro da própria implementação
da API .
Repúdio
De acordo com para STRIDE, um ataque de repúdio acontece quando uma
aplicação ou sistema não adopta controlos para rastrear e registar
adequadamente as acções dos utilizadores, o que permite a manipulação
maliciosa ou a falsificação da identificação de novas acções. Para muitos
pedidos feitos a uma API, é importante compreender os detalhes do pedido,
o payload e a resposta gerada (e as acções internas correspondentes). Em
determinados casos de utilização regulamentares ou de conformidade, pode
ser necessário inspecionar arbitrariamente o que estava numa troca, Se um
pedido puder ser repudiado - ou seja, se não houver provas do que o
atacante fez - então o atacante pode rejeitar ou discordar de que tentou
executar qualquer ação maliciosa. É por isso que as ameaças de repúdio (o
"R" em STRIDE) estão incluídas na metodologia STRIDE.
Para identificar os pedidos que estão a passar pelo seu sistema e para
compreender o que está a acontecer, é necessário adicionar registo e
monitorização. O registo e a monitorização insuficientes são uma
vulnerabilidade no OWASP API Top 10. Com todos os pedidos dos
utilizadores a fluírem através do gateway da API, este é um
pontocentralizado óbvio para monitorizar o tráfego e registar os pedidos e
as respostas. Muitos gateways da API fornecerão esta funcionalidade pronta
a utilizar, mas é necessário compreender como armazenar, pesquisar e
extrair estas informações, especialmente ao longo do tempo. Tal como
acontece com quaisquer capacidades de recuperação de desastres e
continuidade do negócio (DR/BC), o registo e a monitorização devem ser
verificados regularmente para garantir que está a capturar o que é esperado.
Divulgação de informações
Divulgação de informações é o "I" em STRIDE, e está centrado em não
expor informações que só devem ser utilizadas internamente ou mantidas
em segredo. Dois antipadrões comuns nesta categoria de ameaça incluem a
exposição excessiva de dados e a gestão inadequada de activos.
Exposição excessiva de dados
O OWASP API Top 10 Excessive data exposure concentra-se em garantir
que os dados não sejam expostos de forma inadequada. Como um cenário
hipotético, imagina que o serviço Attendee contém PII, como um número
de passaporte. Ao projetar sua API, é importante evitar a exposição
inadequada desses dados. É muito fácil fazer suposições ingénuas sobre a
forma como uma API será chamada, especialmente à medida que um
sistema evolui ao longo do tempo. As APIs que inicialmente se destinavam
apenas ao consumo interno podem ser expostas publicamente (com boas
intenções), ou uma API anterior que só estava acessível a uma aplicação
cliente de confiança pode ser aberta ao consumo público.
Se uma API for chamada através de uma aplicação Web, é fácil examinar os
pedidos, as respostas e as cargas correspondentes através das ferramentas de
desenvolvimento incluídas nos navegadores Web modernos. Por exemplo,
qualquer pedido de informações do utilizador efectuado à API Attendee
pode devolver acidentalmente informações sobre o passaporte:
{
"values": [
{
"id": "0",
"name": "Danny B",
"age": 65,
"email", "danny.b@[Link]",
"passport": "Abc12408NJUILM"
},
{
"id": "1",
"name": "Jimmy G",
"age": 93,
"email": "jimmy.g@[Link]",
"passport": "ZYX123ASJJ0072M"
}
]
}
É possível executar a validação de resposta num gateway de API. No
entanto, é da responsabilidade de quem constrói a API saber o que está a
expor e não expor dados sensíveis que deveriam ser privados. Qualquer
implementação num gateway de API deve ser vista como a verificação de
último recurso (ou parte de uma abordagem de verificação "com cinto e
suspensórios"). Também é necessário garantir que não há fuga de dados
sensíveis para os clientes que efectuam a chamada, como as versões de um
servidor Web que está a ser utilizado ou um stack trace da aplicação que
tenha sido gerado como resultado de uma falha.
Gestão inadequada dos activos
A gestão inadequada de activos ocorre normalmente à medida que os
sistemas evoluem e a organização perde o controlo das API (e das versões)
que estão expostas ou das API concebidas apenas para consumo interno.
Como exemplo hipotético com a API Attendee, poderia ser possível ter
várias versões da API implementadas na produção, com uma versão inicial
da API a expor todas as propriedades dos participantes por predefinição. À
medida que o modelo de dados evolui, são adicionados vários campos
privados que contêm PII e as novas versões do serviço Attendee removem
estas informações quando a API é consultada. Mesmo que a versão antiga
do serviço Attendee não funcione totalmente, pode ainda ser utilizada para
extrair as informações adicionais contidas no modelo de dados.
Um exemplo hipotético para o serviço Attendee é o facto de o ponto final
/beta/attendees estar exposto publicamente. Esta versão inicial foi
exposta para alguns testes e depois esquecida. Como não existe uma gestão
adequada dos activos expostos, não é notada, mas um atacante pode tentar
chamar o ponto final. Se todo o tráfego da API for gerido através do teu
gateway, deves ter um registo no mesmo para saberes o que existe. Também
podes examinar os pedidos e procurar anomalias de pedidos chamados para
pontos finais inesperados.
Para contrariar este problema, pode ser utilizada uma plataforma de gestão
de API ou de portal do programador para catalogar e acompanhar todas as
APIs implementadas na produção. Muitas soluções de gestão de API
incluem esta funcionalidade como padrão, uma vez que é vista como um
componente vital para gerir o ciclo de vida das APIs.
Negação de serviço
Em a metodologia STRIDE, o "D" está centrado na negação de serviço
(DoS). Um ataque DoS tenta sobrecarregar um sistema ou qualquer uma
das suas defesas para fins maliciosos. Por exemplo, uma firewall que fica
sobrecarregada pode passar a permitir todo o tráfego, o que permite a um
atacante fazer chamadas maliciosas que anteriormente teriam sido
bloqueadas. Ao sobrecarregar o sistema com tráfego, nenhum pedido
legítimo pode ser feito e nenhum utilizador pode votar. O OWASP API Top
10 tem uma questão de segurança que cobre extensivamente o DoS.
A API Attendee tem de satisfazer as tuas exigências de escalabilidade, mas
também deve evitar ficar sobrecarregada com tráfego. Para tal, podes
utilizar as técnicas de limitação da taxa e de redução da carga.
Por exemplo, muitos fornecedores de redes de distribuição de conteúdos
(CDN) incluem a prevenção de DoS por defeito e a maioria dos
fornecedores públicos oferece um serviço semelhante que pode ser
associado a nomes de domínio públicos e endereços IP.
AVISO
À medida que os sistemas evoluem, não é invulgar introduzir acidentalmente dependências
circulares e, dadas as condições certas, isto pode envolver serviços internos que chamam as APIs
uns dos outros num ciclo infinito. É por isso que a implementação da limitação da taxa e da
monitorização de erros nas chamadas internas às APIs pode ser inestimável!
Limitação da taxa e corte de carga
Limitação de taxa, como o nome sugere, limita o número de pedidos que
podem ser feitos à sua API durante um período de tempo.10 O uso de
limitação de taxa normalmente se refere à rejeição de tráfego com base em
propriedades de solicitações individuais (muitas de um determinado
usuário, aplicativo cliente ou local). A redução de carga se refere à rejeição
de solicitações com base no estado geral do sistema (banco de dados na
capacidade, não há mais threads de trabalho disponíveis). Por padrão,
muitos aplicativos, servidores Web e gateways de API não implementam
limitação de taxa ou redução de carga e os modos de falha correspondentes
podem ser indefinidos. A realização de testes de carga pode fornecer
informações sobre os limites, pontos de interrupção e comportamento
visível.
AVISO
É importante perceber se o seu gateway de API e outras ferramentas de segurança de ponta têm
políticas de "abertura por falha" ou de "fecho por falha". As políticas de abertura por falha
continuarão a permitir o acesso aos seus serviços mesmo que existam condições de falha. Um
exemplo hipotético é que, nos serviços de emergência médica, é mais importante fornecer
informações sobre o historial médico de um paciente do que autenticar o pedido. Uma política de
fecho por falha é quando as ligações são bloqueadas em condições de falha. Não existe uma única
implementação correta, e a predefinição deve satisfazer os seus requisitos. Por exemplo, a maioria
das APIs financeiras desejaria uma política de fecho por falha por predefinição, enquanto um
serviço meteorológico público pode implementar uma política de abertura por falha.
Para o estudo de caso , o local mais apropriado para implementar a
limitação de taxa seria o gateway da API. Para executar a limitação de taxa,
normalmente você desejará identificar o originador de cada solicitação (ou
conjunto de solicitações agregadas). As propriedades de exemplo incluem
endereço IP, localização geográfica ou uma ID de cliente enviada pelo
cliente. Talvez você não queira limitar uma propriedade de entrada e, em
vez disso, tratar todas as solicitações como iguais.
Uma vez selecionada uma propriedade do pedido (nenhuma, ou outra), é
necessário aplicar uma estratégia para efetuar a limitação. Os exemplos
mais comuns incluem:
Janela fixa
Um limite fixo dentro de um período, por exemplo, 2.400 pedidos por
dia.
Janela de correr
Um limite no último período, por exemplo, 100 pedidos na última hora.
Balde de fichas
É permitido um determinado número total de pedidos (balde de fichas) e
cada pedido recebe uma ficha quando é efectuado. O balde é
reabastecido periodicamente.
Balde com fugas
Tal como o balde Token, no entanto, a taxa a que os pedidos são
processados é uma taxa fixa; esta é a fuga do balde.
Podes ver a aplicação do rate limiting na Figura 6-4.
Figura 6-4. Exemplo de limitação de taxa com o gateway da API
Um exemplo de corte de carga é mostrado na Figura 6-5.
Figura 6-5. Exemplo de limitação de carga com a API gateway
Elevação de privilégio
O final da letra "E" no STRIDE centra-se na "Elevação de Privilégios". Isto
ocorre quando um utilizador ou aplicação encontra uma forma de executar
uma tarefa que está fora do âmbito do que deveria ser permitido dado o
contexto de segurança atual - por exemplo, um utilizador é capaz de
executar tarefas que só devem ser executadas por um administrador:
Autorização de nível de objeto quebrada
Autorização de nível de função quebrada
Ambos se concentram na imposição de autorização e na garantia de que os
pedidos à sua API têm direito a executar a operação, o que foi abordado em
"Imposição de autorização".
Configuração incorrecta da segurança
Configuração incorrecta da segurança não se limita a uma destas categorias
STRIDE, uma vez que a configuração incorrecta pode ocorrer em vários
locais, como a divulgação de informações, em que uma permissão é
atribuída incorretamente, ou na negação de serviço, em que uma política de
limitação da taxa é incorretamente definida para falhar na abertura. É um
truísmo que ter uma segurança mal configurada pode ser pior do que não ter
qualquer segurança, uma vez que os utilizadores se comportam de forma
muito diferente quando acreditam que as suas acções e dados não estão
seguros. Há certas caraterísticas de segurança que provavelmente vai
sempre querer, como a Segurança da Camada de Transporte (TLS), e outras
que podem ser personalizadas para uma API ou uma configuração, como a
lista de permissões de IP.11
No nosso estudo de caso, o gateway da API é um local chave onde a
configuração incorrecta da segurança pode ter um efeito desastroso. É
necessário prestar especial atenção à sua configuração, uma vez que o
gateway da API actua como a "porta da frente".
Terminação TLS
O TLS irá garantir que o tráfego que você recebe não foi intercetado e
modificado. Além disso, os certificados TLS fornecem informações sobre o
proprietário de um domínio, para que você possa ter certeza de quem está
contatando. Como o gateway de API lida com todo o tráfego de entrada, o
TLS pode ser ativado aqui. Ter um local centralizado para gerenciar os
certificados TLS externos para solicitações de entrada também é
conveniente. Isto, em comparação com a não utilização de um gateway, em
que os certificados TLS têm de ser adicionados a cada servidor Web, proxy
e aplicação que lida com o tráfego de pedidos, é mais difícil de gerir e mais
propenso a erros. É importante utilizar um protocolo moderno e uma
encriptação forte e, no momento em que escrevo, recomenda-se a utilização
do TLS 1.2 ou posterior devido a problemas conhecidos com versões
anteriores deste protocolo.12
Partilha de pedidos entre origens (CORS)
O CORS é um mecanismo baseado em cabeçalhos HTTP que permite a um
servidor indicar quaisquer origens (domínio, esquema ou porta) diferentes
das suas, a partir das quais um navegador deve permitir o carregamento de
recursos. O suporte do CORS é um requisito essencial para qualquer
navegador Web moderno e, por motivos de segurança, os navegadores
restringem os pedidos HTTP de origem cruzada iniciados a partir de scripts.
O CORS funciona através da realização de pedidos de "preflight" pelo
navegador Web para verificar se é permitido fazer a chamada pretendida.
Podes explorar isto verificando as funcionalidades "Ferramentas de
desenvolvimento" de um navegador. Na secção "Chamadas de Network+",
podes normalmente ver os pedidos de Opções HTTP; estes são
normalmente pedidos CORS.13
Reforço da diretiva de segurança
Um pedido a um ponto de extremidade da API pode conter um payload
arbitrário, incluindo cabeçalhos e um payload de dados. Embora todos os
pedidos genuínos correspondam ao contrato esperado, um atacante pode
adicionar cabeçalhos e dados desconhecidos, incorrectos ou malformados
numa tentativa de obter acesso ou comprometer o seu sistema. É necessário
tomar medidas para mitigar esta situação. No nosso estudo de caso, por
exemplo, deves pensar em implementar uma lista de permissões de
cabeçalhos HTTP no gateway da API e remover todos os cabeçalhos HTTP
inválidos. Um atacante pode enviar cabeçalhos HTTP adicionais para a API
Attendee, como X-Assert-Role=Admin ou X-
Impersonate=Admin. O atacante espera que estes cabeçalhos não
sejam removidos e sejam utilizados internamente, o que pode dar alguns
privilégios extra .
Etapa 5: Avaliar os riscos de ameaça
Quando você realiza sua própria modelagem de ameaças e acaba com uma
lista de ameaças, é importante entender a prioridade de corrigi-las. É disso
que trata a Etapa 5 do processo de modelagem de ameaças. Para avaliar as
ameaças, você pode empregar um cálculo de risco qualitativo conhecido
como DREAD. Tal como o STRIDE, o DREAD foi desenvolvido na
Microsoft. Esta metodologia fornece-te uma abordagem para começares a
adicionar valores de risco às ameaças. Embora o DREAD já não seja
utilizado pela Microsoft, continua a ser utilizado por muitas empresas e
promovido como uma forma útil de estabelecer uma métrica sobre o risco
de uma ameaça.
O DREAD tem um sistema de pontuação simples baseado no acrónimo
subjacente:
Danos
Qual seria a gravidade de um ataque?
Reprodutibilidade
Um ataque pode ser facilmente reproduzido?
Exploração
Quão fácil é montar um ataque bem sucedido?
Utilizadores afectados
Quantos utilizadores são afectados?
Descoberta
Qual é a probabilidade de esta ameaça ser descoberta?
Cada ameaça é classificada em relação a estas categorias DREAD, em que
cada categoria é classificada de 1 a 10. O valor do risco atribuído a uma
ameaça é (Danos + Reprodutibilidade + Explorabilidade + Utilizador
afetado + Capacidade de descoberta) / 5.
Neste exemplo do nosso estudo de caso, vais analisar a ameaça mostrada na
Figura 6-6. Esta ameaça é um ataque DDoS contra o gateway da API onde
não existe limitação de taxa.
Figura 6-6. Diagrama de fluxo de dados da ameaça de falsificação de TCP
Segue a classificação desta ameaça:
Danos: 8
Não há limitação de taxa em vigor. Este é um sério motivo de
preocupação, pois permite que qualquer pessoa envie quantos pedidos
quiser para o gateway da API e, potencialmente, sobrecarregue-o,
tornando-o inutilizável.
Reprodutibilidade: 8
Se chamares o gateway da API repetidamente com muitos pedidos por
segundo, o gateway começará a degradar-se e, eventualmente, deixará
de funcionar.
Capacidade de exploração: 5
O atacante pode estar fora da nossa rede para começar a tentar executar
um ataque DoS. O gateway da API verifica primeiro a autenticação e a
autorização para impor o pedido. Isto significa que o pedido tem de vir
de uma das nossas aplicações cliente legítimas e conhecidas que se
integram no nosso sistema.
Utilizadores afectados: 10
Isto pode ter efeitos devastadores, porque se o gateway estiver
indisponível, isso afectará todos os nossos utilizadores.
Capacidade de descoberta: 10
Isto é fácil de descobrir para qualquer pessoa que queira explorar e
causar danos ao nosso sistema.
A pontuação total é (8 + 8 + 5 + 10 + 10) / 5 = 8,2.
É importante notar que os valores atribuídos ao risco são subjectivos. Para
obter uma classificação algo consistente, para cada categoria deve definir o
significado dos valores - por exemplo, se todos os utilizadores forem
afectados, a pontuação é 10; se todos os utilizadores internos ou externos
forem afectados, a pontuação é 7; se metade de um grupo for afetado, a
pontuação é 3; e se ninguém for afetado, a pontuação é 0.
Para o estudo de caso, todas as ameaças identificadas são coletadas,
pontuadas e, em seguida, priorizadas. Nesse caso, o item de maior
prioridade é a falta de proteção contra DDoS para o gateway da API. Como
você identificou nesta seção do capítulo, a atenuação desse problema é
implementar limitação de taxa e redução de carga no gateway da API.
OUTRAS FERRAMENTAS DE AVALIAÇÃO DE RISCOS
Existem outras formas de avaliar as ameaças - uma delas é o DREAD-D
(pronuncia-se Dread menos D). No cálculo de risco do DREAD, um
dos D's é a Descoberta, que, em alguns casos, pode ser a segurança
através da obscuridade, que é uma forma terrível de proteger quaisquer
dados. Por isso, o elemento Descoberta é eliminado; é por isso que se
chama DREAD-D. Outra ferramenta que pode ser utilizada é o
Common Vulnerability Scoring System (CVSS), que pode ser utilizado
para medir a gravidade (ou seja, os danos), O CVSS é utilizado pelo
NIST para avaliar os CVE, por isso, se alguma vez olhares para um
CVE, podes encontrar um CVSS. Por exemplo, podes ver isto olhando
para o CVE do Log4J e para o CVSS do NIST.
Etapa 6: Validação
O sexto e último passo do processo de modelação de ameaças é validar que
os objectivos de segurança estão completos e perguntar se é necessária
outra revisão. Como parte da modelação de ameaças, deves ter avaliado
todas as ameaças descobertas e identificadas e tomado medidas para mitigar
os riscos. Também queres garantir que completaste os objectivos de
segurança que definiste no início do exercício de modelação de ameaças. A
modelação de ameaças deve ser um processo recursivo, em que cada
execução do processo identifica problemas anteriormente desconhecidos.
Deves também executar periódica e continuamente o processo de
modelação de ameaças, especialmente quando adicionas novas
funcionalidades ao sistema, mas também porque o ambiente de ameaças
externas evolui continuamente.
A modelação de ameaças é uma competência e leva tempo a aprender o
processo em si, além de consumir muito tempo. No entanto, como acontece
com qualquer competência, quanto mais for utilizada e integrada no teu
fluxo de trabalho regular, mais fácil se torna.
Resumo
Neste capítulo, aprendeste a realizar um exercício de modelação de
ameaças, tanto em relação ao estudo de caso como à sua aplicação aos teus
próprios sistemas e APIs:
Existem fortes penalizações financeiras e danos à reputação por não
proteger as API.
A modelação de ameaças de um sistema baseado em API começa
normalmente pela criação de um diagrama de fluxo de dados (DFD).
Podem ser utilizadas ferramentas automatizadas para analisar e
identificar rapidamente potenciais ameaças.
Não precisas de ser um perito em segurança para realizar a modelação
de ameaças, e uma competência fundamental é "pensar como um
atacante".
O processo de modelação de ameaças inclui: identificar os teus
objectivos, reunir as informações corretas, decompor o sistema,
identificar ameaças, avaliar o risco dessas ameaças e validar os
resultados e as acções.
O OWASP API Security Top 10 é um excelente recurso para
compreender as ameaças que podes esperar.
A metodologia STRIDE concentra a sua ação nas ameaças de
falsificação, adulteração, repúdio, divulgação de informações, negação
de serviço e elevação de privilégios.
A metodologia DREAD pode ser utilizada para calcular uma métrica
de risco qualitativa que pode ajudar a definir as prioridades das
ameaças a mitigar em primeiro lugar.
Dentro de um sistema baseado em API, um gateway de API pode
muitas vezes fornecer uma mitigação de alto nível para os riscos que
foram identificados. No entanto, à medida que os sistemas se tornam
mais distribuídos, deves sempre considerar implementações de
serviços individuais e comunicação interserviços.
Já viste uma variedade de ameaças que existem e formas de as mitigar. No
entanto, quando estás a devolver dados ao consumidor da API, queres
garantir que ele é quem diz ser e que o consumidor da API só pode executar
acções para as quais tem permissões. Para veres como identificas quem é o
recetor e o que pode fazer, vais mergulhar mais fundo na autenticação e
autorização no próximo capítulo.
1 O ideal seria que a segurança "começasse pela esquerda" para que a segurança fosse a base.
2 Para uma referência exaustiva e uma descrição das formas de efetuar a modelação de
ameaças, consulta Threat Modeling de Izar Tarandach e Matthew J. Coles (O'Reilly).
3 Pessoas como Edward Snowden e programas de televisão como Mr. Robot aumentaram as
conversas sobre segurança entre o público em geral.
4 Para uma análise completa dos DFDs, visita a página de introdução aos DFDs da OWASP.
5 Podes encontrar a Ferramenta de Modelação de Ameaças da Microsoft aqui e explorar outras
opções através do repositório GitHub do OWASP Threat Dragon.
6 As definições utilizadas provêm do documento "The threats to our Products" (descarregar),
escrito em 1999 por Loren Kohnfelder e Praerit Garg, os criadores da STRIDE.
7 Embora esta definição se refira a máquinas individuais, o contexto do que é um ataque de
negação de serviço continua a ser o mesmo atualmente. Trata-se de colocar os recursos offline.
8 Duas metodologias adicionais incluem o P.A.S.T.A e o Trike.
9 O padrão Active Record é a prática de expor um objeto de dados e as suas funções, que
mapeiam mais ou menos o modelo de base de dados subjacente.
10 Um dos autores, Daniel, escreveu uma série de artigos sobre limitação de taxa e sua aplicação
a gateways de API. O primeiro artigo da série está disponível online em: "Parte 1: Limitação
de taxa: Uma ferramenta útil em sistemas distribuídos".
11 As listas de permissões de IP são uma lista literal de IPs que têm permissão para se ligarem ao
teu sistema. Se o IP que estabelece a ligação não constar dessa lista, o pedido é rejeitado.
12 A maioria dos gateways de API comerciais só permite, por defeito, a utilização das versões
actuais do TLS, pelo que terás de ativar versões mais fracas com vulnerabilidades conhecidas,
se tal for necessário.
13 Para ler uma explicação completa do CORS, podes consultar este artigo da Mozilla.
Capítulo 7. Autenticação e
autorização de API
Este trabalho foi traduzido com recurso a IA. Agradecemos o teu feedback e comentários:
translation-feedback@[Link]
No capítulo anterior, aprendeste a modelar sistemas baseados em APIs e a
conhecer o Top 10 de segurança de APIs da OWASP. A API Attendee está
pronta para receber tráfego do mundo exterior; no entanto, como é que o
consumidor da API é identificado? Neste capítulo, vamos explorar a
autenticação e a autorização para APIs. A autenticação diz-nos quem é o
interlocutor e a autorização diz-nos o que ele pode fazer.
Começaremos destacando o que é autenticação e autorização para APIs, o
que leva à importância de proteger as APIs e às possíveis limitações do uso
de chaves e tokens de API. O OAuth2 é uma estrutura de autorização
baseada em token introduzida em 2012 e que rapidamente se tornou o
padrão do setor para proteger APIs e determinar quais ações um aplicativo
pode executar em relação a uma API. Uma grande parte deste capítulo se
concentrará no OAuth2 e na variedade de abordagens de segurança
oferecidas para usuários finais e interações baseadas em sistemas. Os
consumidores de APIs às vezes precisam saber detalhes do usuário em
nome do qual estão agindo - para mostrar como isso pode ser alcançado,
apresentaremos o OIDC.
O capítulo ilustra as diferentes abordagens à segurança, procurando
preparar a API Attendee para utilização externa pelo sistema CFP.
Autenticação
Autenticação é o ato de verificar uma identidade. No caso de um utilizador,
o método mais tradicional é o utilizador apresentar as suas credenciais sob a
forma de um nome de utilizador e de uma palavra-passe. Atualmente, é
cada vez mais comum que a autenticação multifactor (MFA) faça parte de
um fluxo de início de sessão normalizado. A MFA é útil para dar níveis
mais elevados de garantia de que o utilizador é quem diz ser. No caso da
autenticação máquina-a-máquina, as credenciais podem assumir a forma de
chaves ou certificados. Ao verificar a identidade das credenciais
apresentadas, sabemos quem está a tentar comunicar com os nossos
sistemas.
Vamos analisar isto no contexto do nosso serviço Attendee. A API Attendee
contém informações de identificação pessoal (PII), como o nome e o
endereço de correio eletrónico, que um utilizador espera que sejam
protegidas. Para proteger estas informações, o primeiro passo é desafiar e
identificar o chamador da API. A afirmação desta identidade chama-se
autenticação. Uma vez autenticado o chamador, a API Attendee estabelece
o que o chamador pode aceder e obter: este tipo de verificação de direitos é
a autorização.
AFigura 7-1 demonstra a interação com a API Attendee. A aplicação móvel
liga-se através do gateway da API e consulta a API Attendee. Outra
interação segue um caminho semelhante a partir do sistema CFP, no entanto
o sistema CFP é propriedade de um terceiro. Vamos considerar as opções
que temos para autenticar um utilizador final (o utilizador da aplicação
móvel e os oradores do sistema CFP) e uma interação sistema-a-sistema (o
sistema CFP).
Figura 7-1. Protege o nosso estudo de caso
Autenticação do utilizador final com Tokens
A aplicação móvel actua em nome do participante e recupera e apresenta
informações sobre os participantes. Na autenticação baseada em token, o
utilizador introduz o seu nome de utilizador e a sua palavra-passe, que são
trocados por um token. O token emitido depende da implementação, mas,
no caso mais simples, pode ser uma cadeia opaca. O token é enviado no
pedido REST como parte do cabeçalho Authentication Bearer. Os tokens
são sensíveis e é importante que o pedido REST seja enviado por HTTPS
para proteger as informações em trânsito. Uma vez que um token é recebido
como parte de um pedido, ele é inspecionado e verificado para confirmar a
validade do token.A Figura 7-2 demonstra um processo típico de pesquisa
de token onde o token é armazenado em um banco de dados.
Figura 7-2. Processo de verificação da pesquisa de token do lado do servidor
O token deve ter um tempo de vida limitado - por exemplo, uma hora - e,
depois de expirar, o utilizador terá de obter um novo token. Os tokens têm a
vantagem de as credenciais de longa duração, como as palavras-passe, não
atravessarem a rede em cada pedido de acesso a recursos.
As coisas podem parecer ideais à superfície com os tokens; no entanto, uma
grande desvantagem é o utilizador ter de introduzir o nome de utilizador e a
palavra-passe na aplicação que está a fazer chamadas para uma API para
recuperar os seus dados. Além disso, quando um token é colocado no
armazenamento, procurar o token para verificar a validade de cada vez pode
ser um problema de desempenho e teria de ser atenuado.
AVISO
É possível aceder às APIs utilizando HTTP Basic, no entanto, se uma aplicação de terceiros pedir
para aceder a uma API em teu nome, isso significa que terás de fornecer o teu nome de utilizador
e a tua palavra-passe.1 Recomendamos que não permitas que o HTTP Basic seja utilizado para
aceder às tuas APIs.
Autenticação de sistema para sistema
Em algumas situações um utilizador final não está envolvido na interação e
é necessária uma comunicação sistema a sistema. Uma opção seria utilizar
uma chave de API, que não está em conformidade com qualquer norma
específica. Sempre que utilizar uma chave de API, esta deve ser segura, o
que significa que deve ser gerada utilizando um gerador de números
aleatórios criptograficamente seguro e de comprimento indetetável.
Normalmente, as chaves de API são cadeias de 32 caracteres (256 bits). Se
a chave de API for adivinhável (curta e determinística), isto cria uma
vulnerabilidade de um cliente ser pirateado. Para aceder a uma API com
uma chave de API, basta adicionar a chave de API a um cabeçalho de
pedido e enviá-la para o ponto final.2 A chave da API está associada a uma
aplicação ou projeto, pelo que é possível identificar o requerente.3 A
utilização de uma chave de API é muito semelhante à utilização de uma
palavra-passe.A Figura 7-3 demonstra um exemplo de utilização de uma
chave de API como parte de um pedido.
Figura 7-3. Sistema CFP externo chamando a API Attendee com uma chave de API
Porque não deves misturar chaves e utilizadores
Considera o cenário em que um orador está a utilizar o sistema do PCP,
propriedade de um terceiro, e o PCP está a solicitar uma atualização do
endereço de correio eletrónico associado aos dados desse utilizador. Só
porque o sistema do PCP está a utilizar uma chave API e pode ser
identificado, não significa que este sistema de terceiros deva ser capaz de
afirmar quem é o utilizador final ou quem está a agir em seu nome. Uma
solução para esta situação seria que o sistema do PCP também passasse o
nome de utilizador e a palavra-passe do utilizador (usando HTTP Basic)
juntamente com a chave API para permitir que o serviço Attendee
autentique o utilizador. No entanto, como já alertámos, isto significa que o
utilizador tem de passar o seu nome de utilizador e palavra-passe do serviço
Attendee para o sistema CFP, o que é indesejável. O cenário ideal seria uma
situação em que o sistema CFP pudesse chamar o serviço Attendee, mas
qualquer pedido efectuado em nome de um utilizador pelo sistema CFP não
necessitasse de partilhar credenciais e fosse feito com a aprovação
específica do utilizador. A solução para este problema é, na sua essência, a
utilização do OAuth2.
OAuth2
O OAuth2 é uma estrutura de autorização baseada em token e existe desde
2012. É o substituto do OAuth, que ainda existe - no entanto, é usado em
muito poucos lugares. O OAuth2 permite que um usuário consinta que um
aplicativo de terceiros possa acessar seus dados em seu nome. O
consentimento que o utilizador dá é a autorização - está a permitir ou a
negar o acesso. O OAuth2 elimina a necessidade de um utilizador entregar
as suas credenciais a terceiros, o que dá ao utilizador controlo sobre os seus
dados. Isto torna o OAuth2 apelativo, uma vez que suporta os desafios
enfrentados na secção anterior.
Para explorar melhor o OAuth2, é importante compreender primeiro as
diferentes funções dentro da especificação OAuth2. As definições foram
retiradas diretamente da especificação OAuth2:
Proprietário do recurso
Uma entidade capaz de conceder acesso a um recurso protegido.
Quando o proprietário do recurso é uma pessoa, é referido como
utilizador final.
Servidor de autorização
O servidor emite tokens de acesso para o cliente depois de autenticar
com êxito o proprietário do recurso e obter autorização. A maioria dos
fornecedores de identidade, como o Google ou o Auth0, serão
servidores de autorização OAuth2.
Cliente
Uma aplicação que efectua pedidos de recursos protegidos em nome do
proprietário do recurso e com a sua autorização.
Servidor de recursos
O servidor que aloja os recursos protegidos, capaz de aceitar e
responder a pedidos de recursos protegidos utilizando tokens de acesso.
Função de servidor de autorização com interações de
API
O servidor de autorização tem dois pontos de extremidade:
O ponto final de autorização é utilizado quando um proprietário de
recursos precisa de autorizar o acesso a recursos protegidos.
O ponto de extremidade do token é utilizado pelo cliente para obter um
token de acesso.
Se o serviço Attendee fosse chamado diretamente pelo cliente, então o
serviço Attendee seria o servidor de recursos, uma vez que está a alojar
recursos protegidos. No entanto, um servidor de recursos não precisa de ser
uma aplicação individual; pode representar um sistema completo. Um
padrão popular é utilizar a API gateway como um servidor de recursos,
como mostra a Figura 7-4. Os dois clientes, a aplicação móvel e o sistema
CFP, estão a chamar o serviço Attendee através de um gateway de API.
Podem existir vários serviços por detrás do gateway de API, mas para o
cliente o gateway de API continuaria a ser o servidor de recursos, uma vez
que aloja os recursos protegidos. Os dois proprietários de recursos neste
caso são os participantes que utilizam a aplicação móvel e os oradores que
utilizam o sistema CFP .
Figura 7-4. Gateway de API como servidor de recursos
Tokens Web JSON (JWT)
JavaScript Object Notation (JSON) Web Tokens é um formato de token
padronizado por RFC que é o token padrão de facto para OAuth2. Um
JSON Web Token, também conhecido como JWT (pronuncia-se "jot"),
consiste em reivindicações e estas reivindicações têm valores associados.
Os JWTs são estruturados e codificados utilizando normas para garantir que
o token não é modificável e, adicionalmente, podem ser encriptados. São
especialmente úteis na transferência de informações em "ambientes com
restrições de espaço, como cabeçalhos de autorização HTTP".
Aqui tens um exemplo de JWT:
{
"iss": "[Link]
"sub": "18f913b1-7a9d-47e6-a062-5381d1e21ffa",
"aud": "Attendee-Service",
"exp": 1618146900,
"nbf": 1618144200,
"iat": 1618144200,
"jti": "4d13ba71-54e4-4583-9458-562cbf0ba4e4"
}
Neste exemplo, as reivindicações são iss, sub, aud, exp, nbf, iat e
jti- todas elas são reivindicações reservadas no RFC do JWT. As
reivindicações reservadas têm um significado especial. Não são obrigatórias
num token, mas oferecem um ponto de partida para uma quantidade mínima
de informações. Analisando o nosso token de exemplo, vamos listar as
abreviaturas das reivindicações e a forma como são normalmente utilizadas:
iss (Emissor)
A autoridade que emitiu o token. Normalmente, trata-se de um
fornecedor de identidade (por exemplo, Google ou Auth0).
sub (Assunto)
Um identificador único para identificar o mandante do JWT. No caso da
aplicação móvel que actua em nome do utilizador, será o participante
(e.g., Matthew Auburn); se se tratar de uma ligação servidor a servidor,
poderá ser a aplicação (e.g., o Sistema CFP).4 O valor do assunto não
segue qualquer formato e, se estiveres a definir o que deve ser o
assunto, tens de decidir se deve ser único no teu sistema ou
universalmente único (por exemplo, utilizando um UUID).
aud (Público)
A quem se destina esta ficha.
exp (Tempo de expiração)
Quando o token expira (45 minutos depois de ter sido emitido, neste
caso).
nbf (Não antes)
O token não deve ser utilizado antes desta hora (neste caso, a mesma
hora da emissão).
iat (Emitido em)
A hora em que a ficha foi emitida.
jti (ID JWT)
Um identificador único para o JWT.
NOTA
Os tokens podem conter mais informações, tais como o nome preferido, o e-mail do utilizador,
reclamações sobre a parte emissora e a aplicação que solicitou o token. Para APIs de alta
segurança, é comum que o método de autenticação para o servidor de autorização seja uma
reclamação, que pode ser utilizada para verificar se a MFA foi utilizada pelo proprietário do
recurso para se autenticar.
Codificação e verificação de JSON Web Tokens
Existem dois mecanismos de codificação populares para o JWT, que têm o
seu próprio formato:
As assinaturas Web JSON (JWS) fornecem integridade a um JWT. O
conteúdo do token é visível para qualquer pessoa que o receba; no
entanto, as reivindicações são assinadas digitalmente, o que garante
que, se o conteúdo do token for alterado, o token é imediatamente
inválido.
O JSON Web Encryption (JWE) fornece integridade, mas também é
encriptado. Isto significa que o conteúdo do token não pode ser
examinado.
NOTA
Geralmente, quando é utilizado o JWT, isso implica que o JWT utiliza o JWS e o JWT encriptado
significa o JWT que utiliza o JWE.
O mecanismo mais comum utilizado é o JWS, em que a assinatura digital é
efectuada utilizando uma chave privada. A chave pública é utilizada pelo
recetor do token para validar que o token foi assinado pela parte emissora
específica. A chave pública é partilhada livremente com qualquer parte que
necessite de verificar a integridade do token.
AVISO
Se estiveres a utilizar o JWT com o JWS, não deves inserir dados confidenciais nos valores da
reivindicação. O JWS fornece integridade às reivindicações; no entanto, qualquer pessoa que
tenha o JWT pode ler as reivindicações. Para garantir que o JWT não pode ser lido, utiliza o JWE.
Os JWTs são uma excelente opção para um formato de token. Os serviços
API consomem o JWT, validam-no verificando a assinatura e não precisam
de procurar um token numa base de dados. Como o token de acesso será de
um servidor de autorização que está (muito provavelmente) sob o teu
controlo, podes adicionar todas as informações que esperas/exiges ao teu
JWT.
Quando o JWT é recebido, há várias partes a serem verificadas. Primeiro, a
assinatura é verificada para confirmar que foi emitida pela parte esperada e
não foi modificada ou adulterada. Em seguida, outras afirmações no token
devem ser validadas, como verificar se o token não expirou (afirmação exp)
ou se o token não foi usado antes de ser permitido (afirmação nbf). Todos
os tokens emitidos devem ser de curta duração; os tokens de longa duração
representam um risco se forem perdidos ou roubados. Relativamente ao
tema das afirmações de longa duração, as Diretrizes Digitais do NIST
(National Institute of Standards and Technology) referem
As asserções de longa duração têm um maior risco de serem roubadas ou
reproduzidas; uma curta duração da asserção atenua este risco.
Não existe uma norma oficial sobre o tempo de validade de um token de
vida curta ou longa. O tempo de vida típico sugerido para um token de vida
curta é entre 1 e 60 minutos, e para um token de vida longa é de um ano a
dez anos. Sugere-se que mantenhas o tempo de vida dos tokens o mais curto
possível.
Há muitos aspectos positivos na utilização de JWTs para um token de
acesso. Agora vamos analisar a sua utilização no âmbito do OAuth2.
Terminologia e mecanismos das concessões OAuth2
O OAuth2 é concebido para ser extensível. A especificação oficial do
OAuth2 foi lançada em 2012 com quatro concessões e, desde então, foram
aprovadas concessões e modificações adicionais para alargar a sua
utilização. Isto é possível porque o OAuth2 apresenta um protocolo
abstrato, mostrado na Figura 7-5:
A. O cliente pede autorização ao proprietário do recurso.
B. O proprietário do recurso concederá ou negará o acesso do cliente aos
seus recursos.
C. O cliente solicita ao servidor de autorização um token de acesso para a
autorização que lhe foi concedida.
D. O servidor de autorização emitirá um token de acesso se o cliente tiver
sido autorizado pelo proprietário do recurso.
E. O cliente faz um pedido para o recurso ao servidor de recursos, que no
nosso caso é a API. O pedido enviará o token de acesso como parte do
pedido.
F. O servidor de recursos devolverá o recurso se o token de acesso for
válido.
Figura 7-5. Fluxo do protocolo abstrato
Este protocolo abstrato sobre como as concessões do OAuth2 devem
funcionar destaca que o proprietário do recurso tem controle sobre seus
próprios recursos. O cliente está solicitando autorização do proprietário do
recurso - ou seja, "posso (o aplicativo) acessar seus recursos em seu nome?"
A forma como a autorização é dada não é importante. O que é essencial é
que o proprietário do recurso tenha a oportunidade de conceder ou negar o
acesso. Ao solicitar um recurso ao servidor de recursos (ou seja, chamar a
API), a forma como o cliente obteve o token de acesso não importa. Desde
que o pedido contenha um token de acesso válido, o servidor de recursos
emitirá o recurso. Cada passo é isolado e não requer informações sobre o
passo anterior. É por isso que existem diferentes concessões para diferentes
cenários, uma vez que têm a sua própria implementação para garantir que
estes passos são seguros para esse ambiente.
Diretriz ADR: Devo considerar a utilização do OAuth2?
É importante que compreenda as razões para adotar a utilização do OAuth2
e se esta é mesmo a escolha certa para si. Para o ajudar nesta decisão, utiliza
esta Diretriz ADR (ver Tabela 7-1) para o ajudar a determinar o que é mais
adequado para si e as conversas que poderá querer ter.
Tabela 7-1. Diretriz ADR: Preciso de utilizar o OAuth2?
Decisão Deve ser utilizado o OAuth2 ou existe outra norma de autenticação e
autorização que seja preferível para o ambiente operacional?
Pontos de discussão Quando começas a trabalhar com APIs, tens a oportunidade de decidir ou
influenciar os mecanismos de segurança para elas:
Examina os requisitos de segurança actuais e a forma como as coisas
podem mudar. Por exemplo, as API são apenas utilizadas dentro de um
plano de controlo ou são também utilizadas fora de um plano de
controlo/potencialmente com terceiros?
Qual é o modelo de segurança que se espera que suportes? Os
integradores externos solicitaram que utilizasses um determinado
modelo de segurança?
Se a sua empresa pretende migrar de um modelo de autenticação
existente para outro, isto é importante.
Recomendações A utilização do OAuth2 proporciona a máxima compatibilidade com outros
utilizadores de API. É uma norma da indústria com documentação e
bibliotecas de clientes que facilitam a integração. O OAuth2 suporta tanto o
utilizador final como os casos de sistema para sistema.
Código de autorização Subvenção
A Concessão de Código de Autorização (Concessão de Código de
Autorização) é uma implementação de uma concessão OAuth2; é uma
implementação do protocolo abstrato que viste anteriormente na Figura 7-5.
Esta é uma concessão muito conhecida, e provavelmente já a usaste sem te
aperceberes.5 O caso de uso típico para a concessão de código de
autorização é um site apoiado por um servidor, que não está disponível
publicamente na Internet (ou seja, pode proteger um segredo). Um
aplicativo cliente que pode proteger um segredo é chamado de cliente
confidencial.A Figura 7-6 descreve em mais detalhes como a concessão
funciona:
A. A aplicação cliente direciona o navegador Web (o agente do utilizador
no diagrama é um navegador Web) para um servidor de autorização. O
redireccionamento para o servidor de autorização incluirá a
identificação do cliente (um ID de cliente) e, como parte do
redireccionamento, também tem a concessão que está a ser utilizada
(neste caso, a concessão do código de autorização é conhecida como
code).
B. O servidor de autorização pede ao proprietário do recurso (utilizador
final) que se identifique. O servidor de autorização precisa de saber
quem é o proprietário do recurso, pelo que o proprietário do recurso
terá de se autenticar no servidor de autorização. O servidor de
autorização é então capaz de obter o consentimento do proprietário do
recurso se este conceder autorização à aplicação cliente. (Os passos A e
B da Concessão do Código de Autorização são todos relativos ao
pedido de autorização; isto é mostrado como um único passo (A) no
protocolo abstrato da Figura 7-5).
C. Assumindo que a autorização é concedida, é passado um código de
autorização à aplicação cliente, através do agente do utilizador. (Este
passo corresponde ao passo B do protocolo de abstração, onde mostra
a concessão de autorização devolvida).
D. O cliente solicita então um token de acesso ao servidor de autorização
apresentando o código de autorização. O servidor de autorização não
pode simplesmente aceitar o código de autorização de qualquer pessoa.
A aplicação cliente tem de se autenticar junto do servidor de
autorização utilizando um segredo que é conhecido pelo servidor de
autorização e pela aplicação cliente. (No protocolo de abstração, este é
o Passo C onde a concessão de autorização é enviada para o servidor
de autorização para ser trocada).
E. Se a aplicação cliente se autenticar com êxito e apresentar um código
de autorização válido, é-lhe concedido um token de acesso. (Este passo
está alinhado com o passo D no protocolo de abstração onde o token de
acesso é emitido).
Figura 7-6. Concessão do código de autorização
Esta solução funciona muito bem e era o modelo predefinido para as
aplicações Web. No entanto, o mundo dos sítios Web evoluiu e agora
existem Single Page Application (SPAs). Os sítios Web SPA baseiam-se em
JavaScript e são executados no browser do utilizador, o que significa que o
código-fonte está totalmente disponível para o utilizador ver. Significa
também que um SPA cliente OAuth2 não pode proteger um segredo e é
conhecido como um cliente público, pelo que não é possível utilizar a
Concessão de código de autenticação tal como está.
Código de autorização Concessão (+ PKCE)
Isto é quando usas a Concessão de Código de Autorização + PKCE, que te
permite usar o OAuth2 para aplicações SPA. PKCE significa Chave de
Prova para Troca de Código e é usado para mitigar ataques de interceção.
Na concessão de Concessão de Código de Autorização + PKCE, são
necessários dois parâmetros adicionais: um para o pedido de autorização,
que é o code_challenge, e um para o pedido de token de acesso, que é
o code_verifier. O code_verifier é uma cadeia de caracteres
criptograficamente aleatória gerada pelo cliente, e o code_challenge é
o valor hash do code_verifier. Quando a aplicação cliente inicia o
pedido ao servidor de autorização, envia o code_challenge, e quando é
pedido um token de acesso, o código de autorização é apresentado
juntamente com o code_verifier. O servidor de autorização pode fazer
o hash do code_verifier para verificar se corresponde ao
code_challenge utilizado para iniciar o pedido de token. Esta extensão
torna a concessão mais segura, uma vez que apenas o cliente original deve
ter o code_verifier; isto evita ataques em que um código de
autorização poderia ser intercetado e trocado por um token de acesso.
Podemos ver essa concessão em ação na Figura 7-7.
A. O pedido de autorização é efectuado e o code_verifier é enviado
para o servidor de autorização. No diagrama t(code_verifier) é
a transformação do code_verifier para o code_challenge e
t_m é o método de transformação (como descrito anteriormente, trata-
se de um hash).
B. Tal como na Concessão de Código de Autorização, é devolvido um
código de autorização.
C. O cliente solicita o token de acesso enviando o pedido de autorização,
que é o código de autorização e o endereço code_verifier. Não é
enviado qualquer segredo do cliente, uma vez que se trata de um
cliente público.
D. O token de acesso é então emitido para a aplicação cliente.
Figura 7-7. Concessão do código de autorização + PKCE
O diagrama tem um aspeto diferente do da Figura 7-6, mas a única
diferença real é o primeiro passo, o Passo A. No Passo A da Figura 7-7,
trata-se do pedido de autorização (tal como no protocolo abstrato do Passo
A) e o processo será o mesmo que na Concessão do Código de Autorização
nos Passos A e B.
DICA
O PKCE deve ser utilizado para clientes públicos. No entanto, podes utilizar o PKCE para clientes
confidenciais, bem como para proteção adicional.
A Concessão de Código de Autorização e a sua extensão PKCE funcionarão
nos cenários mais comuns para os teus clientes públicos e confidenciais
quando tiveres um utilizador final no teu caso.
Estudo de caso: Acessando a API do participante com a
concessão de código de autorização
Existem duas aplicações cliente para aceder à API Attendee. Ambas as
aplicações utilizarão o Authorization Code Grant para aceder à API
Attendee em nome dos utilizadores (os proprietários dos recursos). O
sistema CFP Externo é um cliente confidencial. O cliente pode manter um
segredo, o que significa que pode ser utilizada a Concessão de Código de
Autorização. A aplicação móvel é um cliente público e não pode manter um
segredo, pelo que deve ser utilizada a Concessão de Código de Autorização
+ PKCE. Os passos para o sistema CFP Externo e a aplicação móvel
solicitarem um token de acesso e utilizarem-no para aceder ao serviço
Attendee são apresentados na Figura 7-8. Isto também realça que a
utilização de PKCE não altera os passos de alto nível realizados ou o
percurso do utilizador .
Figura 7-8. Concessão do código de autorização aplicado ao nosso estudo de caso
Atualizar fichas
É uma boa prática emitir tokens de curta duração; no entanto, pedir a um
utilizador que volte a introduzir o seu nome de utilizador e palavra-passe
tornar-se-ia rapidamente uma experiência chocante. Um token de
atualização é um token de longa duração utilizado pelo cliente para solicitar
tokens de acesso adicionais quando o token anterior expira. Os tokens de
atualização são solicitados como parte do pedido de autorização, o que
significa que o utilizador final não está envolvido no pedido de tokens de
acesso adicionais. Como parte das melhores práticas de segurança mais
recentes, a deteção de um token de atualização utilizado duas vezes revoga
imediatamente o token de atualização ativo. Os tokens de atualização são
uma credencial adicional e de longa duração, pelo que é importante que
sejam mantidos em segurança e não sejam divulgados. Se, a qualquer
momento, for necessário negar o acesso a um cliente, incluindo se o
proprietário do recurso não quiser que o cliente tenha mais acesso aos seus
recursos, o token de atualização pode ser revogado. Da próxima vez que a
aplicação cliente pedir um novo token de acesso (que tem uma vida curta),
o acesso será interrompido. Isto significa que pode haver uma janela em que
um cliente tem um token de acesso válido, mas não deveria ter acesso. É
por isso que é importante ter tokens de vida curta.
Concessão de credenciais de cliente
O cliente para a Concessão de Credenciais de Cliente é um cliente
confidencial, uma vez que necessita de manter um segredo. Uma vez que se
trata de comunicação máquina-a-máquina, a ligação é estabelecida
antecipadamente e o acesso (o que o cliente está autorizado a fazer) deve
ser pré-acordado.
O processo de obtenção de um token de acesso pelo cliente é muito simples,
como mostra a Figura 7-9:6
A. A aplicação cliente autentica-se no servidor de autorização e solicita
um token de acesso. O cliente também identifica a concessão que está
a ser utilizada, que é client_credentials.
B. O servidor de autorização devolve um token de acesso se a aplicação
cliente for autenticada com êxito.
Figura 7-9. Concessão de credenciais de cliente
O cliente está a agir em seu próprio nome, pelo que apenas tem de se
identificar.
Estudo de caso: Acesso à API de participante do sistema CFP
com concessão de credenciais de cliente
O sistema produz um relatório trimestral sobre o número de participantes
que submetem palestras e se tornam oradores. Este relatório não é gerado
em nome de um participante, mas sim para o sistema CFP Externo. O
cliente (sistema CFP Externo) é registado no servidor de autorização.7 No
serviço Attendee, o cliente é adicionado a uma lista de clientes que podem
aceder ao serviço e é configurado para poder ler informações sobre os
participantes e consultar quais os utilizadores que apresentaram palestras -
este é o acesso pré-acordado. Quando o cliente pretende aceder à API
Attendee, solicita um token de acesso ao servidor de autorização e utiliza
esse token quando chama a API Attendee.
Já viste como utilizar o OAuth2 para a comunicação máquina-a-máquina,
mas e se o teu caso não tiver sido abordado até agora?
DICA
Os tokens de atualização não são utilizados com a Concessão de Credenciais de Cliente; em vez
disso, o cliente solicita um novo acesso token.
Concessões OAuth2 adicionais
Existem mais concessões OAuth2 disponíveis do que apenas as duas
anteriores discutidas. As outras concessões padronizadas disponíveis estão
listadas aqui, mas não as exploraremos em mais detalhes:
A Concessão de Autorização de Dispositivo é utilizada para
dispositivos que têm entradas limitadas ou não têm um browser. Isto
torna-a útil para dispositivos IoT, como o teu frigorífico inteligente ou
um projeto Raspberry Pi.
A Concessão Implícita era normalmente utilizada para SPAs, mas foi
substituída pela Concessão de Código de Autorização + PKCE.
A concessão de credenciais de palavra-passe do proprietário do recurso
foi historicamente utilizada como um trampolim do HTTP Basic para
iniciar aplicações cliente utilizando o OAuth2. Recomenda-se que não
utilize esta concessão.
Diretrizes do ADR: Escolher quais as subvenções
OAuth2 a apoiar
Como vimos em , existem muitas subvenções OAuth2. É importante
escolher a subvenção adequada ao teu caso ou às subvenções que pretendes
apoiar. A Diretriz ADR na Tabela 7-2 fornece pontos de discussão e
considerações que deves ter em conta antes de escolheres a tua concessão.
Tabela 7-2. Diretriz ADR: Quais concessões OAuth2
Decisão Que concessões OAuth2 devem ser suportadas?
Pontos de discussão Determina que tipos de clientes irão interagir com as tuas APIs:
Precisas de suportar dispositivos IoT e o Device Authorization Grant?
Tens clientes mais antigos que são SPAs que apenas suportam a
subvenção implícita?
Deves proibir completamente a utilização da concessão de credenciais
de palavra-passe do proprietário do recurso?
Se já tiveres um modelo de segurança para autenticação e autorização, deves
mudar para o OAuth2?
Qual é a bolsa que melhor representa o teu modelo de interação?
Os clientes vão poder migrar para a subvenção? Se estiverem sob o teu
controlo ou se tiveres um pequeno número de terceiros, será muito mais
fácil começar a fazer com que os terceiros migrem.
Todos os novos clientes integrados devem utilizar a nova concessão
OAuth2?
Recomendações Se tiveres um modelo de segurança que funcione e muitos clientes pagantes,
pode não ser viável forçá-los a migrar para a utilização do OAuth2. No
entanto, poderá ter de evoluir a sua arquitetura de segurança para utilizar o
OAuth2 de forma a ser mais normalizada, uma vez que isto também pode ser
um pedido de terceiros para que não tenham de criar uma interação
personalizada para o seu modelo de segurança. Começar com a concessão de
credenciais de cliente é frequentemente a forma mais fácil de introduzir o
OAuth2 num sistema de API.
Âmbitos do OAuth2
Os âmbitos de aplicação são um mecanismo importante no OAuth2 e são
efetivamente utilizados para limitar o acesso de um cliente que actua em
nome de um utilizador. Quando um utilizador se autentica pela primeira
vez, o utilizador final recebe um ecrã de consentimento, que indica o que o
cliente está a pedir para fazer. Por exemplo, "A aplicação gostaria de ler os
compromissos no seu calendário" e "A aplicação gostaria de marcar
reuniões no seu calendário".
Estudo de caso: Aplicar âmbitos OAuth2 à API Attendee
Vamos explorar um exemplo prático para mostrar os âmbitos de modelação
dos participantes utilizando alguns pontos finais. Para ajudar neste exemplo,
vamos imaginar que o sistema de conferência antigo também tem dois
pontos finais expostos:
API do participante
GET - /attendees-Obtém uma lista de participantes
GET - /attendees/{attendee_id}- Obtém os dados de um
participante
POST - /attendees-Registar um novo participante
PUT - /attendees/{attendee_id}- Actualiza as
informações dos participantes
API de conferência herdada
GET - /conferences-Obtém uma lista de conferências
POST - /conferences-Cria uma nova conferência
A aplicação CFP externo só precisa de aceder à API de participantes, pelo
que, como proprietário do recurso, não queres que o CFP externo aceda às
informações da conferência. Deve haver uma separação em que possas
autorizar o sistema CFP externo a aceder apenas à API de participantes.
São criados dois âmbitos: o âmbito do Participante e o âmbito da
Conferência, que é apresentado como o âmbito Método HTTP - ponto final
-.
API do participante
GET - /attendees - Participante
GET - /attendees/{attendee_id} - Participante
POST - /attendees - Participante
PUT - /attendees/{attendee_id - Participante
API de conferência herdada
GET - /conferences - Conferência
POST - /conferences - Conferência
Desta forma, consegue separar as conferências e os participantes, mas é
possível ir mais longe e diferenciar as operações de leitura e de escrita:
API do participante
GET - /attendees - AttendeeRead
GET - /attendees/{attendee_id} - AttendeeRead
POST - /attendees - AttendeeAccount
PUT - /attendees{attendee_id} - AttendeeAccount
Os âmbitos não têm um padrão definido, mas são normalmente usados
como uma separação grosseira dentro de uma API. Os âmbitos têm de fazer
sentido para o utilizador final, uma vez que este terá de consentir a sua
utilização. Assim que o proprietário do recurso conceder autorização a um
recurso, esta informação tem de ser usada pelo servidor de recursos para a
impor. Quando se usam tokens de acesso num formato JWT, é normalmente
adicionada uma reivindicação ao JWT; por exemplo, "scope":
"AttendeeRead AttendeeAccount.8 Os âmbitos não são
obrigatórios para o OAuth2, embora seja muito útil e algo que deves
considerar para uma autorização de granularidade grosseira.
Aplicação da autorização
Autorização precisa ser aplicada, pois é fundamental para a segurança da
API. Dois dos problemas mais comuns de autorização de segurança listados
no Top 10 de Segurança de API da OWASP são Autorização de Nível de
Objeto Quebrado (BOLA) e Autorização de Nível de Função Quebrada. A
BOLA é quando um utilizador consegue solicitar informações para um
objeto ao qual não deveria ter acesso, frequentemente descoberto através da
adulteração de uma ID de recurso. A Autorização de Nível de Função
Quebrada é quando o utilizador pode executar tarefas para as quais não está
autorizado, por exemplo, executar um ponto final apenas de administração
como um utilizador padrão.
A autorização é tipicamente baseada em algum tipo de direitos. Isto é
popularmente aplicado utilizando o Controlo de Acesso Baseado em
Funções (RBAC). Embora a escolha exacta dos direitos seja um detalhe,
deve existir algum tipo de controlo de acesso e é importante que cada ponto
final tenha uma verificação de autorização antes de satisfazer o pedido.
Quando analisares a autorização com o OAuth2, tens de ter em mente que
os âmbitos são utilizados para especificar o que o proprietário de um
recurso declarou relativamente ao leque de acções que um cliente pode
executar. Isto não significa que o cliente deva ter acesso a todos os dados do
utilizador final. Para o serviço Participante, podem ser possíveis diferentes
acções, tais como direitos de administrador para gerir participantes e
direitos de apenas visualização dos participantes. Um participante pode
apenas ter permissão para ler a descrição do perfil dos participantes; no
entanto, um cliente pode pedir permissão para ler as informações dos
participantes e para gerir os participantes. Um utilizador pode conceder
acesso ao cliente para executar estas tarefas em seu nome; no entanto, o
próprio utilizador pode não ter acesso. Esta sobreposição de autorização é
realçada na Figura 7-10.
Figura 7-10. Venn de autorização
Os âmbitos são úteis para que um gateway de API imponha a autorização
do âmbito e rejeite pedidos quando um cliente não tem o âmbito correto
para aceder a uma API.
Apresenta a OIDC
O OAuth2 fornece um mecanismo para o cliente aceder a APIs utilizando
autenticação e autorização. Um requisito comum é que o cliente conheça a
identidade do proprietário do recurso. Considera o sistema CFP Externo.
Terá de armazenar dados sobre o orador, mas as concessões OAuth2 não
fornecem uma forma de obter a identidade do utilizador final.
Este é o objetivo do OpenID Connect (OIDC); fornece uma camada de
identidade. Esta camada é construída sobre o OAuth2, fazendo com que o
servidor de autorização OAuth2 implemente funcionalidades adicionais. A
funcionalidade necessária transforma o servidor de autorização OAuth2
também num fornecedor OpenID. Agora é possível que um cliente solicite
informações sobre o utilizador utilizando um âmbito especial chamado .
openidEste âmbito é solicitado juntamente com quaisquer âmbitos
necessários para quaisquer tokens de acesso. A utilização do âmbito
openid fornece ao cliente um token de ID, que é um JWT que contém
afirmações sobre o utilizador.
O token de ID devolvido quando se utiliza apenas o âmbito openid
contém uma quantidade muito limitada de informações sobre o utilizador. A
única afirmação que identifica o utilizador é a afirmação de assunto, que é
um ID único do utilizador e nunca deve mudar (normalmente é um UUID).
Ter apenas um ID único sobre o utilizador não é normalmente suficiente
para o cliente. É por isso que o OIDC especifica âmbitos adicionais que
podem ser adicionados ao pedido para obter informações no token de ID:
profile
name, family_name, given_name, middle_name, nickname,
preferred_username, profile, picture, website,
gender, birthdate, zoneinfo, locale, eupdated_at
email
email e email_verified
address
address
phone
phone_number e phone_number_verified
Podes acabar com um token de ID muito rico que contém muita informação
sobre o utilizador. Estes âmbitos são utilizados no contexto de tokens de ID
- não verias estes âmbitos no teu token de acesso como viste em "Âmbitos
OAuth2".
Três fluxos são declarados pelo OIDC: Fluxo do Código de Autorização,
Fluxo Implícito e Fluxo Híbrido. A especificação OIDC chama "fluxos" aos
passos para adquirir um token de ID. A recomendação é utilizar o Fluxo do
Código de Autorização pelas mesmas razões que a Concessão do Código de
Autorização (+ PKCE) - é mais seguro.
Muitas pessoas pensam que o OAuth2 e o OIDC são a mesma coisa e
referem que o OIDC é utilizado para aceder a APIs. A realidade é que não
são a mesma coisa; são duas coisas distintas. O OIDC tem a sua função,
fornecendo a identidade do utilizador aos clientes; no entanto, não fornece
acesso a APIs. Se o OIDC é algo de que necessita, deve certificar-se de que
o seu fornecedor de identidade o suporta. Não tente construir a sua própria
camada de identidade.
AVISO
Nunca substituas os tokens de ID por tokens de acesso. Esta é uma prática muito perigosa, uma
vez que os tokens de ID não se destinam a este fim. São tokens de longa duração com o objetivo
de fornecer informações sobre o utilizador a um cliente. Não se destinam a aceder a recursos de.
SAML 2.0
Em ambientes empresariais, é comum utilizar SAML 2.0, muitas vezes
referido apenas como SAML. SAML (Security Assertion Markup
Language) é uma norma aberta que transfere asserções. É frequentemente
utilizada para início de sessão único e as asserções transferidas são
identidades de utilizador. SAML é popular no mundo empresarial, uma vez
que é utilizado para permitir que os funcionários iniciem sessão em
aplicações externas. SAML não está alinhado para ser utilizado por APIs na
sua forma bruta. No entanto, existe uma extensão OAuth2: Security
Assertion Markup Language (SAML) 2.0 Profile for OAuth 2.0 Client
Authentication and Authorization Grants. Esta extensão permite que um
cliente solicite um token de acesso usando SAML, assumindo que o
servidor de autorização implementou a funcionalidade. Deves estar ciente
disto se SAML for algo que precisas de usar como parte de uma migração
para OAuth2.
Resumo
Neste capítulo, explorámos a importância de proteger as API e as normas
industriais robustas para o conseguir:
A autenticação estabelece a identidade do proprietário do recurso, que
nas API é um utilizador final ou uma aplicação que efectuauma
comunicação sistema a sistema.
O OAuth2 é o padrão de facto para proteger APIs e muitas vezes
utiliza o JWT como parte do cabeçalho do portador. Os tokens JWT
são muitas vezes codificados e assinados para garantir que não sejam
adulterados.
Diferentes concessões OAuth2 suportam diferentes cenários. As mais
comuns são a Concessão de código de autorização + PKCE e a
Concessão de credenciais do cliente.
Os tokens de atualização ajudam a suavizar a experiência do utilizador
final, que tem de estar sempre a pedir ao utilizador que introduza um
nome de utilizador e uma palavra-passe.
Os âmbitos OAuth2 ajudam a fornecer uma autorização de
granularidade grosseira e permitem ao utilizador final configurar o
acesso de um cliente.
O OIDC é utilizado quando o cliente necessita de informações sobre o
utilizador final. O OIDC fornece informações básicas sobre o
utilizador autenticado e pode, opcionalmente, fornecer detalhes
adicionais.
Fundamentalmente, deve agora compreender como pode identificar um API
callee e como pode proteger as suas próprias APIs. No entanto, isto não é o
fim da jornada, uma vez que a maioria das arquitecturas de software não
fica parada. Aprenderá sobre arquitetura evolutiva com APIs no próximo
capítulo.
1 Se não souberes o que é o HTTP Basic, consulta a especificação rfc7617.
2 O cabeçalho do pedido é um cabeçalho personalizado (por exemplo, X-API-KEY:
My_super_secret_API_Key) ou o cabeçalho de autorização.
3 O Google tem um bom artigo sobre este assunto aqui.
4 Um e-mail ou nome de utilizador não é normalmente uma boa escolha, uma vez que os
utilizadores os modificam ao longo do tempo. Se tiveres um identificador consistente, é mais
simples de gerir.
5 Um cenário típico é quando estás a utilizar o LinkedIn e este pede para aceder aos teus
contactos do GMail. O LinkedIn redirecciona-te para o Google e tu inicias sessão na tua conta
Google. É-te então apresentada uma mensagem que diz "O LinkedIn gostaria de aceder aos
teus contactos de e-mail". Depois de aceitares, o LinkedIn pode aceder aos teus e-mails.
6 Se quiseres saber mais sobre como adicionar ainda mais segurança à aplicação cliente que
obtém tokens de acesso, consulta o RFC8705. Esta especificação utiliza o Mutual TLS em vez
de cadeias secretas para obter tokens de acesso.
7 Não há problema em ter um cliente registado para vários tipos de concessões; o assunto do
recetor será diferente consoante a concessão utilizada. Como vemos aqui nas credenciais do
cliente, o sujeito é o cliente que faz o pedido e não em nome de um proprietário de recursos.
8 Pode ser uma matriz separada por vírgulas ou, como neste caso, separada por espaços.
Parte IV. Arquitetura evolutiva
com APIs
Esta secção explora a forma de evoluir a arquitetura de um sistema ou de
uma série de sistemas utilizando APIs, o que inclui a evolução de
aplicações legadas existentes para arquitecturas orientadas para serviços
baseadas em APIs e também a utilização da infraestrutura de APIs para
evoluir ou reformular um sistema para uma implementação eficaz num
ambiente Cloud.
O Capítulo 8 explora o redesenho de aplicativos monólitos em direção a
umaarquitetura orientada por API.
No Capítulo 9, aprenderás a utilizar a infraestrutura API para fazer evoluir
os teus sistemas actuais para plataformas Cloud.
O Capítulo 10 apresenta um resumo das principais lições que aprendeste ao
longo do livro. Este capítulo também apresenta formas de continuar a
desenvolver o estudo de caso e de avançar a sua aprendizagem sobre a
arquitetura de API.
Capítulo 8. Redesenhando
aplicativos paraarquiteturas
orientadas por API
Este trabalho foi traduzido com recurso a IA. Agradecemos o teu feedback e comentários:
translation-feedback@[Link]
Agora que tens uma sólida noção das operações e da segurança das API,
vais explorar como as API podem ser utilizadas para evoluir e aumentar as
aplicações existentes. Em Building Evolutionary Architectures (O'Reilly),
os autores discutem como uma arquitetura evolutiva suporta mudanças
guiadas e incrementais, em várias dimensões. Quer queiras ou não adotar
uma arquitetura evolutiva tal como definida nesse livro, a realidade é que
quase todos os sistemas bem sucedidos terão de evoluir ao longo do tempo
para satisfazer os novos requisitos dos utilizadores ou para reagir a um
ambiente em mudança. É raro que uma empresa ou organização não altere
os seus produtos com base no feedback dos clientes ou nas condições de
mercado em mudança, hardware que falha e se torna obsoleto), as estruturas
de aplicação subjacentes ou um serviço de terceiros.
As APIs são as interfaces naturais, as abstrações e os pontos de entrada
(encapsulados) para e dentro de um sistema e, como tal, podem ser
instrumentais no apoio a uma arquitetura evolutiva. Neste capítulo,
aprenderás por que a mudança é necessária, como projetá-la e onde
implementar padrões úteis.
Embora possas não te ter apercebido, tens estado a aplicar muitas das
competências discutidas neste capítulo ao longo do estudo de caso do
sistema de conferências. Recomendamos que penses na evolução do estudo
de caso à medida que lês este capítulo e que revejas o estado final da
arquitetura do sistema de conferências em "Estudo de caso: Um olhar para
trás na tua jornada".
Porquê utilizar APIs para desenvolver um
sistema?
Alterar software de uma forma segura pode ser difícil. Este desafio é ainda
maior se o software tiver uma destas três caraterísticas: um grande número
de utilizadores, complexidade inerente na conceção ou uma forte integração
com vários outros sistemas. A maioria dos sistemas "antigos" também
evoluiu de uma forma algo ad hoc, com muitas soluções temporárias,
correcções rápidas ou atalhos a tornarem-se uma parte integrante da
conceção do sistema.
Como arquiteto, as APIs podem ajudar-te a desenvolver um sistema. Uma
API pode ser um limite para um módulo ou componente, o que a torna um
ponto natural de alavancagem quando se tenta garantir que um sistema é
altamente coeso e pouco acoplado.
Criar abstrações úteis: Aumenta a coesão
Coesão refere-se ao grau em que os elementos dentro de um sistema
pertencem uns aos outros. A implementação de APIs e sistemas com
elevada coesão permite uma evolução mais fácil tanto para o fornecedor
como para o consumidor da API. Como fornecedor, pode alterar os
elementos internos do seu serviço, tais como alterar algoritmos, refactorizar
o código para melhorar o desempenho ou alterar os armazenamentos de
dados, e apenas tem de evitar modificar a interface externa de uma forma
que quebre a compatibilidade com versões anteriores. Como consumidor,
pode estar mais confiante na modificação e escalonamento do seu serviço,
com pontos de integração claros e compreensíveis na API existente.
Todos nós podemos compreender e apreciar as diferenças nas abstrações
para controlar diferentes veículos. Num carro, normalmente interage-se
com o painel de instrumentos, os pedais e o volante. Quando se opera um
vaivém espacial, o painel de controlo contém muitos mais painéis de
instrumentos, manípulos de controlo e botões. Os controlos do vaivém
espacial são coesos para a tarefa em questão, mas o nível de controlo e
complexidade aqui oferecido não seria apropriado para a conceção de um
carro. Esperemos que consigas ver a analogia com a conceção de APIs.
Pode ser tentador conceber o equivalente a um painel de controlo de um
vaivém espacial - particularmente em relação ao objetivo de "preparar as
APIs para o futuro" - quando, na realidade, o seu serviço comercial
subjacente é análogo à condução de um carro.
PROCURA APIS COM ELEVADA COESÃO
APIs que são altamente coesas são mais fáceis para um arquiteto entender, construir modelos
mentais e raciocinar sobre elas. APIs coesas também não violam o princípio da menor surpresa.
APIs altamente coesas também podem se tornar pontos focados de mudança dentro de um
sistema. Por exemplo, uma série de mudanças relacionadas pode requerer apenas a modificação de
uma única API, em comparação com a modificação de uma série de APIs necessárias ao modificar
um sistema com baixa coesão. Sempre se esforce e evolua em direção a sistemas altamente
coesos.
Como contra-exemplo de elevada coesão no âmbito do estudo de caso,
imagina que criaste uma API "utils" que expõe uma coleção de funções de
conveniência que podem ser utilizadas em todas as entidades da
conferência. Isto pode facilmente levar a uma situação em que uma
alteração no código por detrás de uma API, como a API dos participantes,
exige que outra API utilitária também seja actualizada. A menos que sejas o
autor original das APIs, ou que tenhas uma documentação e testes muito
bons, pode ser fácil não perceber isto e deixar o sistema com um
comportamento inconsistente ou incompatível.
HÁ MUITOS TIPOS DE COESÃO A CONSIDERAR!
Embora se fale frequentemente de coesão como se esta pudesse ser
medida numa única dimensão, existem vários tipos de coesão que os
arquitectos devem conhecer. Por exemplo, os sistemas podem ser
acoplados de várias formas:
Coesão funcional
Coesão sequencial
Coesão comunicacional
Coesão processual
Coesão temporal
Coesão lógica
Coesão coincidente
O Software Architect's Handbook (Packt Publishing) de Joseph Ingeno
fornece uma visão mais abrangente para os leitores que querem saber
mais.
É claro que a coesão é apenas uma das propriedades a ter em conta na
conceção e evolução dos sistemas. Vejamos agora a relação próxima da
coesão no software : o acoplamento.
Clarificar os limites do domínio: Promovendo o
Acoplamento Solto
Um sistema fracamente acoplado tem duas propriedades. Em primeiro
lugar, os componentes estão fracamente associados (têm relações
quebráveis) entre si, o que significa que as alterações num componente não
afectam a funcionalidade ou o desempenho de outro componente. Em
segundo lugar, cada um dos componentes do sistema tem pouco ou nenhum
conhecimento das definições de outros componentes separados. Os
componentes de um sistema fracamente acoplado podem ser substituídos
por implementações alternativas que fornecem os mesmos serviços e estão
menos limitados à mesma plataforma, linguagem, sistema operativo ou
ambiente de construção.
Como fornecedor, uma API com acoplamento frouxo permitirá a adoção
máxima do seu serviço em toda a organização, tanto do ponto de vista da
facilidade de integração como da facilidade de mudança. E para os
consumidores, uma API com acoplamento frouxo permitirá uma troca mais
fácil de componentes (potencialmente mesmo em tempo de execução),
permitirá testes mais fáceis e reduzirá o custo da gestão de dependências.
ACOPLAMENTO SOLTO PERMITE UMA SIMULAÇÃO E
VIRTUALIZAÇÃO MAIS FÁCEIS DURANTE O TESTE!
Uma API projetada com acoplamento frouxo em mente normalmente será muito mais fácil de
simular ou virtualizar ao realizar testes de integração e de ponta a ponta. Uma API com
acoplamento frouxo permite que a implementação do provedor seja facilmente trocada. Ao testar
um consumidor, a implementação da API do provedor pode ser trocada por um simples stub ou
serviço virtual que retorna a resposta necessária.
Em comparação, muitas vezes não é possível simular ou esboçar uma API que é altamente
acoplada. Em vez disso, terás de executar o fornecedor da API como parte do teu conjunto de
testes ou tentar utilizar uma versão leve (menos funcional) ou incorporada do serviço.
Estudo de caso: Estabelecimento de limites
de domínio dos participantes
Como exemplo com o caso de utilização do sistema de conferências,
imagina que o nosso serviço Attendee está altamente acoplado ao datastore
subjacente e expõe os dados no formato do esquema de dados subjacente.
Se, como fornecedor de serviços, quiseres mudar o datastore para algo
diferente, tens duas opções. Podes implementar um novo sistema para
adaptar todos os dados criados ou recuperados entre o formato antigo e o
novo, o que provavelmente exigirá um código de tradução complicado e
sujeito a erros. Ou podes modificar a tua API externa e fazer com que todos
os teus consumidores a adoptem - e não subestimes a dificuldade de o fazer
com um serviço amplamente adotado!
O PODER DA OCULTAÇÃO DE INFORMAÇÃO
Quando desenha uma API para ser altamente coesa e fracamente
acoplada, beneficia do princípio da ocultação de informação. Este é o
princípio da segregação das decisões de implementação que são mais
susceptíveis de mudar. Se o fizer corretamente, pode proteger outras
partes do sistema de modificações extensas se a decisão de desenho for
alterada.
No que diz respeito às API, a ocultação de informação é a capacidade
de impedir que certos aspectos de um fornecedor sejam acessíveis aos
seus consumidores. Isto pode ser conseguido utilizando apenas pontos
de extremidade de API centrados no negócio ou no domínio e não
divulgando nenhuma das abstrações internas ou o modelo de dados
específico da implementação ou o esquema .
Opções de arquitetura do estado final
À medida que evoluis e redesenhas as tuas aplicações e APIs monólitos,
deves ter uma visão clara do que pretendes que o teu sistema seja capaz de
fazer como resultado das alterações efectuadas. Caso contrário, esta cena
infame de Alice no País das Maravilhas tornar-se-á demasiado verdadeira:
"Podes dizer-me, por favor, em que direção devo ir a partir daqui?" "Isso
depende muito do sítio para onde queres ir", disse o Gato. "Não me
interessa muito para onde - disse a Alice. "Então não interessa para que
lado vais," disse o Gato. "Desde que chegues a algum lado", acrescentou
Alice como explicação.
Aprenderá mais sobre a abordagem para determinar os seus objetivos gerais
para sistemas em evolução na próxima seção deste capítulo, mas, por
enquanto, vamos fazer um tour pelas opções potenciais para a sua
arquitetura e como elas afetam o design da API.
Monólito
Nos últimos anos, o estilo de arquitetura monolítica tem sido mal visto. No
entanto, isto deve-se principalmente ao facto de a palavra "monólito" se ter
tornado sinónimo de "grande bola de lama".1 Na realidade, um monólito é
apenas um sistema de software composto de uma só peça e que funciona
como um processo único, uma aplicação autónoma. Não há nada de
fundamentalmente errado com uma arquitetura monolítica. Para muitos
sistemas, particularmente aplicações de prova de conceito, ou sistemas que
estão a ser criados à medida que o produto comercial subjacente se adapta
ao mercado, este estilo de arquitetura permitir-lhe-á avançar mais
rapidamente no início do projeto. Isto porque é fácil de compreender e
modificar, uma vez que existe apenas uma coisa para olhar, pensar
etrabalhar.
O desafio ao implementar APIs numa aplicação monólita é que é mais fácil
criar acidentalmente um design altamente acoplado, que só se tornará
aparente quando estiver a fazer modificações no futuro. Seguir as melhores
práticas, como utilizar o design orientado para o domínio (DDD) e
potencialmente utilizar uma arquitetura hexagonal, pagará dividendos mais
tarde.
Arquitetura orientada para os serviços (SOA)
A arquitetura orientada para os serviços (SOA) é um estilo de conceção de
software em que os serviços são fornecidos aos outros componentes por
aplicações ou serviços que comunicam através de uma rede. A primeira
utilização da SOA, muitas vezes referida como "SOA clássica", também
tem uma certa má reputação. Isto deve-se principalmente à utilização de
tecnologias pesadas com a SOA inicial, como SOAP, WSDL e XML, e
middleware orientado para o fornecedor, como ESBs e filas de mensagens.
Evoluir as suas aplicações para SOA pode ser benéfico, mas deve ter-se o
cuidado de evitar a utilização de estruturas ou middleware de fornecedores
que promovam um elevado acoplamento ou baixa coesão. Por exemplo,
evite sempre adicionar lógica empresarial a um gateway de API ou a um
barramento de serviços empresariais (ESB). Um dos maiores desafios na
conceção de sistemas baseados em SOA é obter a dimensão e a propriedade
dos serviços "corretos" - ou seja, encontrar um bom equilíbrio com a coesão
da API, ter uma propriedade clara do código em toda a organização e o
custo de conceção e tempo de execução de ter muitos serviços.
Microsserviços
Microsserviços são a mais recente implementação de SOA, em que o
software é composto de pequenos serviços independentes que se
comunicam por meio de APIs bem definidas. Há várias diferenças em
relação ao SOA clássico - ou seja, o uso de "pontos de extremidade
inteligentes e tubos burros" e evitar o uso de middleware pesado que pode
se tornar altamente acoplado aos seus serviços. Muitos livros foram escritos
sobre microsserviços,2 No entanto, os princípios fundamentais com a
evolução dos microsserviços incluem a criação de serviços orientados por
APIs altamente coesos e pouco acoplados.
Tal como acontece com o SOA clássico, um dos maiores desafios ao
projetar APIs usando uma arquitetura de microsserviços é obter os limites
(e a coesão) de uma API e os serviços subjacentes corretos. Usar técnicas
como mapeamento de contexto e tempestade de eventos do mundo do
DDD, antes de construir ou evoluir para microsserviços, muitas vezes
recompensará muito seus esforços futuros. O ideal é que as APIs de
microsserviços usem tecnologias leves que incentivem o acoplamento
frouxo, o que inclui tecnologias que já foram exploradas neste livro, como
REST, gRPC e tecnologias leves orientadas a eventos ou baseadas em
mensagens, como AMQP, STOMP ou WebSockets.
Funções
Embora uma promessa inicial de que as funções seriam a próxima evolução
dos microsserviços não se tenha concretizado, existe uma boa adoção desta
arquitetura numa série de organizações. Este estilo de arquitetura pode ser
um alvo útil a atingir se tiveres um sistema altamente orientado para
eventos - por exemplo, um sistema de negociação baseado no mercado que
seja altamente reativo a notícias e eventos de mercado, ou um sistema de
processamento de imagens com um pipeline de transformações
padronizadas a aplicar e relatórios a gerar.
É muito fácil conceber funções ou serviços que são tão simplistas que
muitos deles têm de ser orquestrados em conjunto para fornecer qualquer
valor comercial. Estes serviços e as suas APIs tendem então a tornar-se
altamente acoplados. O equilíbrio entre a reutilização e a manutenção pode
ser difícil e, por isso, este estilo de arquitetura não deve ser escolhido sem
reconhecer que tu e a tua equipa podem demorar algum tempo a ajustar a
ele.
Gerir o processo evolutivo
Evolução um sistema deve ser uma atividade gerida conscientemente.
Vejamos os aspectos a que deve estar atento ao fazer alterações na sua API.
Determina os teus objetivos
Antes de tentar evoluir um sistema, deve ser claro quanto à motivação por
detrás das mudanças. Os objetivos devem ser catalogados e claramente
comunicados à sua equipa e organização. Identificar suposições e objetivos
incorretos no início do processo de mudança é menos dispendioso do que
no momento em que a codificação começa. Os objetivos dividem-se em
duas categorias: funcionais e multifuncionais.
Objectivos funcionais evolutivos são pedidos de alteração de caraterísticas
ou funcionalidades. Normalmente, são impulsionados por utilizadores finais
ou partes interessadas da empresa. Pode ser necessário refactorizar, mas
estes tipos de objetivos centram-se em escrever mais código ou integrar
mais sistemas.
Os objetivos multifuncionais, também chamados de objetivos não
funcionais, concentram-se nas "habilidades", como manutenção,
escalabilidade e confiabilidade. Por exemplo, as mudanças de manutenção
são muitas vezes impulsionadas pela equipe de liderança técnica que deseja
reduzir o tempo gasto pelos engenheiros para entender, corrigir ou alterar
um sistema. As alterações de escalabilidade são muitas vezes impulsionadas
por partes interessadas do negócio que prevêem um aumento da utilização
ou da procura do sistema. O trabalho de fiabilidade centra-se muitas vezes
na tentativa de reduzir o número e o impacto das falhas num sistema. Estes
tipos de objetivos centram-se normalmente na refatorização de sistemas
existentes ou na introdução de novos componentes de plataforma ou de
infraestrutura.
Criar requisitos multifuncionais faz todo o sentido, mas como é que
definimos objectivos claros em relação às alterações que pretendemos fazer
ao nosso sistema e como é que sabemos se fomos bem sucedidos? É aqui
que as funções de fitness podem ajudar.
Utilizar funções de aptidão
Definir funções de aptidão é um mecanismo que fornece uma interrogação
constante da arquitetura do sistema e dos artefatos de código que compõem
o sistema. Pense em uma função como uma espécie de teste de
unidade/integração para a arquitetura, avaliando as "habilidades" da
arquitetura em uma métrica quantificável. Uma função de adequação é
incluída no pipeline de construção para ajudar a fornecer uma garantia
constante dos objetivos do sistema. No blog da Thoughtworks sobre
funções de adequação, várias categorias de foco são sugeridas, conforme
descrito na Tabela 8-1.
Tabela 8-1. Categorias de funções de aptidão
Qualidade do Esta é uma categoria de função de aptidão que muitas equipas provavelmente
código já têm em vigor até certo ponto. A execução de testes permite-te medir a
qualidade do código antes de o lançares em produção. Também vale a pena
considerar métricas adicionais - por exemplo, assegurar que a complexidade
cíclica é minimizada.
Resiliência Um teste inicial de resiliência consiste em implantar um sistema num
ambiente de pré-produção, executar um tráfego de amostra (ou sintético)
nesse ambiente e observar se a taxa de erro é inferior a um determinado limiar.
Um gateway de API ou uma rede de serviços pode muitas vezes ser utilizado
para injetar falhas no sistema e facilitar o teste de resiliência e disponibilidade
para determinados cenários.
Observabilidade Garantir que os serviços estão em conformidade (e não regridem) e publicar
os tipos de métricas que são exigidas pela plataforma de observabilidade é
fundamental. Em "Métricas importantes para APIs", analisou o que seria um
bom conjunto de métricas de API para publicar; isto poderia ser medido e
aplicado por uma função de aptidão contínua.
Desempenho Os testes de desempenho são muitas vezes uma reflexão tardia; no entanto, se
conseguires definir objectivos de latência e de débito, estes podem ser
medidos no pipeline de construção . Talvez uma das partes mais difíceis deste
objetivo seja obter dados semelhantes aos de produção para que o tipo de
testes de desempenho que precisas de executar seja significativo.
Conformidade Esta secção é muito específica para a empresa/organização em termos de
avaliação do que é fundamental monitorizar. Pode incluir requisitos de
auditoria ou de dados que são fundamentais para continuar a fornecer provas
de que uma empresa está a funcionar como esperado.
Segurança A segurança tem muitos aspectos diferentes e exploraste algumas das
considerações nos Capítulos 6 e 7. Uma possível função de aptidão pode ser
analisar as dependências da biblioteca no projeto e verificar se existem
vulnerabilidades conhecidas. Outra pode ser executar uma verificação
automatizada da base de código para garantir que não existem
vulnerabilidades do tipo OWASP.
Operacionalidade Muitas aplicações são construídas, colocadas em produção e depois começam
a evoluir; os utilizadores são integrados e depois começam os problemas.
Decidir sobre um conjunto mínimo de requisitos para o funcionamento da
plataforma é fundamental para garantir que a fábrica se mantém operacional.
Avaliar se a monitorização e os alertas estão implementados é um bom ponto
de partida.
Criar ADRs em torno das funções de fitness que gostarias de introduzir é
um bom ponto de partida. Pode ser complicado implementar imediatamente
tudo o que é apresentado na tabela anterior.
Algumas decisões são difíceis de reverter e é importante que, sempre que
possível, este tipo de decisões seja identificado.
NOTA
Uma decisão irreversível não é uma coisa má! No entanto, uma decisão irreversível sem uma
reflexão e ponderação cuidadosa é. Um ADR ajuda a resolver a questão comum do tipo "O que é
que eles estavam a pensar...?" e partilha o contexto histórico. As decisões tomadas coletivamente
através da utilização de ADRs e de uma discussão aberta conduzirão a uma arquitetura que tem
longevidade.
Decomposição de um sistema em módulos
Você já trabalhou em uma base de código que foi bash por ser um monólito
(talvez por você mesmo ou por outros)? Um dos autores trabalhou em uma
base de código de quatro milhões de linhas que tinha 24 anos de dívida
técnica (de acordo com o SonarQube). A estrutura do código se conectava
ad hoc a partir de muitas classes diferentes, criando um alto grau de
acoplamentodescontrolado em toda a aplicação. A refatoração de qualquer
parte da aplicação era difícil - muitas vezes a correção de um bug criava
outros bugs inesperados. Nenhum dos problemas era devido à natureza
monólita do sistema, mas sim à falta de organização e design do código.
A conceção de componentes modulares dentro de uma base de código ajuda
a definir limites claros e agrupamentos lógicos com base na coesão da
funcionalidade. Os módulos visam formar limites bem definidos que
ocultam os detalhes da implementação. Em linguagens como Java, existem
opções como método, classe, pacote e módulo. Cada uma destas
construções permite um grau diferente de ocultação de informação que se
sobrepõe às construções de encapsulamento orientadas a objectos. Para
efeitos da nossa discussão, vamos considerar que um módulo define um
particionamento arquitetónico a uma escala maior do que métodos e classes
individuais.
O livro do Sam Newman, Monolith to Microserviices (O'Reilly), é um livro
fantástico sobre modularidade e migrações de monólitos para
microsserviços:
Pessoalmente, eu adoto a abordagem de expor o mínimo possível a partir
da fronteira de um módulo (ou microsserviço). Quando algo se torna
parte da interface de um módulo, é difícil voltar atrás. Mas se o
esconderes agora, podes sempre decidir partilhá-lo mais tarde.
Vamos considerar quais módulos poderíamos potencialmente ter
introduzido no estudo de caso do sistema de conferência com o qual
começamos na Introdução.A Figura 8-1 introduz um módulo para
representar os padrões de controladores, serviços e objeto de acesso a dados
(DAO). Cada controlador expõe os pontos de extremidade RESTful e será
exposto pelo servidor Web que hospeda a aplicação. O módulo de serviço é
onde a lógica de negócios reside por trás do controlador, expondo uma
interface clara para os controladores. O módulo DAO é onde o objeto de
acesso a dados reside por trás dos serviços, expondo interfaces claras para
os serviços. As camadas de módulo são bastante comuns e chegar ao ponto
em que há uma dependência direcional única clara entre os módulos é uma
boa aplicação da modularidade.
Figura 8-1. Proposta de repartição dos módulos no estudo de caso da conferência
Agora que temos uma separação clara, cada módulo pode aplicar uma
estratégia para testar o assunto isoladamente. Outra vantagem de uma
abordagem modular é a capacidade de os programadores raciocinarem e
testarem dentro de um módulo.
Num projeto recente, um dos autores criou um padrão DAO para interagir
com a base de dados como um módulo da aplicação. Uma interface expôs a
funcionalidade aos outros módulos da aplicação, tornando claras as
interações com o módulo. Posteriormente, foi tomada a decisão de dividir a
lógica empresarial em três módulos que utilizavam os DAOs em serviços
independentes - uma primeira evolução do monólito. Os três novos módulos
foram muito bem separados nos seus próprios serviços, utilizando o módulo
DAO como biblioteca. A conceção de módulos bem definidos permitiu uma
evolução independente e a tomada de decisões evolutivas sobre o sistema.
A utilização de diagramas C4 para exprimir software é uma abordagem
ligeira ao nível dos componentes para definir as relações entre os
componentes do sistema. O diagrama de componentes, abordado pela
primeira vez na Introdução, ajuda a fornecer um mecanismo de revisão das
relações e ajuda a definir estruturas modulares.
A definição de módulos nas aplicações é um bom passo de conceção,
embora existam muitas opções para a forma como a modularidade é
alcançada. Procura utilizar o suporte ao nível da linguagem para ajudar a
aplicar módulos e chegar a acordo com a equipa sobre a abordagem que
funcionará melhor para a sua pilha técnica .
Criar APIs como "costuras" para extensão
O conceito de "costuras" foi introduzido pela primeira vez no livro de 2004
de Michael Feather, Working Effectively with Legacy Code (Pearson). Uma
costura é um ponto em que a funcionalidade é costurada - pode ser
considerada como o ponto em que um assunto em consideração interage
com outro.3 Isso geralmente é alcançado por técnicas como injeção de
dependência, injetando o colaborador e executando contra uma interface
que permite a substituibilidade. A consideração de substituibilidade é
importante; isso permite testes efetivos sem a necessidade de executar todo
o sistema (por exemplo, usando mocks ou testes duplos).
Se a aplicação foi construída sem um bom design, a definição de uma
costura pode ser complexa e dificultar a compreensão de todo o
comportamento. Ao trabalhar com código legado, pode ser difícil separar e
refatorar o código para trabalhar de forma mais [Link] Carlo
apresenta uma receita útil para separar costuras de código legado,
assumindo que os testes ainda não existem:
Identifica os pontos de mudança (costuras)
Quebra as dependências
Escreve os testes
Faz as tuas alterações
Refactor
Ao conceber as alterações, considera a criação de um design de API para a
forma como dois (ou potencialmente mais) colaboradores se ligam. Se
houver potencial para que a definição da costura possa ser utilizada fora do
tema em consideração, uma API interserviços pode ser uma óptima escolha.
Por exemplo, se a costura for uma execução semelhante em muitas partes
diferentes da base de código e o objetivo for dividir um serviço em
arquitecturas mais pequenas baseadas em serviços, esta é uma oportunidade
para definir a reutilização entre serviços .
Identificação de pontos de alavancagem de mudança
dentro de um sistema
Às vezes é fácil para arquitetos ou desenvolvedores identificar "pontos de
alavancagem de mudança", ou código e serviços que são candidatos óbvios
para refatorar e mudar a fim de tornar um sistema "melhor" de alguma
forma - por exemplo, mais performático, extensível, seguro. Se trabalhaste
na indústria durante mais do que alguns anos, tenho a certeza que já
trabalhaste num sistema com uma área particularmente desafiante da base
de código, ou num módulo que está constantemente a mudar e a ser alterado
(e muitas vezes os dois problemas estão correlacionados!), e pensaste que
gostarias de passar algum tempo a resolver o problema. No entanto, estes
pontos de alavancagem nem sempre são óbvios, particularmente se herdaste
uma base de código ou um sistema. Para esta situação, livros como Your
Code as a Crime Scene (Pragmatic Bookshelf) de Adam Tornhill serão úteis
para compreender o teu código e as tuas aplicações. Ferramentas
relacionadas podem ser muito úteis, tais como utilitários de deteção de
churn do sistema de controlo de versões que localizam partes de uma base
de código em constante mudança, ou ferramentas de medição da
complexidade do software que analisam uma base de código ou serviço
com cada execução do pipeline de construção.
Entrega e verificação contínuas
No Capítulo 5, você analisou a importância de automatizar a implantação e
os lançamentos de sistemas com acoplamento frouxo. A necessidade de
verificar continuamente os sistemas à medida que implantamos mais é
fundamental para permitir uma arquitetura evolutiva.
Padrões de arquitetura para sistemas em
evolução com APIs
APIs fornecem uma abstração poderosa para a evolução de sistemas em
direção a uma arquitetura moderna e também para introduzir novos recursos
e mudanças. Como você descobriu nos Capítulos 3 e4, gateways e
construções baseadas em malha de serviço permitem uma migração
operacional usando gateways. Ao criar uma mudança evolutiva, uma
consideração primária durante o período evolutivo é mitigar os riscos da
evolução e maximizar os benefícios o mais rápido possível. Vamos rever
alguns padrões de arquitetura que podem ajudar na migração para APIs.
Figo Estrangulador
Um figo estrangulador é qualquer uma das numerosas espécies de figos
tropicais que crescem à volta de uma árvore existente. Embora um figo
estrangulador muitas vezes sufoque e ultrapasse o seu hospedeiro, há
algumas provas de que as árvores envoltas em figos estranguladores têm
mais probabilidades de sobreviver a tempestades tropicais, sugerindo que a
relação pode ser algo mutualista. Em última análise, este é o objetivo de
uma arquitetura evolutiva - suportar um sistema em mudança, o que pode
resultar na remoção completa do que existia anteriormente. Isto é
conseguido através da introdução de novos componentes da aplicação
enquanto o mecanismo antigo ainda está em vigor. O objetivo é migrar
gradualmente para a nova abordagem baseada na API.
Em "Estudo de caso:A Figura 8-2 mostra um diagrama C4 da utilização de
sinalizadores de caraterísticas. Isto funciona bem para costuras que existiam
anteriormente como interações em processo para a introdução de novas
APIs num serviço. No entanto, se existirem muitos consumidores a interagir
com o serviço fora do processo, seria irrealista esperar que todos
implementassem e controlassem umsinalizador de caraterísticas.
Figura 8-2. Diagrama de contentor da aplicação de conferência para participantes e sinalizadores
de caraterísticas
Outro modelo é a utilização de um proxy ou gateway para fazer a interação
com a API, encaminhando para a implementação antiga ou para a nova
implementação. Este é um tipo de fachada que utiliza um proxy, o que
significa que o consumidor da API utiliza a mesma API e não tem
conhecimento da migração de um serviço para outro que está a acontecer
nos bastidores.
Gerir o padrão strangler fig nos bastidores pode ser complicado e a
introdução de um novo componente pode ser um ponto único de falha ou
um estrangulamento, a menos que seja atenuado. O proxy não deve assumir
a lógica empresarial, caso contrário, será difícil removê-lo no final da
migração. Gerir o processo antigo e moderno lado a lado é um desafio para
garantir a coerência dos dados entre os dois serviços. Pode encontrar mais
orientações para ultrapassar estes desafios em em Monólito para
microsserviços.
Fachada e adaptador
Os padrões de fachada e de adaptador são padrões bem conhecidos que
podem ajudar na migração para serviços modernos. O padrão strangler fig é
um tipo de fachada, interceptando chamadas de API e ocultando a
complexidade nos bastidores.
Uma situação comum que encontrámos é a presença de aplicações
distribuídas em grande escala que já utilizam uma forma de API. Talvez a
comunicação entre serviços seja efectuada através de SOAP-RCP ou de
outro protocolo antigo. Os adaptadores podem ajudar a evoluir a
arquitetura, introduzindo um componente que converte um determinado
pedido SOAP numa nova chamada à API RESTful. No entanto, a reescrita
de protocolos pode ser difícil de implementar corretamente. Deve ter-se
cuidado para evitar reduzir a coesão ou introduzir o acoplamento.
No Capítulo 1, exploramos o uso do gRPC como uma tecnologia popular e
eficaz para a comunicação leste-oeste. Usando o projeto grpc-gateway, é
possível apresentar um endpoint RESTful JSON que é convertido para a
representação gRPC em segundo plano.
Uma fachada é normalmente menos complexa do que um adaptador; um
gateway de API tradicional limita-se a encaminhar os pedidos de API,
enquanto um adaptador será responsável pela conversão para uma
representação compreendida pela aplicação de destino.
AVISO
Se um gateway de API ultrapassar a linha de atuação do padrão de fachada para o padrão de
adaptador, o acoplamento aumenta imediatamente. Não te esqueças de perguntar se ainda estás a
utilizar o componente certo para a tarefa!
Bolo de camadas API
Um padrão de migração da API que é muito falado em contextos
empresariais é o "Layered APIs" ou "API Layer Cake", que se baseia no
padrão de camadas de "separação de preocupações" visto em aplicações
empresariais monólitas tradicionais. Durante os anos 2000, foi considerada
uma prática recomendada em aplicações empresariais Java ou .NET
implementar a funcionalidade da aplicação numa série de camadas - por
exemplo, camadas de apresentação, aplicação, domínio e armazenamento
de dados. A ideia central era que cada pedido do utilizador que entrava
numa aplicação fluía sequencialmente para baixo e depois para cima de
cada camada. Este padrão permitia a abstração e a reutilização da
funcionalidade específica de cada camada, com a solução de compromisso
de que um corte de funcionalidade de ponta a ponta exigia frequentemente a
modificação de muitas camadas - ou seja a coesão dentro da camada de
cada camada veio à custa de um alto acoplamento de camadas para fornecer
uma unidade de funcionalidade comercial.
A abordagem moderna baseada em API para este padrão é vista na
Estratégia de Aplicação em Camadas Pace da Gartner.4 São utilizados
novos nomes para cada API ou camada de microsserviço, com a
apresentação a ser traduzida aproximadamente para sistemas de
envolvimento (SoE), aplicação para sistemas de diferenciação (SoD) e
armazenamento de dados para sistemas de registo (SoR).
Ao longo do tempo, este padrão ganhou uma má reputação, particularmente
à medida que os sistemas legados que o implementaram se tornaram cada
vez mais difíceis de evoluir. Este padrão encoraja os arquitectos e os
programadores a tomar atalhos, como duplicar a funcionalidade entre
muitas camadas para evitar chamar uma camada adicional, ou contornar
camadas ao lidar com pedidos, como a camada de apresentação que
comunica diretamente com a camada de armazenamento de dados.
Identificar pontos problemáticos e
oportunidades
É muitas vezes tentador evitar trabalhar em partes de um sistema ou base de
código que têm uma má reputação, seja por má qualidade de código, alta
complexidade ou apenas falhas frequentes. Alguns pontos problemáticos
nem sempre são óbvios até que tenhas interrupções graves para resolver. No
entanto, nunca desperdices uma boa crise - a identificação e catalogação de
componentes problemáticos dentro do sistema pode ajudar a rastrear e
melhorar problemas conhecidos. Vamos explorar alguns dos problemas
comuns que ocorrem dentro de um sistema distribuído baseado em API e
como abordar isto como uma oportunidade de mudança.
Problemas de atualização e manutenção
Identificação de onde ocorrem as actualizações e os erros comunicados no
sistema global pode ajudar a criar uma "lista de ocorrências":
Percentagem elevada de falhas de modificação para um subsistema
específico
Elevado volume de questões de suporte levantadas para um sistema
Grande quantidade de rotatividade de uma parte específica do sistema
ou da base de código
Elevada complexidade (identificada através de análise estática e
complexidade ciclomática)
Baixo nível de confiança fornecido pelas equipas de desenvolvimento
quando questionadas sobre a facilidade de uma mudança necessária
Um problema de manutenção ou de subsistema pode ser uma boa
oportunidade para introduzir uma abstração de API para retirar a
funcionalidade e usar o strangler fig para impulsionar a melhoria. Também
pode ser um cheiro de código que os bons princípios de codificação não são
seguidos. No Capítulo 9, também consideraremos como abordamos as
aplicações à medida que migramos para arquiteturas baseadas em API em
novas infraestruturas.
Problemas de desempenho
Os acordos de nível de serviço (SLAs) são um excelente limite superior
para rastrear e monitorizar o desempenho. No Capítulo 5, analisou a
monitorização e as métricas que ajudam a sinalizar um problema com um
serviço de API. A realidade é que muitas aplicações não constroem
protecções proactivas contra a introdução de problemas. Se a primeira vez
que a equipa ouve falar de um problema de desempenho é através de
feedback direto do cliente ou da monitorização da produção - por exemplo,
um sistema de ponta que esgotou um orçamento de latência de resposta a
pedidos do utilizador - a equipa está imediatamente em desvantagem
quando reage ao problema.
Os problemas de desempenho podem ser arquitectónicos; por exemplo, tem
um serviço que chama um serviço localizado numa região diferente ou
através da Internet? Quando se trata de problemas de desempenho, a
medição e a criação de um plano objetivo são fundamentais. Faça uma
medição do sistema existente, crie uma hipótese sobre onde o desempenho
pode ser melhorado e, em seguida, teste e verifique. É importante
considerar o sistema como um todo, em vez de tentar otimizar um
componente específico isoladamente. Automatizar o processo de medição
permite-lhe introduzir a medição do desempenho como parte do processo
de construção.
Quebra de dependências: APIs altamente acopladas
Um antipadrão a ter em conta é a coordenação sincronizada de lançamentos
em diferentes partes do sistema. Isto é um sinal de que as APIs estão
potencialmente muito acopladas, e quebrar isto pode ser uma oportunidade
para reutilizar ainda mais e reduzir o atrito dos lançamentos.
Uma competência que é muitas vezes negligenciada nos cursos de formação
e nas equipas é trabalhar eficazmente com código legado. Muitas vezes, os
programadores não têm a certeza de como introduzir os tipos de alterações
que ajudam a quebrar as dependências. Há duas técnicas que são úteis a
considerar quando se procura quebrar dependências.
A técnica de sprout é abordada no livro Working Effectively with Legacy
Code (Trabalhando efetivamente com código legado), de Michael Feather,
de 2004. Muitas vezes, é muito difícil fazer testes unitários em código que
não foi construído com os testes em mente. Sprout envolve criar a nova
funcionalidade em outro lugar, testá-la e adicioná-la a um método legado
conhecido como ponto de inserção. Outra técnica é envolver a
funcionalidade existente criando um novo método com o mesmo nome e
assinatura do método antigo. O método antigo é renomeado e chamado a
partir do novo método, com qualquer lógica adicional antes que o método
legado seja chamado.
Se um serviço é predominantemente legado, trabalhar com código legado é
uma habilidade crítica a ser desenvolvida. Trabalhar em katas de
codificação ou programação em pares em áreas complexas da base de
código ajudará a promover a compreensão em toda a equipe. Sandro
Mancuso criou um excelente vídeo no YouTube que vários de nós usamos
para entender abordagens práticas para trabalhar com código legado.
Resumo
Neste capítulo, aprendeste a utilizar uma abordagem orientada por API para
fazer evoluir as aplicações monólitas vintage para uma arquitetura baseada
em serviços:
As API fornecem muitas vezes uma abstração natural ou "costura"
dentro dos sistemas, suportando a decomposição de serviços e
fachadas para suportar mudanças graduais. Como tal, são uma força
poderosa na caixa de ferramentas de qualquer arquiteto ao evoluir um
sistema.
Conceber e construir sistemas tendo em conta estes conceitos
universais de arquitetura tornará a evolução, os testes e a
implementação de sistemas mais fáceis e seguros.
Sem estabelecer e partilhar claramente estes objectivos, as migrações
podem tornar-se intermináveis, o que esgota os recursos, fornece
pouco valor e pode afetar o moral.
Padrões bem estabelecidos, como o figo estrangulador, podem
aumentar a velocidade e a segurança da evolução de um sistema e
evitar a necessidade de reinventar a roda.
O próximo capítulo baseia-se no foco deste capítulo e alarga o âmbito da
arquitetura evolutiva para incluir também a migração para a infraestrutura
Cloud.
1 Para mais informações e para conheceres a história da grande bola de lama, consulta estes
artigos da Wikipedia e da InfoQ.
2 O livro Building Microsserviços, 2nd Edition (O'Reilly) de Sam Newman é o nosso favorito.
3 Neste contexto, "objeto de estudo" é uma classe ou um conjunto de classes.
4 Para obter mais informações sobre o Pace, consulte "Accelerating Innovation by Adopting a
Pace-Layered Application Strategy" da Gartner e "A Pace-Layered Integration Architecture"
de Dan Toomey.
Capítulo 9. Usando a
infraestrutura de API
paraevoluir em direção às
plataformas Cloud
Este trabalho foi traduzido com recurso a IA. Agradecemos o teu feedback e comentários:
translation-feedback@[Link]
No capítulo anterior, fornecemos uma visão geral das abordagens de
arquitetura que podem ser usadas ao evoluir as APIs e os serviços que as
alimentam. Um tópico igualmente importante a ser considerado na evolução
dos sistemas é a infraestrutura, as plataformas e o hardware subjacentes.
Muitas vezes, isso muda e evolui em seu próprio ritmo: quando o hardware
quebra, as empresas e a tecnologia são fundidas ou adquiridas, ou as
políticas de TI de toda a organização determinam que a infraestrutura seja
atualizada. No entanto, por vezes, um programa de API conduzirá a
alterações na infraestrutura, particularmente em relação à modernização e à
mudança para uma infraestrutura mais semelhante à Cloud (definida por
software). Agora, vais aprender como implementar e gerir a evolução de um
sistema e a correspondente infraestrutura de API.
Este capítulo se baseia nos fundamentos da arquitetura apresentados nos
capítulos anteriores e explora como é possível usar a infraestrutura de API,
como gateways de API, malhas de serviço e portais de desenvolvedor, para
evoluir um sistema ao migrar para um ambiente baseado em Cloud. Você
aprenderá as diferenças entre um "lift and shift" de aplicativos, uma
"replataforma" e uma "refatoração ou rearquitetura" e desenvolverá as
habilidades para saber qual é a mais apropriada em um contexto específico.
O estudo de caso que o acompanha mostrará como o gateway de API
existente e o serviço Attendee podem ser migrados para a Cloud. A
utilização de um gateway de API pode fornecer transparência de
localização para serviços e APIs que estão a ser servidos, o que permite a
implementação de um serviço na Cloud e que o tráfego seja gradualmente
transferido do serviço existente para o novo, com impacto limitado (ou
nulo) nos consumidores. Explorarás também as opções de migração
nascentes para migrar serviços para a Cloud utilizando a funcionalidade de
multilocalização/cluster de uma malha de serviços.
Estudo de caso: Mudança do Serviço de
Atendimento ao Clientepara a Cloud
Para a próxima evolução do estudo de caso do sistema de conferência, você
se concentrará em mover o serviço Attendee para a infraestrutura de um
fornecedor de Cloud. A principal motivação para fazer isso é que os
proprietários do sistema de conferência desejam, eventualmente, eliminar o
ônus de executar seu próprio data center. Isso envolverá, em última análise,
a transferência de todos os novos serviços, o aplicativo monólito, o
middleware (como gateways de API) e os repositórios de dados para a
Cloud. Optamos por migrar primeiro o serviço Attendee, pois é o
componente mais novo e também um dos serviços que recebe mais tráfego.
A Figura 9-1 mostra como o serviço Attendee extraído está sendo
executado atualmente fora do contexto do aplicativo principal do sistema de
conferência.
Figura 9-1. Modelo C4 que mostra o serviço Participante extraído
Como explorarás neste capítulo, existem várias abordagens para mover este
serviço e a infraestrutura de suporte para a Cloud. Antes de mergulhar na
mecânica da abordagem anterior, vamos primeiro explorar as opções que
devemos considerar antes de decidir sobre a estratégia de migração.
Escolher uma estratégia de migração para a
Cloud
Constrói no artigo da Gartner de 2010, "Migrar aplicações para a Cloud:
Rehost, Refactor, Revise, Rebuild, or Replace?" A Amazon Web Services
publicou um blogue em 2016 que apresentava os "seis Rs" da migração para
a Cloud.1 Estes artigos são um excelente ponto de partida se tiveres a tarefa
de avaliar ou liderar uma migração da tua arquitetura e sistemas existentes
para a Cloud. Como as APIs são muitas vezes o componente orientado para
o negócio mais próximo do utilizador - e um ponto-chave de entrada para a
maioria dos pedidos - deves prestar especial atenção a elas quando decidires
a tua abordagem à migração. Os seis Rs apresentam um espetro de opções
desde "não fazer nada" até uma reconstrução completa ou reforma de um
sistema. São eles:
Manter ou revisitar
Rehost
Replataforma
Recompra
Refactor/Re-arquitetar
Retira-te
Vamos examinar os seis Rs da AWS com mais detalhe e explorar como
pode utilizar esta estrutura para desenvolver a infraestrutura da API.
Manter ou revisitar
Esta é a estratégia de não fazer nada (por enquanto). Embora possa ser
tentador desconsiderar esta abordagem, muitos arquitectos (nós incluídos)
sugerem que "escolha as suas batalhas" e, por vezes, a batalha de migrar
uma API não vale o retorno do seu esforço. Esta decisão deve, obviamente,
basear-se numa avaliação comercial e técnica sólida e deve comunicar a
decisão de não tomar medidas interna e externamente, conforme
apropriado. É aqui que os ADRs brilham - em termos de fornecer o rasto de
papel e a lógica destas decisões para referência futura.
COMUNICAR ALTERAÇÕES E DEPRECIAÇÕES
Um negócio e uma avaliação técnica de uma API ou sistema atual podem levar-te a decidir contra
a evolução do sistema no momento atual. Nesta situação, é ainda importante comunicar quaisquer
datas conhecidas até às quais seja necessário tomar medidas. Por exemplo, se uma unidade de
negócio for encerrada numa data conhecida, ou se um sistema chegar ao fim da sua vida útil
(EOL), ou se uma licença de software ou de armazenamento de dados expirar numa data
conhecida, isto deve ser comunicado aos consumidores como um aviso de depreciação. É muito
provável que tenha um aviso de depreciação obrigatório incluído nos contratos e SLAs, por isso
não se esqueça de os consultar.
Um fator-chave quando se considera a possibilidade de mover aplicações
para a Cloud é a introdução de latência entre dois serviços durante as etapas
evolutivas. Se tiver um serviço de elevado tráfego, ocorrerá um
abrandamento para cada pedido ao atravessar os limites da rede. Garantir
que existe uma compreensão do aspeto da degradação é uma consideração
importante e, se isso violar um SLA, mover o serviço pode não ser uma
opção. Em "Modelar intercâmbios e escolher um formato de API",
aprendeu a escolher um protocolo e a conceber uma API dentro de
restrições, o que é uma consideração importante ao atravessar limites.
A retenção não seria uma estratégia viável para o nosso caso de utilização
de conferência, uma vez que seria simplesmente "chutar a lata pela estrada"
e adiar o objetivo de migrar para a Cloud .
Rehost
"Rehost" é também conhecido como "lift-and-shift". Envolve a
transferência de sistemas e cargas de trabalho para uma plataforma Cloud
sem qualquer rearquitectura. Se procura consolidar cargas de trabalho ou
simplesmente tem de migrar da sua infraestrutura atual, esta pode ser uma
estratégia eficaz. No entanto, tenha em atenção que a infraestrutura Cloud
nem sempre se comporta da mesma forma que o hardware local, pelo que
deve identificar e confirmar quaisquer suposições que tenha feito.
SÊ CAUTELOSO COM SISTEMAS ESPECIALIZADOS E
HARDWARE PERSONALIZADO
Por exemplo, os sistemas especializados mais antigos podem assumir que toda a comunicação
dentro do sistema ocorre através de um barramento local ou de ligações de rede dedicadas (o que
não é o caso na Cloud), e certas tecnologias de armazenamento de dados assumem caraterísticas
de hardware específicas (ou garantias) do sistema de armazenamento em bloco subjacente. Em
caso de dúvida, faz a tua pesquisa.
O rehosting pode ser uma abordagem viável para o nosso estudo de caso,
embora tenhamos escolhido a opção de replataforma para nos permitir tirar
partido de algumas funcionalidades da Cloud.
Replataforma
Esta abordagem é por vezes referida como "lift-tinker-and-shift". É muito
semelhante ao rehosting, mas também tira partido de alguns serviços em
nuvem que requerem um retrabalho mínimo. Por exemplo, um datastore
existente que é executado como um componente do sistema pode ser
trocado por um serviço em nuvem compatível com o protocolo. Podes
trocar um datastore MySQL nativo por um AWS RDS compatível com
MySQL, uma base de dados Azure ou GCP Cloud SQL. Outra replataforma
comum é atualizar ou alterar um servidor de aplicações ou um contentor
específico de uma linguagem.
Esta é a abordagem que escolhemos para o nosso estudo de caso do sistema
de conferência, para que possamos evitar grandes retrabalhos e, ao mesmo
tempo, tirar partido dos novos serviços Cloud à medida que nos afastamos
da nossa infraestrutura local existente.
Recompra
Recompra envolve principalmente a mudança para um produto diferente -
por exemplo, subscrever um serviço de envio de correio eletrónico baseado
em SaaS em vez de continuar a gerir um servidor de correio eletrónico
internamente.
Como o nosso exemplo de sistema de conferência consiste principalmente
em aplicações personalizadas e repositórios de dados padrão, não há opção
de recompra (exceto, talvez, a compra de um sistema de gestão de
conferências pronto a usar, que está fora do âmbito damigração).
Refactor/Re-arquitetar
Refatoração significa uma reimaginação de como a aplicação é arquitetada
e desenvolvida, normalmente usando recursos nativos do Cloud. Como em
qualquer refatoração, a funcionalidade central (externa) da aplicação ou do
sistema não deve mudar, mas a forma como a funcionalidade é realizada
internamente definitivamente mudará. Isso geralmente é impulsionado por
uma forte necessidade comercial de adicionar recursos, escala ou
desempenho que, de outra forma, seriam difíceis de alcançar no ambiente
existente da aplicação. Por exemplo, se uma organização decidiu decompor
um aplicativo monólito existente em microsserviços, um movimento em
direção à adoção de padrões nativos da Cloud também é frequentemente
considerado. Esse padrão tende a ser o mais caro para implementar, mas, se
você tiver um bom ajuste de produto-mercado e estiver sendo limitado por
suas escolhas de tecnologia existentes, ele também pode ser o mais
benéfico.
Não escolhemos explicitamente esta abordagem para o nosso estudo de
caso, uma vez que já tens estado a rearquitectar o sistema de conferências
ao longo deste livro. Um ponto importante a considerar é que a
infraestrutura e o design das APIs conduzem a uma forma de pensar mais
nativa da Cloud. Definir e modelar APIs, conforme discutido no Capítulo 1,
facilita um mecanismo simples para representar serviços durante a
refacção/rearquitectura. Também é fundamental que muitos serviços ou
interações baseados na Cloud também se baseiem em APIs. A estratégia em
torno das APIs ao rearquitectar é tão importante como o serviço e os
sistemas que planeias utilizar na Cloud.
Com a re-arquitetura agora concluída, faz todo o sentido replanejar para a
Cloud antes de fazer alterações adicionais à arquitetura.
Retira-te
"Retirar" sistemas durante uma migração significa simplesmente que te
livras deles. Durante muitas das grandes migrações em que participámos, há
frequentemente pelo menos um sistema existente que já não está a ser
utilizado e que foi simplesmente esquecido. Como já não há necessidade
desta funcionalidade, o sistema pode simplesmente ser desativado e o
recurso de hardware libertado ou reciclado.
Um dos objetivos gerais era aposentar o sistema de conferências antigo e,
assim que a reformulação e a refatoração estiverem concluídas, podemos
avançar com .
Estudo de caso: Replataforma do Serviço de
Atendimento ao Clientepara a Cloud
Tendo em conta o contexto fornecido na secção anterior deste capítulo,
decidimos "replataformar" o nosso serviço de participantes, para além de
migrar a porta de entrada da API para a Cloud. Manter ou retirar o serviço
não eram opções válidas, tendo em conta os requisitos para migrar para a
Cloud. A recompra também não fazia sentido neste contexto. Como já
tínhamos rearquitectado a funcionalidade dos participantes, extraindo-a
para um serviço no início deste livro, a refacção/rearquitectura não parecia
adequada. No entanto, quando estiver a adicionar novas funcionalidades ao
sistema de conferências no futuro, rearquitectar o sistema (potencialmente
extraindo um serviço) e transferi-lo para a Cloud seria uma opção a
considerar fortemente. O rehosting poderia ser uma estratégia sólida, mas
estamos interessados em tirar partido de uma base de dados como serviço
baseada na Cloud em vez de "levantar e mudar" a nossa própria instância da
base de dados MySQL.
Conforme mostrado na Figura 9-2, a abordagem de "replataforma"
fornecerá uma boa base para continuar a migração à medida que movemos
mais serviços para a Cloud. Mover o gateway da API para a Cloud agora
também ajudará a suportar o tráfego da API que está a ser encaminhado de
forma incremental do local existente no local para a Cloud.
A Figura 9-2 mostra o estado final da arquitetura replataforma.
Figura 9-2. Diagrama de infraestrutura mostrando o gateway de API extraído e o serviço Attendee
Vamos agora considerar como podes implementar outros requisitos, como a
gestão de API, à medida que o sistema de conferências evolui.
Papel da Gestão de API
Independentemente da estratégia adoptada para a sua jornada evolutiva, a
gestão de APIs pode desempenhar um papel fundamental na migração e
também em desbloquear o valor das APIs em toda a organização e mesmo
fora dela. Os gestores de APIs são essencialmente um gateway
sobrealimentado no centro, fornecendo uma grande variedade de
funcionalidades adicionais para publicar e controlar APIs. Os gestores de
APIs fornecem políticas que permitem preocupações de ponta, tais como
desafios OAuth2, validação de conteúdos, limitação de taxas,
estrangulamento e muitas outras funcionalidades típicas de um gateway.
Além disso, eles podem fornecer portais de desenvolvedor contendo um
mercado de todas as APIs que os desenvolvedores podem usar ao criar
sistemas para consumir as APIs oferecidas. As organizações também podem
usar o gerenciamento de API para monetizar o acesso às APIs, tanto para
clientes externos quanto para "estornos" internos, que são comuns em
empresas e implantações entre divisões. Em "Taxonomia atual do gateway
de API", compartilhamos taxonomias para gateways de API, e o
gerenciamento de APIs está na categoria de gateway corporativo.
Talvez a parte mais importante da gestão de APIs seja o facto de poder
oferecer um ponto central para descobrir APIs, enquanto continua a fazer
alterações nos bastidores. É possível, por exemplo, fazer a interface com o
sistema de conferências antigo através de uma API, ao mesmo tempo que
oferece a nova API de participantes. No caso dos organizadores de
conferências, podem potencialmente considerar a oferta de uma API que
forneça "gestão de conferências como um serviço" que permita que outras
conferências a utilizem, ou que faça a interface de uma forma controlada
com o sistema CFP externo. Partindo do princípio de que os contratos sobre
a API não mudam, é possível evoluir atrás de uma camada de gestão de
API.
As organizações falam frequentemente sobre o conceito de ser API First, o
que significa que todas as interações entre sistemas são cuidadosamente
concebidas e modeladas como APIs. Este foi um conceito que explorámos
no Capítulo 1. Seguindo bons princípios de design e esforçando-se por um
design "API-First", isto permite-lhe desbloquear valor tanto externamente
para os clientes como internamente dentro da organização em geral,
utilizando ferramentas como a gestão de APIs.
À medida que a arquitetura evolui para se tornar híbrida, abrangendo
diferentes redes e implementações, as ideias sobre o tráfego também têm de
ser desafiadas.
Norte-Sul versus Este-Oeste: A indefinição
das linhas degestão do tráfego
Com uma visita guiada às várias opções disponíveis para uma migração da
infraestrutura da API concluída, vamos agora explorar a forma como a
nossa abordagem escolhida para a replataforma terá impacto na gestão do
tráfego da API dentro do sistema de conferência em evolução. Como
optámos por migrar os nossos serviços de forma incremental - em vez de
arriscarmos uma grande explosão - a execução de serviços em vários
ambientes Cloud e centros de dados locais apresenta desafios adicionais.
Tal como acontece com muitas migrações Cloud incrementais, o tráfego
terá de transitar por várias redes para satisfazer um pedido de API feito por
um utilizador.
Começa na borda e trabalha para dentro
No nosso estudo de caso, optámos por começar no limite, migrando o
gateway da API para a Cloud juntamente com um único serviço. Ao fazê-
lo, a equipa de migração pode ter a oportunidade de configurar inicialmente
um ambiente de Cloud completamente novo, sem perturbar o sistema
existente. Por exemplo, pode ser implementado um duplicado do gateway
da API atual na Cloud, enquanto o gateway existente é deixado a funcionar
como está. Isto permite-lhe minimizar o risco, configurando de forma
incremental o gateway da API baseado na Cloud, sem perturbar o sistema
de produção existente.
Muitas vezes, é sensato construir uma prova de conceito isolada puramente
dentro da Cloud e, só depois de verificada, começar a experimentar o
encaminhamento para dentro e para fora do ambiente da Cloud. A conceção
de arquitecturas baseadas na Cloud é muitas vezes uma mudança de
paradigma do ponto de vista da conceção. Não subestimes o tempo
necessário para aprender e compreender uma nova infraestrutura.
Atravessar fronteiras: Roteamento entre redes
Antes que uma migração para a Cloud possa entrar em funcionamento,
muitas vezes é necessário garantir que os sistemas novos e antigos possam
interagir através das diferentes redes. Conforme discutido nos Capítulos 3 e
4, há uma série de opções para implementar esse roteamento. Se houver
uma única aplicação monólita e um pequeno número de rotas simples, pode
ser mais fácil rotear temporariamente do novo gateway de API para o
antigo, potencialmente com um simples redirecionamento HTTP. No
entanto, se houver um grande número de rotas que atravessam redes, ou se
o tráfego não puder sair da rede depois de ter entrado, terás de considerar
outras opções, como pontos finais ou peering de redes privadas virtuais, ou
malha de serviço multicluster.
Com o tráfego de API a transitar por várias redes, é muito provável que
tenhas de consultar as tuas equipas de InfoSec, uma vez que isto irá
perturbar a abordagem tradicional às defesas de perímetro e à arquitetura
zonal. Vamos explorar este tópico com mais profundidade e saber como a
mudança para redes de confiança zero pode ajudar.
Da Arquitetura Zonal à Confiança Zero
Antes de aprender como os gateways de API modernos e as malhas de
serviço podem ajudar-te a implementar redes de confiança zero, vamos
primeiro explorar a abordagem tradicional à arquitetura de rede zonal.
Entra na zona
Com o aumento da popularidade da Internet comercial , cada vez mais
indústrias regulamentadas começaram a fornecer acesso a aplicações, o que
significava que tanto os novos sistemas como os sistemas internos
existentes tinham de ser orientados para o utilizador. O aparecimento de
arquitecturas zonais proporcionou uma melhor prática na conceção de redes
seguras. O zonamento é utilizado para mitigar o risco de uma rede
completamente aberta ou plana, segmentando os serviços de infraestrutura
em agrupamentos lógicos que têm as mesmas políticas de segurança de rede
e requisitos de segurança. Considera uma vulnerabilidade como o
Log4Shell (CVE-2021-44228), uma vulnerabilidade de dia zero que
representa um risco significativo para as aplicações Java que utilizam as
bibliotecas Log4J afectadas. Usando a exploração, um invasor pode obter
acesso a um host em uma rede e começar a executar atividades maliciosas.
O alcance do impacto e dos serviços sob exploração é conhecido como o
raio de explosão do ataque. Se todas as solicitações não confiáveis entrarem
em uma zona que tenha acesso a poucas informações de alto valor, o raio de
explosão será minimizado e as operações de segurança terão tempo de agir
para evitar interrupções graves. As zonas tendem a se formar em cascata,
com cada passagem para a zona seguinte aplicando mais mitigação de
defesa em profundidade para desafiar o tráfego de entrada.
As zonas são separadas por perímetros (pontos de interface de zona)
implementados através de dispositivos de segurança e de rede. O
zonamento é uma abordagem de conceção lógica utilizada para controlar e
restringir o acesso e os fluxos de comunicação de dados apenas aos
componentes e utilizadores de acordo com a política de segurança.
Existem muitas abordagens para definir as zonas e os requisitos de
segurança associados, tanto padronizados (muitas vezes a nível nacional)
como personalizados. No entanto, como mostrado na Figura 9-3, quatro
zonas típicas são encontradas na maioria das arquitecturas zonais:2
Figura 9-3. Uma arquitetura zonal típica, retirada do ITSG-22 do governo canadiano
Zona pública (ZP)
Esta zona é totalmente aberta e inclui redes públicas, como a Internet
pública, a rede telefónica pública comutada e outras redes e serviços de
base de operadores públicos.
Zona de acesso público (ZAP)
Esta zona medeia o acesso entre os sistemas operacionais e a Zona
Pública e inclui frequentemente uma zona desmilitarizada (DMZ).
Zona de Operações (OZ)
Uma OZ é o ambiente padrão para operações de rotina e com controlos
de segurança apropriados nos sistemas finais. Esta zona pode ser
adequada para o processamento de informações sensíveis; no entanto, é
geralmente inadequada para grandes repositórios de dados sensíveis ou
aplicações críticas sem controlos de segurança adicionais fortes e fiáveis
que estão para além do âmbito destas orientações.
Zona Restrita (RZ)
Esta zona proporciona um ambiente de rede controlado, geralmente
adequado para serviços de TI críticos para as empresas ou grandes
repositórios de informações sensíveis e suporta o acesso a partir de
sistemas na Zona Pública através de uma PAZ e uma OZ.
Essa abordagem de design de rede baseada em perímetro é um pouco
semelhante à antiga defesa "castelo e fosso", em que um invasor terá mais
dificuldade no ponto de entrada, mas, uma vez dentro das muralhas do
castelo, geralmente terá mais facilidade para navegar. Isso ocorre em grande
parte porque são feitas suposições sobre qualquer comunicação originada
dentro do perímetro, da rede ou do local do sistema. No entanto, a
infraestrutura Cloud pode desafiar essas suposições. Em muitas plataformas
Cloud, a localização geográfica e de rede da infraestrutura subjacente é
abstraída ou não está disponível. Mesmo com as protecções implementadas
pelos fornecedores de clusters, existe ainda o risco de um ataque à cadeia de
fornecimento, em que o software é manipulado com conteúdo malicioso no
momento da construção. Outra possibilidade é um utilizador malicioso no
local do fornecedor da infraestrutura, que acede a informações a partir do
nível da plataforma.
É possível executar diferentes tipos de segurança em diferentes tipos de
implantação, mas uma abordagem mais homogénea reduz o risco de se
fazerem suposições e a necessidade de aprender diferentes técnicas de
segurança. Existe uma confiança inerente concebida numa arquitetura
baseada em zonas, o que levou à evolução de uma nova abordagem: a do
zero trust.
Não confies em ninguém e verifica
O modelo de segurança de confiança zero , também conhecido como
arquitetura de confiança zero ou segurança sem perímetro, descreve uma
abordagem à conceção e implementação de sistemas de rede modernos. O
principal conceito subjacente ao modelo de segurança de confiança zero é
"nunca confies, verifica sempre", o que significa que os dispositivos não
devem ser considerados fiáveis por defeito, mesmo que estejam ligados a
uma rede autorizada, como uma LAN empresarial, e mesmo que tenham
sido previamente verificados. A abordagem tradicional- confiar nos
dispositivos dentro de um "perímetro empresarial" nocional ou nos
dispositivos ligados através de uma VPN - não é relevante no ambiente
complexo de uma rede empresarial. A abordagem de confiança zero
defende a autenticação mútua, incluindo a verificação da identidade e da
integridade dos dispositivos sem ter em conta a localização, e o
fornecimento de acesso a aplicações e serviços com base na confiança da
identidade e da integridade do dispositivo em combinação com a
autenticação do utilizador.
Os oito princípios delineados nas nossas orientações ajudar-te-ão a
implementar a tua própria arquitetura de rede de confiança zero num
ambiente empresarial. Os princípios são
Conhece a tua arquitetura, incluindo utilizadores, dispositivos, serviços
e dados.
Conhece as tuas identidades de utilizador, serviço e dispositivo.
Avalia o comportamento do utilizador, o dispositivo e o estado do
serviço.
Utiliza políticas para autorizar pedidos.
Autentica e autoriza em todo o lado.
Concentra a tua monitorização em tudo o que diz respeito ao acesso:
utilizadores, dispositivos e serviços.
Não confies em nenhuma rede, incluindo a tua.
Escolhe e concebe serviços de confiança zero.
Os oito princípios descritos são perfeitamente razoáveis, no entanto, são
muito difíceis de considerar na arquitetura zonal. O conceito de
pressupostos de confiança de uma zona desafiaria muitos destes pontos. Por
exemplo, uma arquitetura zonal muitas vezes só autentica um utilizador
uma vez na extremidade do sistema, e todas as redes dentro do perímetro
são de confiança por defeito. Vamos explorar como podemos
potencialmente evoluir para uma arquitetura baseada na confiança zero.
Papel do Service Mesh em arquitecturas de confiança
zero
AZero Trust Architecture, publicada pelo NIST em 2020, é um documento
fantástico para definir a confiança zero e as principais considerações
arquitectónicas. A malha de serviços e os gateways de API combinados
fornecem uma plataforma fantástica para implementar arquitecturas
baseadas na confiança zero. A utilização da malha de serviços ajuda a
fornecer uma modelação homogénea da forma como os componentes da sua
arquitetura são representados e como o tráfego flui entre eles. As
tecnologias subjacentes permitem um modelo concreto em torno da
identidade do processo em execução e o gerenciamento de certificados
ajuda a afirmar e provar a identidade. A integração do rastreamento e
monitoramento ativos permite a análise em todos os pontos da plataforma,
tanto para os usuários quanto para os serviços subjacentes e a integridade
do pod do Kubernetes. Todo o tráfego de entrada deve ter um desafio forte,
muitas vezes afirmando essa solicitação com o OAuth2, conforme discutido
no Capítulo 7, e o tráfego dentro do cluster pode usar o mTLS para uma
forte afirmação de autenticação e autorização.
Não confies em nenhuma rede, incluindo a tua, é um desafio interessante
para o service mesh. Na maioria dos modelos de service mesh, um sidecar
está intimamente ligado a um serviço ou aplicação, permitindo a gestão do
tráfego e a segurança através do encaminhamento pelo sidecar. No entanto,
a simplicidade desta implementação significa que não podes fazer
afirmações concretas sobre a plataforma em que estás a correr. O que está
sob a aplicação e o sidecar precisa de ser protegido para não fazer
suposições baseadas na confiança.
Aumenta o Service Mesh com políticas de rede
A segurança da plataforma sustenta quaisquer suposições que faças ao nível
da aplicação. Por conseguinte, precisas de descer um nível para obteres
confiança zero total. Kubernetes tem o conceito de NetworkPolicies que
permite a utilização de um plug-in de rede, como o Calico. Os controlos
permitem-te criar um isolamento de pods da plataforma em que operam.
Por exemplo, a política a seguir impedirá que todo o tráfego de entrada e
saída possa entrar em um determinado pod. Para uma arquitetura de
confiança zero, esse seria o padrão para pods; ao aplicar a regra, o pod se
torna totalmente isolado:
---
apiVersion: [Link]/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
spec:
podSelector: {}
policyTypes:
- Egress
- Ingress
As implementações de service mesh dependem muitas vezes da pesquisa de
nomes de serviços através de um sistema DNS central. Mesmo esse sistema
está bloqueado. Tens de começar a permitir alguns cenários controlados na
plataforma para que permaneçam bloqueados, mas ainda assim permitir que
o service mesh funcione. Na política seguinte, permitimos a pesquisa de
DNS no sistema de conferência antigo, para que este localize o serviço
Attendee:
---
apiVersion: [Link]/v1
kind: NetworkPolicy
metadata:
name: allow-dns
spec:
podSelector:
matchLabels:
app: legacy-conference
policyTypes:
- Egress
egress:
- ports:
# allow DNS resolution
- port: 53
protocol: UDP
---
Neste ponto, o serviço de conferência legado do service mesh pode
descobrir onde estão os participantes através do sidecar, mas o pedido em si
seria bloqueado. Cada regra de encaminhamento no service mesh precisa de
uma regra de permissão correspondente definida no adaptador de política de
rede. Neste exemplo final, abrimos a regra para que o sistema de
conferência legado comunique com o serviço Attendee:
---
apiVersion: [Link]/v1
kind: NetworkPolicy
metadata:
name: allow-conference-egress
spec:
podSelector:
matchLabels:
app: legacy-conference
policyTypes:
- Egress
egress:
- to:
- namespaceSelector:
matchLabels:
[Link]/[Link]: attendees
Para que o ingresso funcione, também seria necessário adicionar regras de
ingresso do gateway de malha de serviço até os serviços de destino. Em
"Decisões de aplicativos para lançamentos de software eficazes",
descrevemos as decisões no nível do aplicativo para uma plataforma
opinativa. Garantir que as regras e a configuração sejam aplicadas de
maneira consistente no momento do lançamento é outro motivo para
considerar uma plataforma opinativa.
Ao usar a malha de serviço e as políticas de rede, você aprendeu como criar
uma arquitetura microssegmentada. O benefício dessa abordagem é que
você pode ter um cenário em que a segurança é consistente em uma
arquitetura híbrida tanto com a Cloud quanto com ambientes que antes eram
baseados em zonas. Um padrão comum que está surgindo é o uso de uma
malha de serviço para fazer a ponte entre redes diferentes ("multicluster").
Isso é realizado por meio do uso de malhas de serviço de peering entre os
clusters, colocando o plano de dados local e da Cloud sob o conhecimento
de um plano de controle combinado.3 Na Figura 9-4, a malha de serviço é
responsável por todo o roteamento e pode fornecer uma arquitetura de
confiança zero entre as redes. A vantagem de seguir esse caminho é que ele
leva a uma arquitetura evolutiva segura e a um ambiente de segurança
homogêneo. Ao fazer com que o local funcione como a Cloud, agora há um
caminho fácil para evoluir os serviços restantes para a Cloud.
Figura 9-4. Emparelhamento em malha de serviço multicluster
Resumo
Neste capítulo, aprendeste como a utilização da infraestrutura de API, como
gateways de API, service meshes e portais de programador, pode ser
utilizada para evoluir um sistema quando se muda para um ambiente
baseado na Cloud:
Há uma série de abordagens para evoluir ou migrar um sistema
baseado em API para a Cloud, desde manter ("não fazer nada"), rehost,
replataforma, recompra, refactor/re-arquitetura (reescrever para tirar
partido da infraestrutura da Cloud) e retirar.
Ao migrar uma aplicação API para a Cloud, verifica frequentemente
que a linha entre a gestão do tráfego norte-sul (entrada) e este-oeste
(serviço-a-serviço) se esbate.
Um gateway de API pode ser utilizado como uma ferramenta para a
migração, uma vez que pode encapsular a funcionalidade e atuar como
uma fachada para vários sistemas backend que operam a partir de
diferentes ambientes e redes.
A indústria está a afastar-se das arquitecturas de rede zonais para
sistemas de "confiança zero", e a tecnologia service mesh pode
facilitar esta mudança.
A adoção da confiança zero permite combinar as arquitecturas de
confiança zero e zonal, o que ajuda a fazer a ponte entre os sistemas
Cloud e locais durante um período de migração.
Com a tua viagem através do panorama da arquitetura das API quase
concluída, o próximo e último capítulo encerra os conceitos-chave e
apresenta uma visão do futuro neste espaço.
1 Ver "6 estratégias para migrar aplicações para a Cloud".
2 Os leitores interessados podem obter mais informações sobre arquitecturas zonais no Network
Security Zoning do governo canadiano.
3 A mecânica deste processo varia consoante a implementação da rede de serviços.
Capítulo 10. Encerramento
Este trabalho foi traduzido com recurso a IA. Agradecemos o teu feedback e comentários:
translation-feedback@[Link]
Nos nove capítulos anteriores deste livro, empreendeste uma viagem que
abrangeu tudo, desde a conceção de APIs até à sua implementação,
segurança e funcionamento. O foco foi a arquitetura, mas igualmente
importante é a forma como aplicas a arquitetura na tua organização.
Neste capítulo final do livro, explorarás as tecnologias API emergentes que
podem desempenhar um papel mais importante no futuro e aprenderás
como nos mantemos actualizados com estas melhores práticas, ferramentas
e plataformas em constante mudança.
Estudo de caso: Um olhar para trás na tua
viagem
Ao longo do livro, temos vindo a dar passos evolutivos para atualizar e
amadurecer o caso de utilização da arquitetura do sistema de conferências
com que começámos. Pode ver o ponto de partida na Figura 10-1.
Figura 10-1. Arquitetura original do sistema de conferência
Como mostrado na Figura 10-2 e discutido na Introdução, tomámos a
decisão (com base nos requisitos dos intervenientes no sistema de
conferências) de extrair a funcionalidade dos participantes para um serviço
baseado na API que seria executado como um processo autónomo externo
ao sistema de conferências .
Figura 10-2. Extrai o serviço Attendee do sistema de conferência
Nos Capítulos 1 e2, a arquitetura permaneceu estática enquanto
explorávamos a forma de conceber e testar a API e o serviço Attendee. No
Capítulo 3, demos o nosso primeiro grande passo evolutivo, introduzindo
um gateway de API entre o cliente utilizador final e o sistema de
conferências existente e o novo serviço.
Como mostra a Figura 10-3, o cliente faz agora pedidos ao sistema de
conferências através do gateway da API, que fornece uma abstração e um
ponto de entrada único para o tráfego delimitado ao sistema de conferências
antigo ou ao novo serviço Attendee. Este passo introduziu um padrão de
fachada, permitindo o controlo sobre quando o serviço antigo é chamado
em relação ao serviço moderno.
Figura 10-3. Adiciona um gateway de API ao sistema de conferência
Nós demos um passo adiante no Capítulo 4, extraindo a funcionalidade da
sessão de conferência do sistema de conferência legado para um novo
serviço Session e introduzindo uma malha de serviço para lidar com o
tráfego da API de serviço a serviço. Neste ponto do estudo de caso, a
arquitetura parecia com a Figura 10-4.
Figura 10-4. Modelo C4 mostrando a extração do serviço Session do sistema de conferência
Com foco no lançamento incremental de serviços baseados em API no
Capítulo 5, criamos uma versão interna e externa do serviço Attendee e
usamos sinalizadores de recursos para determinar para qual serviço a
solicitação de um usuário foi encaminhada.A Figura 10-5 mostra os dois
serviços Attendee lado a lado no diagrama de arquitetura estática.
Figura 10-5. Modelo C4 mostrando dois serviços de Participante sendo roteados por meio de
sinalizadores de recursos
No Capítulo 6, centrámo-nos na segurança e, embora a arquitetura se
mantivesse estática, introduzimos o conceito de uma aplicação móvel que
liga para o sistema de conferência, como mostra a Figura 10-6, de modo a
proporcionar um cenário realista para a modelação de ameaças.
Figura 10-6. Arquitetura C4 mostrando uma aplicação móvel que interage com o sistema de
conferência
O Capítulo 7 adicionou um sistema CFP externo à arquitetura, conforme
ilustrado na Figura 10-7, o que exigiu a implementação de uma
autenticação externa (virada para o utilizador) e autorização.
Figura 10-7. Sistema externo a comunicar com o sistema de conferência
No Capítulo 9, nos concentramos na migração do serviço Attendee e do
gateway de API para uma plataforma Cloud, o que resultou na arquitetura
mostrada na Figura 10-8.
Figura 10-8. Migração Cloud para sistema de conferência
Finalmente, no Capítulo 9, fornecemos um modelo potencial para migrar
para uma arquitetura de confiança zero, com uma abordagem uniforme para
implantação, roteamento e segurança. Na Figura 10-9, há uma opção de
arquitetura híbrida enquanto a jornada evolutiva continua para a Cloud.
Figura 10-9. Migração Cloud para o sistema de conferências utilizando a malha de serviços
multicluster
Ao longo do estudo de caso, o nosso foco tem sido destacar os principais
pontos de decisão que tu e a tua equipa terão de tomar à medida que um
sistema típico evolui para se tornar baseado em APIs ou serviços. Desde o
início humilde de um único serviço e base de dados a funcionar no local, à
medida que caminhaste para um sistema multi-serviços a funcionar na
Cloud e no local, aprendeste que, com o aumento da flexibilidade que esta
implementação final oferece, também existem soluções de compromisso
com a complexidade da arquitetura e da infraestrutura.
Embora isto conclua a evolução do nosso estudo de caso neste livro,
encorajamos-te a experimentar a criação de novos requisitos, a conceção de
novas APIs e a extração de serviços adicionais.
APIs, a Lei de Conway e a tua organização
Este não é um livro sobre design organizacional, mas queríamos mencionar
a importância disso em relação ao design, construção e execução de APIs.
A "Lei de Conway" tornou-se famosa na comunidade de microsserviços, e o
conceito também se aplica à arquitetura de APIs:
Qualquer organização que conceba um sistema (definido em sentido
lato) produzirá um desenho cuja estrutura é uma cópia da estrutura de
comunicação da organização.
—Melvin Conway em How Do Committees Invent?
Ou, dito de forma mais sucinta, "se tiveres quatro grupos a trabalhar num
compilador, terás um compilador de 4 passagens." Já vimos isto no mundo
das APIs - como gostamos de brincar, "se tiveres quatro grupos a trabalhar
num sistema de microsserviços, terás quatro camadas de APIs." Não
podíamos esperar cobrir o tópico do design organizacional com a
profundidade que merece neste livro e, por isso, gostaríamos de recomendar
a leitura dos seguintes livros:
Topologias de equipa (IT Revolution Press)
Design de organização de TI Agile: Para a transformação digital e a
entrega contínua (Addison-Wesley)
A Arte da Escalabilidade (Addison-Wesley)
Qualquer sistema baseado em API é inerentemente um sistema
sociotécnico, pelo que deves ter sempre em conta o aspeto "sociotécnico"
tanto quanto o "técnico".
Compreender os tipos de decisão
Jeff Bezos, o fundador da Amazon, é famoso por muitas coisas, e uma delas
é a sua discussão sobre as decisões de Tipo 1 e as decisões de Tipo 2. As
decisões de Tipo 1 não são facilmente reversíveis, e tens de ter muito
cuidado ao tomá-las. As decisões de Tipo 2 são fáceis de mudar:
"Normalmente, este conceito é apresentado em relação à confusão entre os
dois e à utilização de processos de Tipo 1 em decisões de Tipo 2: "O
resultado final disto é a lentidão, a aversão ao risco irreflectida, a
incapacidade de experimentar o suficiente e, consequentemente, a
diminuição da invenção. No entanto, na maioria dos casos - especialmente
no contexto de uma grande empresa - a escolha de tecnologias que
permitem a API, como um gateway de API ou um service mesh, é uma
decisão de Tipo 1. Certifica-te de que a tua organização age em
conformidade!
Prepara-te para o futuro
Quando escrevemos um livro, captamos naturalmente a experiência e o
conhecimento num determinado momento, mas há sempre novos
desenvolvimentos a surgir. Seguem-se três tópicos que considerámos que
ainda não mereciam secções completas, mas que, no entanto, vale a pena
manter debaixo de olho pelo seu impacto futuro na arquitetura das API.
Comunicação assíncrona
APIs assíncronas são muito populares, dividindo-se geralmente em duas
categorias: cliente-servidor e cliente-broker. Um exemplo de relação
cliente-servidor é obtido com tecnologias como gRPC, e a relação cliente-
broker é obtida usando tecnologias intermediárias como Kafka. Como você
aprendeu no Capítulo 1, as especificações OpenAPI foram fundamentais
para descrever e especificar consistentemente as APIs REST.
A AsyncAPI é uma norma empolgante e em desenvolvimento que fornece
uma especificação para APIs assíncronas. Um dos desafios das APIs
assíncronas é suportar a variedade de formatos de protocolo e a gama de
tecnologias. É definitivamente uma norma a observar, uma vez que a
popularidade das arquitecturas orientadas para eventos e a necessidade de
definir intercâmbios é um espaço em rápido crescimento.
HTTP/3
O HTTP/3 é a terceira versão principal do Protocolo de Transferência de
Hipertexto utilizado para trocar informações na World Wide Web,
juntamente com o HTTP/1.1 e o HTTP/2. A semântica do HTTP é
consistente em todas as versões: os mesmos métodos de pedido, códigos de
estado e campos de mensagem são normalmente aplicáveis a todas as
versões. As diferenças residem no mapeamento desta semântica para os
protocolos de transporte subjacentes. Tanto o HTTP/1.1 como o HTTP/2
utilizam o TCP como transporte (como no TCP/IP). O HTTP/3 utiliza o
QUIC, um protocolo de rede da camada de transporte que utiliza o UDP. A
mudança para o QUIC visa corrigir um problema importante do HTTP/2
chamado "bloqueio de cabeça de linha", que afecta em particular os sítios
Web que requerem o carregamento de vários recursos.
O HTTP/3 prometia ganhos de velocidade potencialmente grandes, mas
como o protocolo de transporte subjacente mudou, isso exigirá
actualizações dos proxies de entrada e de outros componentes de Network+.
A boa notícia é que, no momento em que escrevemos este artigo, o HTTP/3
já é suportado por mais de 70% dos navegadores Web em funcionamento.
Malha baseada na plataforma
Como sugeriu no Capítulo 4, muitos sinais apontam para a fusão do service
mesh com as ofertas de plataformas modernas. Se essa tendência continuar,
pode ser sensato adotar o mesh integrado na pilha de tecnologia do
fornecedor escolhido. Da mesma forma que a maioria das organizações que
adotam a pilha Kubernetes de um fornecedor de Cloud não substitui as
implementações de contêineres (OCI) ou de rede (CNI), pode muito bem
ser o mesmo no futuro com as comunicações de serviço a serviço. Como
parte desta evolução, recomendamos que te mantenhas atento aos padrões
relacionados neste espaço, como o Service Mesh Interface (SMI). O
surgimento e a adoção de interfaces sólidas apontam certamente para a
homogeneização desta camada da pilha de comunicação.
O que vem a seguir: Como continuar a
aprender sobre aarquitetura da API
Começámos este livro mencionando que nós os três começámos a jornada
que levou à criação deste livro em fevereiro de 2020 na Conferência de
Arquitetura de Software da O'Reilly (SACON). Todos adoramos aprender e
participar em eventos é uma grande parte da nossa abordagem contínua para
adquirir novas competências e conhecimentos. Uma das perguntas gerais
mais comuns que nos fazem está relacionada com a forma como abordamos
a aprendizagem e a experimentação de novas tecnologias. Nesta secção do
capítulo, vamos partilhar contigo as nossas práticas, ideias e hábitos.
Aperfeiçoa continuamente os fundamentos
Todos nós acreditamos que é de vital importância revisitar constantemente
os fundamentos de qualquer habilidade que queiras dominar. Isto é
especialmente importante numa indústria tão orientada para o domínio das
modas como a do desenvolvimento de software e operações. Iremos cobrir
alguns dos locais onde procuramos este tipo de conhecimento, mas
queremos salientar que ao navegar em sites, ler livros, participar em
conferências e afins, procuramos ativamente a cobertura existente e mais
recente dos fundamentos. Por exemplo, em muitas conferências de
arquitetura, encontrarás sessões que abordam tópicos como a coesão e o
acoplamento, e todos nós já aprendemos e fomos relembrados de conceitos
que levamos para os nossos escritórios e aplicamos no dia seguinte. Para
além de lermos o livro mais recente sobre plataformas Cloud, também
lemos novas abordagens a tópicos tradicionais, como "The Architect
Elevator: O arquiteto da transformação", de Gregor Hohpe.
É um cliché na nossa indústria que "o que é velho é novo", e os ciclos de
tecnologia que se repetem constantemente em formas ligeiramente
diferentes podem ser navegados de forma muito mais eficaz por designers
de arquitetura que estão constantemente a lembrar-se dos fundamentos.
Manter-se atualizado com as notícias do sector
Recomendamos que reúna e aperfeiçoe constantemente uma lista de sítios
Web e de redes sociais que fornecem cobertura das notícias mais recentes
nos domínios da arquitetura e das API. A leitura destas listas uma vez por
semana ajudará a afinar a tua perceção das tendências e tecnologias
emergentes que poderás querer investigar. Por exemplo:
InfoQ
DZone
A nova pilha
Arquitetura de software Reddit
Para além destes sites de notícias gerais e agregadores, é provável que
também encontres certas organizações ou indivíduos que escrevem blogues
úteis sobre tópicos emergentes. A utilização de um leitor de RSS, como o
Feedly, pode permitir-te reunir estas fontes e analisá-las semanal ou
mensalmente. O Twitter pode ser uma ferramenta poderosa para obter
informações e comentários sobre tecnologias emergentes; seguir indivíduos
que têm interesses semelhantes e contribuem para projectos de código
aberto é uma boa forma de descobrir antecipadamente novas
funcionalidades do.
Radares, quadrantes e relatórios de tendências
Apesar de deveres sempre realizar as tuas próprias experiências e provas de
conceito, também recomendamos que te mantenhas atualizado sobre as
tendências tecnológicas específicas através de sites de analistas. Este tipo de
conteúdo pode ser especialmente útil quando estás a debater-te com um
problema ou identificaste uma solução e precisas de uma peça específica de
tecnologia que muitos fornecedores oferecem. Recomendamos as seguintes
fontes de informação para saber mais sobre o estado da arte da tecnologia
no espaço da API:
Radar de tecnologia da ThoughtWorks
Quadrante Mágico da Gartner para Gestão de APIs de Ciclo de Vida
Completo
Cloud Native Computing Foundation (CNCF) Tech Radar
Relatórios de tendências do InfoQ
Várias organizações e indivíduos também publicam periodicamente folhas
de cálculo de comparação de tecnologias, que podem ser úteis para simples
"avaliações em papel", a fim de selecionar produtos para experimentar. É
evidente que terás de verificar se estas comparações são tendenciosas (os
fornecedores patrocinam frequentemente este tipo de trabalho) e garantir
que a data de publicação é relativamente recente.
Aprende sobre as melhores práticas e casos de
utilização
Também recomendamos que estejas constantemente atento às melhores
práticas e aos casos de utilização relacionados com o trabalho que estás a
fazer. Muitas organizações gostam de partilhar o porquê, o quê e o como do
que estão a fazer. É importante compreender as motivações para tal, mas
muitas vezes é uma mistura de altruísmo, direitos de gabarolice,
sensibilização para as vendas e recrutamento. É sempre necessário ter
cuidado quando se aprende sobre casos de utilização, uma vez que a maior
parte deles se inclina para uma cobertura positiva, podendo saltar as
tentativas iniciais falhadas, as coisas que correram mal ou as coisas que
ainda estão a correr mal. No entanto, o contexto fornecido pode permitir-te
fazer corresponder os problemas e as soluções à tua organização e equipa.
Por vezes, isto pode confirmar a pilha de tecnologia ou a abordagem
escolhida e, noutras ocasiões, pode fazer-te repensar!
Geralmente, recomendamos que procures ambos, e a vantagem das
apresentações em conferências é que podes conversar com os
apresentadores depois da palestra para saberes mais! Segue-se uma lista de
conferências em que participamos regularmente :
Série de conferências QCon
CraftConf
APIDays (centrado na API)
KubeCon (específico da plataforma)
Devoxx / JavaOne (específico da linguagem)
Eventos online da O'Reilly
Aprende fazendo
Acreditamos que os arquitectos devem permanecer como engenheiros de
software praticantes. Podes não estar a colocar o código em produção todos
os dias, mas recomendamos que arranjes tempo na tua agenda para,
periodicamente, trabalhares em conjunto com um engenheiro da tua equipa
ou realizares pesquisas e experimentares as tecnologias mais recentes. Sem
fazeres isto regularmente, é fácil que a empatia de um arquiteto pelos
programadores se desvaneça. Fazer este trabalho também permite
compreender novos pontos de fricção ou uma tarefa que pode ter sido
introduzida pela adoção de novas tecnologias. Por exemplo, descobrimos
que muitos arquitectos não compreenderam inicialmente o impacto que a
tecnologia de contentores teria nas cadeias de ferramentas dos
programadores. A menos que tenha experiência na criação de imagens de
contentores e no seu envio para um registo remoto, é fácil ignorar o impacto
destas acções no seu fluxo de trabalho diário de criação e manutenção de
API.
Aprende ensinando
Como se espera que seja evidente neste livro, também aprendemos muito
através do ato de ensinar. Quer se trate de escrever livros, dar cursos ou
fazer apresentações em conferências, nada supera a experiência de reunir a
informação necessária para ensinar um conceito.
Quer se trate de educar os programadores sobre os fundamentos ou de
partilhar novas práticas recomendadas, este ato de ensinar reforçará
continuamente o teu conjunto de competências e estabelecerá a tua
credibilidade no seio da equipa maior.
Boa sorte na tua jornada para dominar a arquitetura da API.
Índice
protocolo de abstração para as subvenções OAuth2, Terminologia e
mecanismos das subvenções OAuth2
abstrações, alta coesão e, Criando Abstrações Úteis: Aumenta a Coesão-
CriandoAbstrações Úteis: Aumentar a coesão
gestão de contas com gateways de API, Monetize APIs: Gestão de contas,
faturação e pagamento
padrão arquitetónico do adaptador, Fachada e Adaptador
ADCs (controladores de entrega de aplicações), meados dos anos 2000:
Controladores de entrega de aplicações (ADCs)
Diretrizes ADR
escolha de normas API, Diretriz ADR: Escolher uma norma API
Escolher a solução de gestão de tráfego de entrada, Orientação: Proxy,
balanceador de carga ou gateway de API
ensaios contratuais, Diretriz ADR: Testes de contratos - Diretriz ADR:
Testes de contratos
testes de ponta a ponta, Diretrizes ADR: Testes de ponta a ponta -
Diretriz ADR: Testes de ponta a ponta
para, Dominar a API: Diretrizes ADR
testes de integração, Diretrizes ADR: Testes de integração
intercâmbios demodelos, Diretriz: Modelação de intercâmbios
OAuth2, diretriz ADR: Devo considerar a utilização do OAuth2?
Subvenções OAuth2, Diretrizes ADR: Escolher quais as subvenções
OAuth2 a apoiar
plataformas deopinião, Orientação ADR: Plataformas de opinião -
Diretriz ADR: Plataformas de opinião
seleção de gateways de API, Diretrizes ADR: Seleção de um gateway
de API
Selecionar umarede de serviços, Lista de verificação: Seleção de uma
Service Mesh - Lista de verificação: Seleção de uma Service Mesh
separar a libertação e a implantação, Diretriz ADR: Separar a liberação
da implantação com gestão de tráfego e sinalizadores de recursos
service mesh versus bibliotecas, Diretrizes: Deves adotar o Service
Mesh?
Extração de serviços de sessão, Estudo de caso: Extraindo a
funcionalidade das sessões para um serviço
estratégias de ensaio, ADR Guideline for Testing Strategies
ADRs (registos de decisões de arquitetura)
em estudo de caso de sistema de conferência, Attendees Evolution
ADR-AttendeesEvolution ADR
definido, Utilizar registos de decisões de arquitetura-Utilizarregistos
de decisões de arquitetura
para decisões irreversíveis, utilizando funções de aptidão
secções de, Utilizando registos de decisões de arquitetura
agregar serviços backend, Simplificar o consumo: Agregação/tradução de
serviços backend-Simplificaro consumo: Agregação/tradução de serviços
backend
alertas, associar a métricas, Métricas importantes para APIs
Ambassador Edge Stack, instalar, Instalar o Ambassador Edge Stack em
Kubernetes
sites de analistas, Radares, Quadrantes e Relatórios de tendências
Gateways API
adicionando ao estudo de caso do sistema de conferência, Estudo de
caso: Expondo o serviço de participantes aos consumidores, Estudo de
caso: Um olhar para trás na tua viagem-Estudo de caso: Um olhar
retrospetivo sobre a tua viagem
benefícios de, Porquê utilizar um API Gateway?-Monetizaas APIs:
Gestão de contas, faturação e pagamento
agregação/tradução de back-end, Simplifica o consumo:
Agregação/Tradução de serviços de backend-Simplifiqueo
consumo: Agregação/tradução de serviços de backend
gestão do ciclo de vida, Gerir APIs como produtos:
Gerenciamento do ciclo de vida da API - GerenciaAPIs como
produtos: Gestão do ciclo de vida da API
Acoplamento livre, Reduzir o Acoplamento: Adaptador/Facada
entre Frontends e Backends
monetização, Monetiza APIs: Gestão de contas, faturação e
pagamento
observabilidade, Compreender como as APIs estão a ser
consumidas: Observabilidade - Compreendecomo as APIs estão a
ser consumidas: Observabilidade
deteção/mitigação de ameaças, Proteger as APIs contra uso
excessivo e abusivo: Deteção e mitigação de ameaças - Protegeas
APIs do uso excessivo e do abuso: Deteção e mitigação de
ameaças
configurando mapeamentos, Configurando mapeamentos de caminhos
de URL para serviços de back-end - Configurandomapeamentos
usando roteamento baseado em host
definido, O que é um API Gateway?
local de implantação, Onde é implantado um API Gateway?
proxies de borda e controladores de entrada versus, 2015 em diante:
Gateways de API de segunda geração
gestão de falhas, Implementação de API Gateways: Compreender e
geriros riscos de mitigação de falhas
história de, A Modern History of API Gateways-2015Onward:
Gateways de API de segunda geração
armadilhas de implementação, armadilhas de implementação de
gateways de API comuns - armadilhas(gateways de API) a torto e
adireito
validação de entrada, injeção de cargaútil-injeção de carga útil
instalando, Instalando o Ambassador Edge Stack no Kubernetes
integração com tecnologias de ponta, Como é que um gateway de API
se integra com outras tecnologias na ponta?
objetivo de, Que funcionalidade oferece um API Gateway?
limitação da taxa, limitação da taxa e corte de carga
Proxiesreversos e balanceadores de carga versus, Um API Gateway é a
única solução?Proxy, balanceador de carga ou gateway de API
má configuração da segurança, má configuração da segurança -reforço
da diretiva de segurança
Seleção, Seleção de uma API Gateway-ADRGuideline: Seleção de um
gateway de API
service mesh as, Service Mesh as Gateway
tipos de, Taxonomia atual de API Gateway-Comparação detipos de
API Gateway
Chaves API
autenticação com, Autenticação de sistema para sistema
misturar tipos de autenticação, Porque não deves misturar chaves e
utilizadores
Padrão arquitetónico do bolo de camadasda API, Bolo de camadas da API
Gestão da API na migração para a Cloud, Papel da gestão da API - Papelda
gestão da API
Design API-First, O percurso da arquitetura, Papel da gestão de API
APIs (interfaces de programação de aplicações)
assíncrono, Comunicação assíncrona
em estudo de caso de sistema de conferência, Tipos de APIs no estudo
de caso de conferência
Lei de Conway, APIs, Lei de Conway e a tua organização-APIs, Lei de
Conway e a tua organização
definido, Uma breve introdução às APIsUmabreve introdução às APIs
conceção, Estudo de caso: Projetando a API do participante-Estudo de
caso: Projetando a API do participante
Diretrizes da API REST da Microsoft, Padrões e estrutura da API
REST
sistemas evolutivos com
padrões arquitectónicos, Architectural Patterns for Evolving
Systems with APIs-APILayer Cake
benefícios de, Por que usar APIs para evoluir um sistema?-Estudo
de caso: Estabelecendo limites de domínio do participante
pontos de alavancagem da mudança, Identificação dos pontos de
alavancagem da mudança num sistema
arquitecturas de estado final, Opções-Funções da Arquitetura de
Estado Final
funções de fitness, Utilizar funções de fitness-Utilizarfunções de
fitness
definição de objectivos, Determina os teus objectivos-
Determinaos teus objectivos
conceção de módulos, Decomposição de um sistema em módulos-
Decomposiçãode um sistema em módulos
pontos de dor e oportunidades, Identificar pontos de dor e
oportunidades - Quebrardependências: APIs altamente acopladas
gestão do processo, Gerir o processo evolutivo -entrega e
verificação contínuas
seams for extension, Criar APIs como "Seams" para extensão-
CriarAPIs como "Seams" para extensão
modelação, Da arquitetura em camadas à modelação de APIs
APIs multiformato, Especificações múltiplas-Desafiosdas
especificações combinadas
REST(ver REST)
testes(ver testar APIs)
controlo de versões
OAS e, Especificação e controlo de versões daOpenAPI-
Especificação e controlo de versões da OpenAPI
opções para, Versão da API-Versãoda API
versionamento semântico, Versionamento semântico
controladores de entrega de aplicações (ADCs), meados dos anos 2000:
Controladores de entrega de aplicações (ADCs)
interfaces de programação de aplicações(ver APIs)
decisões de lançamento a nível da aplicação, Application Decisions for
Effective Software Releases-ADRGuideline: Plataformas de opinião
aplicações(ver sistemas)
padrões arquitectónicos, Architectural Patterns for Evolving Systems with
APIs-APILayer Cake
registos de decisões de arquitetura(ver ADR)
Rollouts Argo, Estudo de caso: Executando Rollouts com Argo Rollouts-
Estudo de caso: Realizando Rollouts com Rollouts Argo
gestão de activos, imprópria, Gestão de activos imprópria
APIs assíncronas, Comunicação assíncrona
API do participante(ver estudo de caso do sistema de conferência)
autenticação
API do participante, autenticação, estudo de caso: Um olhar para trás
na tua viagem
definido, Autenticação
MFA (Multi-Fator Authentication), Autenticação
autenticaçãosistema a sistema, sistema a sistema
com base em tokens, Autenticação do utilizador final
comtokensAutenticação do utilizador finalcom tokens
autorização
Elevação deprivilégio, Elevação de privilégio
OAuth2
protocolo de abstração, terminologia e mecanismos das
subvenções OAuth2
Concessão decódigo deautorização, Concessão de código
deautorização-Estudo de caso: Acessando a API do participante
com a concessão do código de autorização
Concessão decredenciais de cliente, Concessão de credenciais de
cliente -Estudo de caso: Acesso à API de participante do sistema
CFP com concessão de credenciais de cliente
definido, OAuth2
Concessão de autorização de dispositivo, concessões OAuth2
adicionais
execução, Execução deautorização-Execução de autorização
diretrizes de subvenções, Diretrizes ADR: Escolher as
subvenções OAuth2 a apoiar
diretrizes, Diretrizes ADR: Devo considerar a utilização do
OAuth2?
Concessão implícita, concessões OAuth2 adicionais
JWT (JSON Web Token), JSON Web Tokens (JWT)-
Encodificaçãoe verificação de JSON Web Tokens
tokens de atualização, tokens de atualização
Concessão de credenciais de senha do proprietário do recurso,
concessões adicionais do OAuth2
funções em,Função de servidor de autorização OAuth2com
interações API
âmbitos, Âmbitos do OAuth2 -Estudo de caso: Aplicação de
âmbitos OAuth2 à API Attendee
OIDC (OpenID Connect), Apresentando o OIDC - Apresentandoo
OIDC
SAML 2.0 (Security Assertion Markup Language), SAML 2.0
Concessãode código de autorização (OAuth2), Concessão de código de
autorização -Estudo de caso: Aceder à API do participante com a concessão
do código de autorização
servidores de autorização, OAuth2
automatizar testes de ponta a ponta, Automatizar a validação de ponta a
ponta-Automatizara validação de ponta a ponta
melhores práticas, Aprender sobre as melhores práticas e casos de
utilização-Aprendersobre as melhores práticas e casos de utilização
faturação com gateways de API, Monetize APIs: Gestão de contas,
faturação e pagamento
azul-verde, azul-verde-azul-verde
BOLA (Broken Object Level Authorization), Aplicação de autorização
Autorização de nível de função quebrada, aplicação de autorização
C
Diagramas C4
componente, C4 Diagrama de Componentes
contentor, C4 Diagrama de contentor
contexto, C4 Diagrama de contexto
UML versus, Utilização de diagramas C4
canary releases, Canary Releases-CanaryReleases
estudo de caso(ver estudo de caso do sistema de conferência)
CDC (contratos orientados para o consumidor), Contratos orientados para o
consumidor
CDNs (redes de distribuição de conteúdo), início dos anos 2000 em diante:
Balanceadores de carga de software
deteção de alterações com o OAS, Deteção de alterações
pontos de alavancagem da mudança, Identificação dos pontos de
alavancagem da mudança num sistema
Cilium, Sidecarless: Implementações do kernel do sistema operativo (eBPF)
dependências circulares, negação de serviço
Concessão de credenciais de cliente (OAuth2), Concessão de credenciais de
cliente -Estudo de caso: Aceder à API de participante a partir do sistema
CFP com a concessão de credenciais de cliente
clientes, OAuth2
migração para a Cloud
Gestão de API em, Papel da gestão de API - Papelda gestão de API
API do Participante, Estudo de Caso: Movendo o Serviço de
Atendimento ao Cliente para a Cloud, Estudo de Caso: Replataforma
do Serviço de Atendimento para a Cloud -Estudo de
caso:Replataforma do Serviço de Atendimento ao Cliente para a
Cloud, Estudo de Caso: Um olhar retrospetivo sobre a tua jornada-
Estudo de caso: Um olhar para trás na tua jornada
estratégias para, Escolher uma estratégia de migração para aCloud-
Retire
refactor, Refactor/Re-architect-Refactor/Re-architect
rehost, Rehost-Rehost
replataforma, Replataforma
recompra, recompra
retain or revisit, reter ourevisitar - reterou revisitar
retirar, Retirar
gestão do tráfego em, Norte-Sul Versus Este-Oeste: Linhas de gestão
de tráfego pouco nítidas - Atravessandofronteiras: Encaminhamento
através de redes
coesão, Criar abstrações úteis: Aumenta a Coesão-CriandoAbstrações
Úteis: Aumentar a coesão
colecções
filtragem, Filtragem de colecções-Filtragem decolecções
paginação, Colecções e paginação
Common Vulnerability Scoring System (CVSS), Passo 5: Avalia os riscos
de ameaça
diagramas de componentes, Diagrama de Componentes C4
teste de componentes, Teste de componentes API -Estudo de caso: Teste de
componentes para verificar o comportamento
chamadas API simultâneas, orquestração, Simplifica o consumo:
Agregação/tradução de serviços de back-end
estudo de caso do sistema de conferência
Adição de gateway de API, Estudo de caso: Expondo o Serviço de
Participantes aos Consumidores, Estudo de Caso: Um olhar para trás
na tua viagem - Estudo de caso: Um olhar retrospetivo sobre a tua
viagem
Tipos deAPI em, Tipos de APIs no estudo de caso da conferência
Extração de serviços para participantes, Estudo de caso: Um passo
evolutivo -tráfego Leste-Oeste, Estudo de caso: Um olhar para trás na
tua viagem
evolução dos participantes ADR, Evolução dos participantes ADR-
Aevolução dos participantes ADR
Autenticação, Autenticação, Estudo de caso: Um olhar para trás na tua
viagem
autorização
Concessão decódigo deautorização, estudo de caso: Acessando a
API do participante com a concessão de código de autorização
Concessão de credenciais decliente, Estudo de caso: Acessando a
API de participante do sistema CFP com concessão de credenciais
de cliente
Funções OAuth2, função de servidor de autorização com
interações API
âmbitos, Estudo de caso: Aplicar âmbitos OAuth2 à
APIAttendee-Estudo de caso: Aplicar âmbitos de aplicação
OAuth2 à API Attendee
CDCs (contratos orientados para o consumidor), Estudo de caso:
Aplicação dos CDC
requisitos de alteração para, Razões para alterar o sistema de
conferências
migração para a Cloud, Estudo de caso: Movendo o serviço de
atendimento para a Cloud, Estudo de caso: Replataforma do serviço de
atendimento para a Cloud -Estudo de caso: Replataforma do serviço de
atendimento para a Cloud, Estudo de caso: Um olhar retrospetivo
sobre a tua jornada-Estudo de caso: Um olhar para trás na tua jornada
componentes de, Exemplo de execução: Estudo de caso do sistema de
conferência -Exemplo de execução: Estudo de caso do sistema de
conferência, Estudo de caso: Um olhar para trás na tua viagem
conceção de APIs, Estudo de caso: Projetando a API do participante-
Estudo de caso: Projetando a API do participante
Diretrizes da API REST da Microsoft, Normas e estrutura da API
REST
expondo APIs, Estudo de caso: Expondo o serviço de participante aos
consumidores, Estudo de caso: Evolução do sistema de conferência
usando um gateway de API - Configurandomapeamentos usando
roteamento baseado em host, Estudo de caso: Um olhar para trás na tua
jornada - Estudo de caso: Um olhar para trás na tua jornada
sinalização deelementos, Estudo de caso: Marcação de caraterísticas -
Estudo de caso: Sinalizaçãode caraterísticas, Estudo de caso: Um olhar
para trás na tua viagem
acoplamento flexível, Estudo de caso: Estabelecendo limites de
domínio dos participantes
APIs de modelação em, Da arquitetura em camadas à modelação de
APIs
conceção de módulos, Decomposição de um sistema em módulos
malha de serviço multicluster, Aumentar a malha de serviço com
políticas de rede, Estudo de caso: Um olhar para trás na tua jornada-
Estudo de caso: Um olhar para trás na tua jornada
lançamento com Argo Rollouts, Estudo de caso: Executando Rollouts
com Argo Rollouts-Estudo de caso: Realizando rollouts com o Argo
Rollouts
roteiro para, Roteiro para o estudo de caso da conferência-Roteiropara
o estudo de caso da conferência
Extração de serviços de sessão, Estudo de caso: Extraindo a
funcionalidade de sessões para um serviço - Estudo de caso:Extraindo
a funcionalidade de sessões para um serviço, Estudo de caso: Um olhar
para trás na tua jornada
testando APIs, Cenário do sistema de conferência para este capítulo
teste de componentes, Estudo de caso: Teste de componentes para
verificar o comportamento -Estudo de caso: Teste de
componentes para verificar o comportamento
teste de integração, Estudo de caso: Aplicando contêineres de
teste para verificar integrações-Estudo de caso: Aplicando
contêineres de teste para verificar integrações
modelação de ameaças, Estudo de caso: Aplicando o OWASP à API
do Participante -Estudo de caso: Aplicando o OWASP à API do
participante, Estudo de caso: Um olhar para trás na tua jornada-Estudo
de caso: Um olhar para trás na tua jornada
validação de entrada, Injeção de cargaútil-Injeção de carga útil
atribuição em massa, Atribuição emmassa-Atribuição em massa
Limitaçãode taxa, Limitação de taxa e redução de carga
padrões de tráfego em, Estudo de caso: Um passo evolutivo -tráfego
leste-oeste, Estudo de caso: Um olhar para trás na tua viagem
configurando mapeamentos, Configurando mapeamentos de caminhos de
URL para serviços de back-end - Configurandomapeamentos usando
roteamento baseado em host
Consul, Segmentação de redecom Consul-Segmentação de redecom Consul
contratos orientados para o consumidor (CDC), contratos orientados para o
consumidor
consumidores
conceção da API de participantes, Estudo de caso: Projetando a API do
participante-Estudo de caso: Projetando a API de participantes
definido, Testes de contrato
diagramas de contentores, Diagrama de contentores C4
contentores, Diagrama de contentores C4
redes de distribuição de conteúdos (CDN), início dos anos 2000+:
Balanceadores de carga de software
diagramas de contexto, C4 Diagrama de contexto
aprendizagem contínua, What's Next: Como continuar a aprender sobre a
arquitetura da API - Aprenderensinando
ensaios contratuais
benefícios de, Porque é que os ensaios por contrato são muitas vezes
preferíveis - Porque é queos ensaios por contrato são muitas vezes
preferíveis
implementação do contrato, Como é implementado um contrato-
APIarmazenamento e publicação de contratos
quadros para, Quadros de ensaio de contratos
diretrizes, Diretrizes ADR: Testes de contrato - Diretriz ADR: Testes
de contrato
terminologia, ensaios contratuais
contratos
contratos orientadospara o consumidor, contratos orientados para o
consumidor
criar, Como um contrato é implementado-Comoum contrato é
implementado
definido, Testes de contrato
visão geral da metodologia, Visão geral da metodologia dos contratos
contratos de produtor, Contratos deprodutor-Contratos de produtor
armazenamento e publicação, armazenamento e publicação de
contratos API
plano de controlo, O que é um API Gateway?
conversão entre especificações API, Especificações múltiplas-Desafiosdas
especificações combinadas
Lei de Conway, APIs, Lei de Conway e a tua organização-APIs, Lei de
Conway e a tua organização
CORS (partilha de pedidos entre origens), partilha de pedidos entre origens
(CORS)
CRDs (Custom Resource Definitions), Estudo de caso: Executando rollouts
com o Argo Rollouts
comunicação interfuncional com service mesh, Apoiar a comunicação
interfuncional entre línguas
objectivos multifuncionais para sistemas em evolução, Determina os teus
objectivos
CVSS (Common Vulnerability Scoring System), Passo 5: Avalia os riscos
de ameaça
diagramas de fluxo de dados (DFDs), Modelaçãode ameaças 101-
Modelação de ameaças101, Passo 3: Decompor o sistema
plano de dados, O que é um API Gateway?
tipos de decisão, Compreender os tipos de decisão
dissociação(ver separar a libertação e a implantação)
negação de serviço (DoS), negação de serviço -limitação de taxae corte de
carga
dependências, quebra, Quebra de dependências: APIs altamente acopladas
implantação
definido, separando a implantação e a liberação
separar da libertação, Separação entre a implantação e a libertação -
Diretriz ADR: Separação entre liberação e implantação com
gerenciamento de tráfego e sinalizadores de recursos
sinalizadores de caraterísticas, Estudo de caso: Sinalização de
caraterísticas-Estudo de caso: Sinalização de caraterísticas
diretrizes, Diretrizes ADR: Separar o lançamento da implantação
com a gestão do tráfego e as marcações de caraterísticas
gestão do ciclo de vida, Estudo de caso: Modelagem de liberações
no sistema de conferência - Mapeamento deestratégias de
liberação para o ciclo de vida
gestão de tráfego, Gestão de tráfego-Gestãode tráfego
avisos de depreciação, Manter ou Revisitar
conceção de APIs, Estudo de caso: Projetando a API do participante-Estudo
de caso: Projetando a API do participante
Diretrizes da API REST da Microsoft, Normas e estrutura da API
REST
deteção de alterações com o OAS, Deteção de alterações
Concessão de autorização de dispositivo (OAuth2), Concessões OAuth2
adicionais
DFDs (diagramas de fluxo de dados), Modelação de ameaças101-
Modelação de ameaças101, Passo 3: Decompor o sistema
diagnósticos, registo para auxiliar a depuração
fazer, aprender com, Aprender fazendo
DoS (negação de serviço), negação de serviço -limitação de taxae redução
de carga
Metodologia DREAD, Etapa 5: Avaliar os riscos de ameaça - Etapa5:
Avaliar os riscos de ameaça
Metodologia DREAD-D, Etapa 5: Avaliar os riscos de ameaça
tráfego este-oeste
em migração Cloud, Norte-Sul Versus Este-Oeste: Linhas de gestão de
tráfego pouco nítidas - Atravessandofronteiras: Encaminhamento entre
redes
definido, tráfego Este-Oeste
Implementação do servidor gRPC, Implementação de RPC com gRPC-
Implementação deRPC com gRPC
modelação de intercâmbios, Modelação de intercâmbios e escolha de
um formato API
diretrizes para, Diretrizes: Modelagem de intercâmbios
serviços de alto tráfego, Serviços de alto tráfego
Desempenho do HTTP/2, Benefícios de desempenho do HTTP/2
grandes cargas úteis, Grandes cargas úteis de intercâmbio -
Grandescargas úteis de intercâmbio
componentes vintage, Formatos Vintage
separação da gestão do tráfego norte-sul, Separação da gestão do
tráfego de entrada e da gestão do tráfego de serviço a serviço -
Separaçãoda gestão do tráfego de entrada e da gestão do tráfego de
serviço a serviço
malha de serviço
Benefícios de, Porquê utilizar um Service Mesh?- Separação
dagestão do tráfego de entrada e de serviço para serviço
Definido, O queé o Service Mesh?-O queé o Service Mesh?
localização da implantação, Onde é implantado um Service
Mesh?
gestão de falhas, Implantação de uma malha de serviço:
Compreender e gerir as falhas
história da, Evolução da Service Mesh -História e motivações
iniciais
padrões de implementação, padrões de implementação -
taxonomia de malha de serviço
armadilhas de implementação, Desafios comuns de
implementação do Service Mesh - demasiadascamadas de
Network+
integração com tecnologias de rede, Como é que um Service
Mesh se integra com outras tecnologias de rede+?
bibliotecas versus, o Service Mesh é a única solução?-Guia:
Deves adotar o Service Mesh?
segmentaçãode rede com o Consul, Segmentação de rede com
oConsul-Segmentação de rede com o Consul
observar com o Linkerd, Observar o tráfego com o Linkerd-
Observaro tráfego com o Linkerd
objetivo de, Qual é a funcionalidade de uma rede de serviços?
roteamento com o Istio, roteamento com o IstioRoteamentocom o
Istio
seleção, Seleção de uma rede de serviços - Lista de verificação:
Seleção de uma Service Mesh
Implementação da rede de serviços eBPF, Sidecarless: Implementações do
kernel do sistema operativo (eBPF)
proxies de borda, 2015 em diante: Gateways de API de segunda geração
Elevação de privilégio, Elevação de privilégio
arquitecturas de estado final, Opções-Funções da Arquitetura de Estado
Final
testes de ponta a ponta
automatizando, Automatizando a validação de ponta aponta-
Automatizando avalidação de ponta a ponta
definido, Pirâmide de teste
diretrizes, Diretrizes ADR: Testes de ponta a ponta - Diretriz ADR:
Testes de ponta a ponta
objetivo de, Teste de ponta a ponta
tipos de testes, Tipos de testes extremo-a-extremo-Tiposde testes
extremo-a-extremo
autenticação do utilizador final, Autenticação do utilizador final com
tokens-Autenticação do utilizador finalcom tokens
misturar com baseado em chaves, Porque não deves misturar chaves e
utilizadores
execução da autorização, Execução da Autorização-Execuçãoda
Autorização
tratamento de erros, diretrizes para, Tratamento de erros
ESB (enterprise service bus)
Gateway de API como, Gateway de API como um ESB
service mesh as, Service Mesh as ESB
avaliar os riscos, Passo 5: Avaliar os riscos de ameaças-Passo5: Avaliar os
riscos de ameaças
arquitetura evolutiva, The Architecture Journey
sistemas em evolução
com APIs
padrões arquitectónicos, Architectural Patterns for Evolving
Systems with APIs-APILayer Cake
benefícios de, Por que usar APIs para evoluir um sistema?-Estudo
de caso: Estabelecimento de limites de domínio do participante
pontos de alavancagem da mudança, Identificação de pontos de
alavancagem da mudança num sistema
arquitecturas de estado final, Opções-Funções da Arquitetura de
Estado Final
funções de fitness, Utilizar funções de fitness-Utilizarfunções de
fitness
definição de objectivos, Determina os teus objectivos-
Determinaos teus objectivos
conceção de módulos, Decomposição de um sistema em módulos-
Decomposiçãode um sistema em módulos
pontos de dor e oportunidades, Identificar pontos de dor e
oportunidades - Quebrardependências: APIs altamente acopladas
gestão do processo, Gerir o processo evolutivo -entrega e
verificação contínuas
seams for extension, Criar APIs como "Seams" para extensão-
CriarAPIs como "Seams" para extensão
para a migração para a Cloud
Gestão de API em, Papel da gestão de API - Papelda gestão de
API
API para participantes, Estudo de caso: Movendo o Serviço de
Atendimento ao Cliente para a Cloud, Estudo de Caso:
Replataforma do Serviço de Atendimento para a Cloud -Estudo
de caso:Replataforma do Serviço de Atendimento ao Cliente para
a Cloud, Estudo de Caso: Um olhar retrospetivo sobre a tua
jornada-Estudo de caso: Um olhar para trás na tua jornada
estratégias para, Escolher umaestratégia de migração para a Cloud
- Reforma
gestão do tráfego em, Norte-Sul Versus Este-Oeste: Linhas ténues
de gestão de tráfego - Atravessarfronteiras: Encaminhamento
através de redes
exemplos, OEA para, Exemplos e simulações-Exemplose simulações
exposição excessiva de dados, exposição excessiva de dados - exposição
excessivade dados
extração
Serviço aos participantes, Estudo de caso: Um passo evolutivo -tráfego
Leste-Oeste, Estudo de caso: Um olhar para trás na tua viagem
Serviço de sessão, Estudo de caso: Extraindo a funcionalidade de
sessões para um serviço - Estudo de caso:Extraindo a funcionalidade
das sessões para um serviço, Estudo de caso: Um olhar para trás na tua
jornada
padrão arquitetónico de fachada, Fachada e adaptador
políticas de encerramento de falhas, limitação de taxa e corte de carga
políticas de abertura a falhas, limitação de taxa e corte de carga
gestão de falhas
Gateways deAPI, Implantação de gateways de API: Compreender e
geriros riscos de mitigação de falhas
métricas a seguir, Métricas importantes paraAPIs-Métricas
importantespara APIs
pilares da observabilidade, Três pilares da observabilidade-Trêspilares
da observabilidade
ler os sinais, Ler os sinais-Leros sinais
service mesh, Implantação de um Service Mesh: Compreender e gerir
falhas
sinalização deelementos, Estudo de caso: Marcação de caraterísticas -
Estudo de caso: Sinalizaçãode caraterísticas, Estudo de caso: Um olhar para
trás na tua viagem
filtrarcolecções, Filtrar colecções-Filtrarcolecções
Gateways de API de primeira geração, Início da década de 2010: Gateways
de API de primeira geração
funções de fitness, Utilizar funções de fitness-Utilizarfunções de fitness
encaminhar proxies, Que funcionalidade oferece um gateway de API?
fogo amigo DoS (negação de serviço), negação de serviço
padrão do controlador frontal, Exemplo de execução: Estudo de caso do
sistema de conferência
full proxies, Qual é a funcionalidade de um Service Mesh?
objectivos funcionais para sistemas em evolução, Determina os teus
objectivos
funções, Funções
gateways(ver API gateways)
GDPR (Regulamento Geral sobre a Proteção de Dados), O risco de não
proteger APIs externas
objetivos para sistemas em evolução, Determina os teus objetivos-
Determinaos teus objetivos
caminho dourado(ver plataformas de opinião)
concessões (OAuth2)
protocolo de abstração para, Terminologia e Mecanismos de
Concessão OAuth2
Concessão decódigo deautorização, Concessão de código
deautorização-Estudo de caso: Acesso à API de participante com a
concessão de código de autorização
Concessão decredenciais de cliente, Concessão de credenciais de
cliente -Estudo de caso: Acesso à API de participante do sistema CFP
com concessão de credenciais de cliente
Concessão de autorização de dispositivo, concessões OAuth2
adicionais
diretrizes, Diretrizes ADR: Escolher quais as subvenções OAuth2 a
apoiar
Concessão implícita, concessões OAuth2 adicionais
tokens de atualização, tokens de atualização
Concessão de credenciais de senha do proprietário do recurso,
concessões adicionais do OAuth2
GraphQL, uma breve menção ao GraphQL - Umabreve menção ao
GraphQL
Gregory, Janet, Test Quadrant
gRPC, Introdução às APIs de chamada de procedimento remoto (RPC)
conversão de/para OpenAPI, Especificações múltiplas-Desafiosdas
especificações combinadas
bibliotecas, Bibliotecas de gRPC semproxy-Bibliotecas de gRPC sem
proxy
implementação de servidor, Implementação de RPC com gRPC-
Implementação deRPC com gRPC
grpc-gateway, Será que a Especificação Dourada existe?
balanceadores de carga de hardware, 1990s Onward: Balanceadores de
carga de hardware
propagação decabeçalhos, Propagação de cabeçalhos ao nível da aplicação
alta coesão, Reduzir o acoplamento: Adapta/Facade entre Frontends e
Backends, Criando Abstrações Úteis: Aumenta a Coesão-
CriandoAbstrações Úteis: Aumentando a coesão
serviços de elevado tráfego, Serviços de elevado tráfego
história
de gateways de API, A Modern History of API Gateways-
2015Onward: Gateways de API de segunda geração
de service mesh, Evolução do Service Mesh -História e motivações
iniciais
roteamento baseado em host, Configurando mapeamentos usando
roteamento baseado em host
HTTP Basic, autenticação do utilizador final com tokens
Lista de permissões do cabeçalho HTTP, reforço da diretiva de segurança
Desempenho do HTTP/2, Benefícios do desempenho do HTTP/2
HTTP/3, Benefícios de desempenho do HTTP/2, HTTP/3
I
Concessão implícita (OAuth2), Concessões OAuth2 adicionais
gestão inadequada deactivos, Gestão inadequada de activos
APIs em processo
em estudo de caso de sistema de conferência, Tipos de APIs no estudo
de caso de conferência
definido, Uma breve introdução às APIs
resposta a incidentes, resolução de incidentes e problemas
sites de notícias do sector, Manter-se atualizado com as notícias do sector-
Manter-seatualizado com as notícias do sector
divulgação de informações, Divulgação de informações-Gestão
inadequadade activos
recolha de informações na modelação de ameaças, Passo 2: Recolhe as
informações corretas
ocultação de informações, Reduzir o acoplamento: Adaptador/Facada entre
front-ends e back-ends, Estudo de caso: Estabelecendo limites de domínio
do participante
infraestrutura, padrões de tráfego e, API Infraestrutura e padrões de tráfego
controladores de ingresso, 2015 em diante: Gateways de API de segunda
geração
gestão do tráfego de entrada(ver API gateways; tráfego norte-sul)
validação de entrada com gateways de API, injeção de cargaútil-injeção de
carga útil
instalar gateways de API, Instalar o Ambassador Edge Stack em Kubernetes
teste de integração, teste de integração API
diretrizes, Diretrizes ADR: Teste de integração
servidores stub em, Usando servidores stub: Por que e como-
Usandoservidores stub: Por que e como
Biblioteca Testcontainers, Containerizando componentes de
teste:Testcontainers-Estudo de caso: Aplicando Testcontainers para
Verificar Integrações
intenções (Consul), Segmentação de rede comConsul-Network
Segmentation with Consul
decisões irreversíveis, utilizando funções de aptidão
Istio, roteamento com o IstioRoteamentocom o Istio
journaling, Registo para auxiliar a depuração
JWE (JSON Web Encryption), Codificação e verificação de JSON Web
Tokens
JWS (JSON Web Signature), Codificação e verificação de JSON Web
Tokens
JWT (JSON Web Token), JSON Web Tokens (JWT)-Encodificaçãoe
verificação de JSON Web Tokens
chaves, autenticação com, Autenticação sistema a sistema
Kubernetes, instalar o Ambassador Edge Stack, Instalar o Ambassador
Edge Stack em Kubernetes
grandes cargas úteis de câmbio, Grandes cargas úteis de câmbio-
Grandescargas úteis de câmbio
aprendizagem
continua, o que vem a seguir: Como continuar a aprender sobre
arquitetura API - Aprendeensinando
aprender fazendo, Aprender fazendo
por ensino, Aprender ensinando
pontos de alavancagem para a mudança, Identificar os pontos de
alavancagem da mudança num sistema
bibliotecas
implementação de service mesh, Bibliotecas-Bibliotecas
service mesh versus, Será que o Service Mesh é a única solução?-
Diretrizes: Deves adotar o Service Mesh?
gestão do ciclo de vida
Gateways de API, Gerir APIs como produtos: Gestão do ciclo de vida
da API - GereAPIs como produtos: Gerenciamento do ciclo de vida da
API
mapeamento das estratégias de lançamento, Mapeamento das
estratégias de lançamento para o ciclo de vida
etapas, Ciclo de vida da API
Linkerd, Observar o tráfego com o Linkerd-Observaro tráfego com o
Linkerd
balanceadoresde carga versus gateways de API e proxies reversos, Um
gateway de API é a única solução?Proxy, balanceador de carga ou gateway
de API
limitação de carga, limitação de taxa e limitação de carga
registos
definido, Três pilares da observabilidade
tipos de, Registo para auxiliar a depuração
tokens de longa duração, Codificação e verificação de JSON Web Tokens
loopback (gateways API), API Gateway Loopback
Acoplamento flexível, Reduzir o Acoplamento: Adapta/Facade entre
Frontends e Backends, Clarificando os limites do domínio: Promovendo o
Acoplamento Solto
questões de manutenção quando os sistemas evoluem, Questões de
atualização e manutenção
versões principais, Versionamento semântico
Mapeamentos, configurando, Configurando mapeamentos de caminhos de
URL para serviços de back-end - Configurandomapeamentos usando
roteamento baseado em host
atribuição em massa, Atribuição emmassa-Atribuição em massa
malha(ver malha de serviço)
rede mesh, O que é o Service Mesh?
métricas
definido, Três pilares da observabilidade
ler os sinais de, Ler os sinais-Leros sinais
que rastrear, Métricas importantes paraAPIs-Métricas importantespara
APIs
MFA (Multi-Fator Authentication), Autenticação
microsserviços, Microsserviços/Micro Gateways, Microsserviços-
Microsserviços
Diretrizes da API REST da Microsoft, Normas e estrutura da API REST -
Normas e estrutura da API REST
escolher normas API, Diretriz ADR: Escolher um padrão de API
tratamento de erros, Tratamento de erros
filtragem de colecções, Filtragem de colecções-Filtragem decolecções
nomeação, Padrões e estrutura da API REST
paginação, Colecções e paginação
Ferramenta de Modelação de Ameaças da Microsoft, Passo 4: Identificar as
Ameaças - Fazendo isto no teu STRIDE
migração(ver migração para a Cloud; sistemas em evolução)
versões secundárias, Versionamento semântico
má configuração da segurança, má configuração da segurança -reforço da
diretiva de segurança
mocking, OAS para, Exemplos e Mocking-Exemplose Mocking
APIs de modelação, Da arquitetura em camadas à modelação de APIs
modelação de intercâmbios, Modelação de intercâmbios e escolha de um
formato API
diretrizes para, Diretrizes: Modelagem de intercâmbios
serviços de alto tráfego, Serviços de alto tráfego
Desempenho do HTTP/2, Benefícios de desempenho do HTTP/2
grandes cargas úteis, Grandes cargas úteis de intercâmbio -
Grandescargas úteis de intercâmbio
componentes vintage, Formatos Vintage
módulos, decomposição de sistemas em, Decomposição de um sistema em
módulos-Decomposiçãode um sistema em módulos
monetização de APIs, Monetize APIs: Gestão de contas, faturação e
pagamento
monitorização na gestão de falhas, Detetar e assumir os problemas
arquitecturas monolíticas, Monólito-Monólito
Autenticaçãomulti-fator (MFA), Autenticação
malha de serviço multicluster, Aumentar a malha de serviço com políticas
de rede, Estudo de caso: Um olhar para trás na tua jornada-Estudo de caso:
Um olhar para trás na tua jornada
APIs multiformato, Especificações múltiplas-Desafiosdas especificações
combinadas
múltiplos gateways de API, Turtles (API Gateways) All the Way Down
Nomeação de APIs, padrões e estrutura de API REST
políticas de rede em arquitecturas de confiança zero, Augmenting Service
Mesh with Network Policies-AugmentingService Mesh with Network
Policies
segmentaçãode rede com o Consul, Segmentação de rede com oConsul-
Segmentação de rede com o Consul
tráfego norte-sul
Gateways API
benefícios de, Porquê utilizar um API Gateway?-Monetizaas
APIs: Gestão de contas, faturação e pagamento
configurando mapeamentos, Configurando mapeamentos de
caminhos de URL para serviços de back-end -
Configurandomapeamentos usando roteamento baseado em host
definido, O que é um API Gateway?
local de implantação, Onde é implantado um API Gateway?
proxies de borda e controladores de entrada versus, 2015 em
diante: Gateways de API de segunda geração
gestão de falhas, Implementação de API Gateways: Compreender
e geriros riscos de mitigação de falhas
história de, A Modern History of API Gateways-2015Onward:
Gateways de API de segunda geração
armadilhas de implementação, armadilhas de implementação de
gateways de API comuns - armadilhas(gateways de API) a torto e
adireito
instalando, Instalando o Ambassador Edge Stack no Kubernetes
integração com tecnologias de ponta, Como é que um API
Gateway se integra com outras tecnologias na ponta?
objetivo de, Que funcionalidade oferece um API Gateway?
Proxiesreversos e balanceadores de carga versus, Um API
Gateway é a única solução?Proxy, balanceador de carga ou
gateway de API
Seleção, Seleção de uma API Gateway-ADRGuideline: Seleção
de um gateway de API
tipos de, Taxonomia atual de API Gateway-Comparação detipos
de API Gateway
em migração Cloud, Norte-Sul Versus Este-Oeste: Linhas de gestão de
tráfego pouco nítidas - Atravessandofronteiras: Encaminhamento entre
redes
definido, Tráfego norte-sul
modelação de intercâmbios, Modelação de intercâmbios e escolha de
um formato API
diretrizes para, Diretrizes: Modelagem de intercâmbios
serviços de alto tráfego, Serviços de alto tráfego
Desempenho do HTTP/2, Benefícios de desempenho do HTTP/2
grandes cargas úteis, Grandes cargas úteis de intercâmbio -
Grandescargas úteis de intercâmbio
componentes vintage, Formatos Vintage
separação da gestão do tráfego este-oeste, Separação da gestão do
tráfego de entrada e da gestão do tráfego serviço-a-serviço -
Separaçãoda gestão do tráfego de entrada e da gestão do tráfego
serviço-a-serviço
OAS (Especificações OpenAPI)
para a deteção de alterações, Deteção de alterações
para geração de código, Geração de código
conversão de/para gRPC, Especificações múltiplas-Desafiosdas
especificações combinadas
para exemplos e simulações, Exemplos e simulações - Exemplose
simulações
explicado, Especificando APIs REST usando OpenAPI-
EspecificandoAPIs REST usando OpenAPI
para validação, Validação OpenAPI -Validação OpenAPI
versionamento e, Especificação e Versionamento daOpenAPI-
Especificação e Versionamento da OpenAPI
OAuth2
definido, OAuth2
execução, Execução deautorização-Execução de autorização
subvenções
protocolo de abstração para, Terminologia e Mecanismos de
Concessão OAuth2
Concessão decódigo deautorização, Concessão de código
deautorização-Estudo de caso: Acesso à API de participante com
a concessão de código de autorização
Concessão decredenciais de cliente, Concessão de credenciais de
cliente -Estudo de caso: Acesso à API de participante do sistema
CFP com concessão de credenciais de cliente
Concessão de autorização de dispositivo, concessões OAuth2
adicionais
diretrizes, Diretrizes ADR: Escolher quais as subvenções OAuth2
a apoiar
Concessão implícita, concessões OAuth2 adicionais
tokens de atualização, tokens de atualização
Concessão de credenciais de senha do proprietário do recurso,
concessões adicionais do OAuth2
diretrizes, Diretrizes ADR: Devo considerar a utilização do OAuth2?
JWT (JSON Web Token), JSON Web Tokens (JWT)-Encodificaçãoe
verificação de JSON Web Tokens
funções em,Função de servidor de autorização OAuth2com interações
API
âmbitos, Âmbitos do OAuth2 -Estudo de caso: Aplicação de âmbitos
OAuth2 à API Attendee
objectivos, identificar para modelação de ameaças, Passo 1: Identificar os
teus objectivos
observabilidade, Compreende como as APIs estão a ser consumidas:
Observabilidade - Compreendecomo as APIs estão a ser consumidas:
Observabilidade
em gestão de falhas, Detectando e assumindo os problemas
pilares da, Três pilares da observabilidade - Trêspilares da
observabilidade
de service mesh, Provide Transparent Observability-
ProvideTransparent Observability
com o Linkerd, Observar o tráfego com o Linkerd-Observaro
tráfego com o Linkerd
OIDC (Open ID Connect), Introduzir o OIDC-Introduziro OIDC
OPA (Open Policy Agent), segmentação de rede com o Consul
Especificações OpenAPI(ver OAS)
openapi-diff, Especificação e controlo de versões da OpenAPI
openapi2proto, Existe a Especificação Dourada?
Projeto OpenTelemetry, Três Pilares da Observabilidade
Implementação da rede de serviços do kernel do sistema operativo (eBPF),
Sidecarless: Implementações do kernel do sistema operativo (eBPF)
Zona de Operações (OZ), Entrar na Zona
plataformas deopinião, Considerando uma Plataforma de Opinião -Diretriz
RAD: Plataformas de opinião
orquestrar chamadas API simultâneas, Simplifica o consumo:
Agregação/tradução de serviços de back-end
design organizacional, APIs, Lei de Conway e a tua organização-APIs, Lei
de Conway e a tua organização
APIs fora de processo
em estudo de caso de sistema de conferência, Tipos de APIs no estudo
de caso de conferência
definido, Uma breve introdução às APIs
OWASP (Projeto de Segurança de Aplicações Web Abertas), Estudo de
caso: Aplicando o OWASP à API do Participante
Pact, estruturas de teste de contrato
paginação de colecções, Colecções e paginação
versões de patches, Versionamento semântico
caminho pavimentado(ver plataformas de opinião)
injeção de carga útil, Injeção de cargaútil-Injeção de carga útil
pagamento com gateways de API, Monetize APIs: Gestão de contas,
faturação e pagamento
problemas de desempenho na evolução dos sistemas, Problemas de
desempenho
testes de desempenho, Tipos de testes de ponta a ponta
segurança sem perímetro(ver arquitetura de confiança zero)
PKCE (Proof Key for Code Exchange), Concessão de código de
autorização (+ PKCE) -Concessão de código de autorização (+ PKCE)
malha baseada na plataforma, malha baseada na plataforma
plug-ins com gateways de API, API Gateway como um ESB
contratos de produtor, Contratos deprodutor-Contratos de produtor
produtores
conceção da API de participantes, Estudo de caso: Projetando a API do
participante-Estudo de caso: Projetando a API de participantes
definido, Testes de contrato
fornecedores(ver produtores)
servidores proxy, Qual é a funcionalidade de um API Gateway?
bibliotecas proxyless gRPC, bibliotecas Proxyless gRPC-Bibliotecas
ProxylessgRPC
Zona de acesso público (ZAP), entrar na zona
Zona Pública (ZP), Entrar na Zona
contratos de publicação, armazenamento e publicação de contratos API
limitação da taxa, limitação da taxa e redução da carga -limitação da taxa e
redução da carga
RBAC (Controlo de Acesso Baseado em Funções), Aplicação de
Autorização
MétricasRED (Rate, Error, Duration), Métricas importantes paraAPIs-
Métricas importantespara APIs
refactor estratégia de migração para Cloud, Refactor/Re-architect-
Refactor/Re-architect
tokens de atualização, tokens de atualização
estratégia de migração para a cloud da rehost, Rehost-Rehost
liberta
decisões ao nível da aplicação, Application Decisions for Effective
Software Releases-ADRGuideline: Plataformas de opinião
com Argo Rollouts, Estudo de caso: Executando Rollouts com Argo
Rollouts-Estudo de caso: Realização de rollouts com Rollouts Argo
definido, separando a implantação e a liberação
gestão de falhas
métricas para, Métricas importantes paraAPIs-Métricas
importantespara APIs
pilares da observabilidade, Três pilares da observabilidade-
Trêspilares da observabilidade
ler os sinais, Ler os sinais-Leros sinais
Separação da implantação, Separação da implantação e liberação -
Diretriz ADR: Separação da liberação da implantação com
gerenciamento de tráfego e sinalizadores de recursos
sinalizadores de caraterísticas, Estudo de caso: Sinalização de
caraterísticas-Estudo de caso: Sinalização de caraterísticas
diretrizes, Diretrizes ADR: Separar o lançamento da implantação
com a gestão do tráfego e as marcações de caraterísticas
gestão do ciclo de vida, Estudo de caso: Modelagem de liberações
no sistema de conferência - Mapeamento deestratégias de
liberação para o ciclo de vida
gestão de tráfego, Gestão de tráfego-Gestãode tráfego
estratégias
azul-verde, azul-verde-azul-verde
canary releases, Canary Releases-CanaryReleases
mapeamento para o ciclo de vida, Mapeamento das estratégias de
lançamento para o ciclo de vida
espelhamento de tráfego, Espelhamento de tráfego -Espelhamento
de tráfego
fiabilidade da rede de serviços, Fiabilidade-Fiabilidade
Chamadas de procedimento remoto(ver RPCs)
estratégia de migração para a Cloud da Replatform, Replatform
repúdio, Repúdio-Repúdio
recompra a estratégia de migração para Cloud, recompra
Concessão de credenciais de senha do proprietário do recurso (OAuth2),
Concessões adicionais de OAuth2
proprietários de recursos, OAuth2
servidores de recursos, OAuth2
recursos de informação, Manter-se atualizado com as notícias do sector -
Aprendersobre as melhores práticas e casos de utilização
caching de resposta, Caching de resposta
REST (REpresentational State Transfer)
definido, Introdução ao REST
exemplo de, Introdução ao REST e HTTP por Exemplo-Introduçãoao
REST e HTTP por Exemplo
Diretrizes da API REST da Microsoft, Normas e estrutura da API
REST -Normas e estrutura da API REST
escolher normas API, Diretriz ADR: Escolher um padrão de API
tratamento de erros, Tratamento de erros
filtragem de colecções, Filtragem de colecções-Filtragem
decolecções
nomeação, Padrões e estrutura da API REST
paginação, Colecções e paginação
OEA
para a deteção de alterações, Deteção de alterações
para geração de código, Geração de código
conversão de/para gRPC, Especificações múltiplas-Desafiosdas
especificações combinadas
para exemplos e simulações, Exemplos e simulações - Exemplose
simulações
explicado, Especificando APIs REST usando OpenAPI-
EspecificandoAPIs REST usando OpenAPI
para validação, Validação OpenAPI -Validação OpenAPI
Modelo de maturidade de Richardson, O modelo de maturidade de
Richardson-Omodelo dematuridadede Richardson
RPCs versus, Introdução às APIs de chamada de procedimento remoto
(RPC)
Zona de restrição (RZ), entrar na zona
manter ou rever a estratégia de migração para a Cloud, Manter ou Rever -
Manterou Rever
Retira a estratégia de migração para a Cloud, Retira
proxies inversos
Gateways de API e balanceadores de carga versus, Um gateway de
API é a única solução?Proxy, balanceador de carga ou gateway de API
definido, que funcionalidades oferece um API Gateway?
Modelo de maturidade de Richardson, O modelo de maturidade de
Richardson-Omodelo dematuridadede Richardson
avaliação de riscos, Etapa 5: Avaliar os riscos de ameaças-Passo5: Avaliar
os riscos de ameaças
mitigação de riscos, Mitigação de riscos
risco de violações de segurança, O risco de não proteger as APIs externas-
Orisco de não proteger as APIs externas
Controlo de Acesso Baseado em Funções (RBAC), Aplicação de
Autorização
controlo de encaminhamento com service mesh, Controlo de
encaminhamento, fiabilidade e gestão de tráfego com granularidade fina -
Encaminhamento transparentee normalização de nomes de serviços
Istio, Roteamento com Istio - Roteamentocom Istio
RPCs (Chamadas de procedimento remoto)
conversão de/para OpenAPI, Especificações múltiplas-Desafiosdas
especificações combinadas
definido, Introdução às APIs de chamada de procedimento remoto
(RPC)
Implementação do servidor gRPC, Implementação de RPC com gRPC-
Implementação deRPC com gRPC
REST versus, Introdução às APIs de chamada de procedimento remoto
(RPC)
SAML 2.0 (Security Assertion Markup Language), SAML 2.0
testes de cenário, Como um contrato é implementado, Tipos de testes de
ponta a ponta
esquemas, Porque é que os testes por contrato são muitas vezes preferíveis
âmbitos(OAuth2), Âmbitos OAuth2 -Estudo de caso: Aplicação de âmbitos
OAuth2 à API Attendee
gateways de API de segunda geração, 2015 em diante: Gateways de API de
segunda geração-2015em diante: Gateways de API de segunda geração
segurança
autenticação(ver autenticação)
autorização(ver autorização)
em testes extremo-a-extremo, Tipos de testes extremo-a-extremo
aplicação com service mesh, Enforce Security: Segurança de
transporte, autenticação e autorização
risco de violações, O risco de não proteger as APIs externas-Orisco de
não proteger as APIs externas
pontos únicos de falha, API Gateway como um ponto único de falha
modelação da ameaça(ver modelação da ameaça)
arquitetura de confiança zero
princípios de, Não Confies em Ninguém e Verifica -Não Confies
emNinguém e Verifica
service mesh in, Papel do service mesh em arquitecturas de
confiança zero - complementando oservice mesh com políticas de
rede
arquitetura zonal, Entrar na zona-Entrarna zona
reforço da diretiva de segurança, reforço da diretiva de segurança
má configuração da segurança, má configuração da segurança -reforço da
diretiva de segurança
seleção
Gateways de API, Seleção de um Gateway de API -Diretrizes ADR:
Seleção de um gateway de API
service mesh, Seleção de uma Service Mesh - Lista de verificação:
Seleção de uma Service Mesh
versionamento semântico, Versionamento semântico
Separação entre a libertação e a implantação, Separação entre a implantação
e a libertação -Diretriz ADR: Separação entre liberação e implantação com
gerenciamento de tráfego e sinalizadores de recursos
sinalizadores de caraterísticas, Estudo de caso: Sinalização de
caraterísticas-Estudo de caso: Sinalização de caraterísticas
diretrizes, Diretrizes ADR: Separar o lançamento da implantação com
a gestão do tráfego e as marcações de caraterísticas
gestão do ciclo de vida, Estudo de caso: Modelagem de liberações no
sistema de conferência - Mapeamento deestratégias de liberação para o
ciclo de vida
gestão de tráfego, Gestão de tráfego-Gestãode tráfego
malha de serviço
como API gateway, Service Mesh Gateways, Service Mesh como
Gateway
benefícios de, Porquê utilizar um Service Mesh?- Separação dagestão
do tráfego de entrada e de serviço para serviço
comunicação interfuncional, Apoiar a comunicação interfuncional
entre idiomas
observabilidade, Fornecer Observabilidade Transparente -
ForneceObservabilidade Transparente
fiabilidade, fiabilidade - fiabilidade
controlo de encaminhamento, controlo fino do encaminhamento,
fiabilidade e gestão do tráfego -normalização transparente do
encaminhamento e do nome do serviço
aplicação da segurança, Aplicar a segurança: Segurança de
transporte, autenticação e autorização
Separação da gestão do tráfego de entrada e de serviço a serviço,
Separação da gestão do tráfego de entrada e de serviço a serviço -
Separaçãoda gestão do tráfego de entrada e de serviço a serviço
policiamento de tráfego, policiamento de tráfego
modelação do tráfego, Modelação do tráfego
Definido, O queé o Service Mesh?-O queé o Service Mesh?
localização da implantação, Onde é implantado um Service Mesh?
gestão de falhas, Implantação de uma malha de serviço: Compreender
e gerir as falhas
história da, Evolução da Service Mesh -História e motivações iniciais
padrões de implementação, Implementation Patterns-ServiceMesh
Taxonomy
comparação de, Service Mesh Taxonomy
eBPF, sem carro lateral: Implementações do kernel do sistema
operativo (eBPF)
bibliotecas, Bibliotecas-Bibliotecas
bibliotecas proxyless gRPC, Bibliotecas proxyless gRPC-
Bibliotecas proxylessgRPC
proxies sidecar, Sidecars-Sidecars
armadilhas de implementação, Desafios comuns de implementação do
Service Mesh - demasiadascamadas de Network+
integração com tecnologias de rede, Como é que um Service Mesh se
integra com outras tecnologias de rede+?
bibliotecas versus, o Service Mesh é a única solução?-Guia: Deves
adotar o Service Mesh?
segmentaçãode rede com o Consul, Segmentação de rede com
oConsul-Segmentação de rede com o Consul
observar com o Linkerd, Observar o tráfego com o Linkerd-Observaro
tráfego com o Linkerd
baseado na plataforma, Malha baseada na plataforma
objetivo de, Qual é a funcionalidade de uma rede de serviços?
roteamento com o Istio, roteamento com o IstioRoteamentocom o Istio
seleção, Seleção de uma rede de serviços - Lista de verificação:
Seleção de uma Service Mesh
em arquitecturas de confiança zero, Papel do Service Mesh em
arquitecturas de confiança zero - complementando oService Mesh com
políticas de rede
normalização do nome do serviço, Encaminhamento transparente e
normalização do nome do serviço
testes de serviço, pirâmide de testes
arquitetura orientada para os serviços (SOA), arquitetura orientada para os
serviços (SOA)
gestão do tráfego serviço a serviço(ver tráfego este-oeste; service mesh)
Serviço de sessão, extração, Estudo de caso: Extraindo a funcionalidade de
sessões para um serviço-Estudo de caso:Extraindo a funcionalidade de
sessões para um serviço, Estudo de caso: Um olhar para trás na tua jornada
tokens de curta duração, Codificação e verificação de JSON Web Tokens
sidecar proxies, O que é o Service Mesh?
implementação do service mesh, Sidecars-Sidecars
Aplicações de página única (SPAs), concessão de código de autorização
pontos únicos de falha, API Gateway como um ponto único de falha
SOA (arquitetura orientada para os serviços), Arquitetura orientada para os
serviços (SOA)
software(ver sistemas)
balanceadores de carga de software, do início dos anos 2000 em diante:
Balanceadores de carga de software - Início dosanos 2000 em diante:
Balanceadores de carga de software
SPAs (Single Page Applications), Concessão de código de autorização
spoofing, Spoofing
Contratos da Spring Cloud, estruturas de teste de contratos
armazenamento de contratos, armazenamento e publicação de contratos API
padrão arquitetónico da figueira-da-índia estranguladora,Figueira-da-índia-
estranguladora
Metodologia STRIDE
DoS (negação de serviço), negação de serviço -limitação de taxae
redução de carga
elementos de, Passo 4: Identificar as ameaças - Tomar isto em teu
STRIDE-Passo4: Identificar as ameaças - Tomar isto em teu STRIDE
Elevação deprivilégio, Elevação de privilégio
divulgação de informações, Divulgação de informações-Gestão
inadequadade activos
repúdio, Repúdio-Repúdio
má configuração da segurança, má configuração da segurança -reforço
da diretiva de segurança
spoofing, Spoofing
adulteração,adulteração-atribuição de massa
servidores stub
definido, porque é que os ensaios por contrato são muitas vezes
preferíveis
em testes de integração, Usando Stub Servers: Por que e como-
Usandoservidores Stub: Por que e como
autenticação de sistema para sistema, autenticação de sistema para sistema
sistemas, em evolução
com APIs
padrões arquitectónicos, Architectural Patterns for Evolving
Systems with APIs-APILayer Cake
benefícios de, Por que usar APIs para evoluir um sistema?-Estudo
de caso: Estabelecendo limites de domínio do participante
pontos de alavancagem da mudança, Identificação dos pontos de
alavancagem da mudança num sistema
arquitecturas de estado final, Opções-Funções da Arquitetura de
Estado Final
funções de fitness, Utilizar funções de fitness-Utilizarfunções de
fitness
definição de objectivos, Determina os teus objectivos-
Determinaos teus objectivos
conceção de módulos, Decomposição de um sistema em módulos-
Decomposiçãode um sistema em módulos
pontos de dor e oportunidades, Identificar pontos de dor e
oportunidades - Quebrardependências: APIs altamente acopladas
gestão do processo, Gerir o processo evolutivo -entrega e
verificação contínuas
seams for extension, Criar APIs como "Seams" para extensão-
CriarAPIs como "Seams" para extensão
para a migração para a Cloud
Gestão de API em, Papel da gestão de API - Papelda gestão de
API
API para participantes, Estudo de caso: Movendo o Serviço de
Atendimento ao Cliente para a Cloud, Estudo de Caso:
Replataforma do Serviço de Atendimento para a Cloud -Estudo
de caso:Replataforma do Serviço de Atendimento ao Cliente para
a Cloud, Estudo de Caso: Um olhar retrospetivo sobre a tua
jornada-Estudo de caso: Um olhar para trás na tua jornada
estratégias para, Escolher umaestratégia de migração para a Cloud
- Reforma
gestão do tráfego em, Norte-Sul Versus Este-Oeste: Linhas ténues
de gestão de tráfego - Atravessarfronteiras: Encaminhamento
através de redes
adulteração,adulteração-atribuição de massa
ensinar, aprender através de, Aprender através do ensino
estratégia da pirâmide de teste, Pirâmide deteste-Pirâmide de teste
estratégia do quadrante de teste, Quadrante de teste -Quadrante de teste
Biblioteca Testcontainers, Containerização de componentes de teste:
Testcontainers -Estudo de caso: Aplicando Testcontainers para verificar
integrações
testar APIs
teste de componentes, Teste de componentes API -Estudo de caso:
Teste de componentes para verificar o comportamento
ensaios contratuais
benefícios de, Porque é que os ensaios por contrato são muitas
vezes preferíveis - Porque é queos ensaios por contrato são muitas
vezes preferíveis
implementação do contrato, Como é implementado um contrato-
APIarmazenamento e publicação de contratos
quadros para, Quadros de ensaio de contratos
diretrizes, Diretrizes ADR: Testes de contrato - Diretriz ADR:
Testes de contrato
terminologia, ensaios contratuais
testes de ponta a ponta
automatizando, Automatizando a validação de ponta aponta-
Automatizando avalidação de ponta a ponta
definido, Pirâmide de teste
diretrizes, Diretrizes ADR: Testes de ponta a ponta - Diretriz
ADR: Testes de ponta a ponta
objetivo de, Teste de ponta a ponta
tipos de testes, Tipos de testes extremo-a-extremo-Tiposde testes
extremo-a-extremo
importância de, Testes de APIs
teste de integração, Teste de Integração API
diretrizes, Diretrizes ADR: Teste de integração
servidores stub em, Usando servidores stub: Por que e como-
Usandoservidores stub: Por que e como
Biblioteca Testcontainers, Containerizando componentes de
teste:Testcontainers-Estudo de caso: Aplicando Testcontainers
para Verificar Integrações
testes de cenário, Como um contrato é implementado, Tipos de testes
de ponta a ponta
testes de serviço, pirâmide de testes
estratégias
diretrizes, ADR Guideline for Testing Strategies
importância de, Estratégias de ensaio
pirâmide de teste, Pirâmide deteste-Pirâmide de teste
quadrante de ensaio, Quadrante de ensaio -Quadrante de ensaio
Testes de IU, Pirâmide de testes
testes unitários, pirâmide de testes
Radar de tecnologia da Thoughtworks, separando implantação e lançamento
deteção/mitigação de ameaças, Protege as APIs contra o uso excessivo e
abusivo: Deteção e mitigação de ameaças - Protegeas APIs contra uso
excessivo e abusivo: Deteção e mitigação de ameaças
modelação de ameaças
API do Attendee, Estudo de caso: Aplicando o OWASP à API de
participantes -Estudo de caso: Aplicando o OWASP à API
departicipantes, Estudo de caso: Um olhar para trás na tua jornada -
Estudo de caso: Um olhar para trás na tua jornada
definido, Modelação de Ameaças 101
DFDs (diagramas de fluxo de dados), Modelação de ameaças101-
Modelação de ameaças101, Passo 3: Decompor o sistema
avaliar os riscos, Passo 5: Avaliar os riscos de ameaças-Passo5:
Avaliar os riscos de ameaças
recolha de informações, Passo 2: Recolhe as informações corretas
identificar objectivos, Passo 1: Identificar os teus objectivos
passos em, Como fazer o modelo de ameaça
Metodologia STRIDE
DoS (negação de serviço), negação de serviço -limitação de taxae
redução de carga
elementos de, Passo 4: Identificar as ameaças - Tomar isto no teu
STRIDE-Passo4: Identificar as ameaças - Tomar isto no teu
STRIDE
Elevação de privilégio, Elevação de privilégio
divulgação de informações, Divulgação de informações-Gestão
inadequadade activos
repúdio, Repúdio-Repúdio
má configuração da segurança, má configuração da segurança -
reforço da diretiva de segurança
spoofing, Spoofing
adulteração,adulteração-atribuição de massa
pensar como um atacante, Pensar como um atacante
validação, Passo 6: Validação
acoplamento estreito, quebra de dependências: APIs altamente acopladas
Terminação TLS, terminação TLS
autenticação baseada em token, Autenticação do utilizador final comtokens-
Autenticação do utilizador finalcom tokens
misturar com baseado em chaves, Porque não deves misturar chaves e
utilizadores
traços, três pilares da observabilidade
gateways API empresariais tradicionais, Gateways empresariais tradicionais
gestão do tráfego
Gateways API
benefícios de, Porquê utilizar um API Gateway?-Monetizaas
APIs: Gestão de contas, faturação e pagamento
configurando mapeamentos, Configurando mapeamentos de
caminhos de URL para serviços de back-end -
Configurandomapeamentos usando roteamento baseado em host
definido, O que é um API Gateway?
local de implantação, Onde é implantado um API Gateway?
proxies de borda e controladores de entrada versus, 2015 em
diante: Gateways de API de segunda geração
gestão de falhas, Implementação de API Gateways: Compreender
e geriros riscos de mitigação de falhas
história de, A Modern History of API Gateways-2015Onward:
Gateways de API de segunda geração
armadilhas de implementação, armadilhas de implementação de
gateways de API comuns - armadilhas(gateways de API) a torto e
adireito
instalando, Instalando o Ambassador Edge Stack no Kubernetes
integração com tecnologias de ponta, Como é que um gateway de
API se integra com outras tecnologias na ponta?
objetivo de, Que funcionalidade oferece um API Gateway?
Proxiesreversos e balanceadores de carga versus, Um API
Gateway é a única solução?Proxy, balanceador de carga ou
gateway de API
Seleção, Seleção de uma API Gateway-ADRGuideline: Seleção
de um gateway de API
tipos de, Taxonomia atual de API Gateway-Comparação detipos
de API Gateway
em migração Cloud, Norte-Sul Versus Este-Oeste: Linhas de gestão de
tráfego pouco nítidas - Atravessandofronteiras: Encaminhamento entre
redes
definido, infraestrutura API e padrões de tráfego
separar a liberação e a implantação, Gestão dotráfego-Gestão do
tráfego
malha de serviço
Benefícios de, Porquê utilizar um Service Mesh?- Separação
dagestão do tráfego de entrada e de serviço para serviço
Definido, O queé o Service Mesh?-O queé o Service Mesh?
localização da implantação, Onde é implantado um Service
Mesh?
gestão de falhas, Implantação de uma malha de serviço:
Compreender e gerir as falhas
história da, Evolução da Service Mesh -História e motivações
iniciais
padrões de implementação, padrões de implementação -
taxonomia de malha de serviço
armadilhas de implementação, Desafios comuns de
implementação do Service Mesh - demasiadascamadas de
Network+
integração com tecnologias de rede, Como é que um Service
Mesh se integra com outras tecnologias de rede+?
bibliotecas versus, o Service Mesh é a única solução?-Guia:
Deves adotar o Service Mesh?
segmentaçãode rede com o Consul, Segmentação de rede com
oConsul-Segmentação de rede com o Consul
observar com o Linkerd, Observar o tráfego com o Linkerd-
Observaro tráfego com o Linkerd
objetivo de, Qual é a funcionalidade de uma rede de serviços?
roteamento com o Istio, roteamento com o IstioRoteamentocom o
Istio
seleção, Seleção de uma rede de serviços - Lista de verificação:
Seleção de uma Service Mesh
espelhamento de tráfego, espelhamento de tráfego -espelhamento de tráfego
padrões de tráfego
Infraestrutura daAPI e, Infraestrutura da API e padrões de tráfego
em estudo de caso de sistema de conferência, Estudo de caso: Um
passo evolutivo -tráfego Leste-Oeste, Estudo de caso: Um olhar para
trás na tua viagem
modelação de intercâmbios, Modelação de intercâmbios e escolha de
um formato API
diretrizes para, Diretrizes: Modelagem de intercâmbios
serviços de alto tráfego, Serviços de alto tráfego
Desempenho do HTTP/2, Benefícios de desempenho do HTTP/2
grandes cargas úteis, Grandes cargas úteis de intercâmbio -
Grandescargas úteis de intercâmbio
componentes vintage, Formatos Vintage
objetivo de, Da arquitetura em camadas à modelação de APIs
policiamento de tráfego, policiamento de tráfego
modelação do tráfego, Modelação do tráfego
tradução de serviços backend, Simplificar o consumo: Agregação/tradução
de serviços backend-Simplificaro consumo: Agregação/tradução de
serviços backend
Decisões de tipo 1, Compreender os tipos de decisão
Decisões de tipo 2, Compreender os tipos de decisão
Testes de IU, Pirâmide de testes
UML (Unified Modeling Language), Utilização de diagramas C4
testes unitários, pirâmide de testes
problemas de atualização quando os sistemas evoluem, Problemas de
atualização e manutenção
casos de utilização, Aprender sobre as melhores práticas e casos de
utilização - Aprendersobre as melhores práticas e casos de utilização
validação
modelação de ameaças, Passo 6: Validação
com OAS, Validação OpenAPI -Validação OpenAPI
APIs de controlo de versões
OAS e, Especificação e controlo de versões daOpenAPI-Especificação
e controlo de versões da OpenAPI
opções para, Versão da API-Versãoda API
versionamento semântico, Versionamento semântico
componentes vintage, Formatos vintage
WAFs (firewalls de aplicações Web), início dos anos 2000 em diante:
Balanceadores de carga de software
arquitetura de confiança zero
princípios de, Não Confies em Ninguém e Verifica -Não Confies
emNinguém e Verifica
service mesh in, Papel do service mesh em arquitecturas de confiança
zero - complementando oservice mesh com políticas de rede
arquitetura zonal, Entrar na zona-Entrarna zona
Sobre os autores
James Gough é um engenheiro renomado da Morgan Stanley que trabalha
com arquitetura de API e programas de API. Ele é um Java Champion que
participou do Java Community Process Executive Committee em nome da
London Java Community e contribuiu para o OpenJDK. James também é
coautor de Optimizing Java e gosta de falar sobre arquitetura e Java de
baixo nível.
Daniel Bryant é o diretor de relações com programadores na Ambassador
Labs. Quando se trata de funções de trabalho, subscreve a filosofia
Pokémon de "tem de os apanhar a todos", e em vidas anteriores, Daniel
trabalhou como académico, programador, arquiteto, engenheiro de
plataformas, consultor e CTO. A sua experiência técnica centra-se em
ferramentas DevOps, plataformas Cloud/container e implementações de
microsserviços. Daniel é um Java Champion e contribui para vários
projectos de código aberto. Também escreve para InfoQ, O'Reilly e The
New Stack, e apresenta-se regularmente em conferências internacionais
como KubeCon, QCon e Devoxx. No seu imenso tempo livre, gosta de
correr, ler e viajar.
Matthew Auburn trabalhou para a Morgan Stanley numa variedade de
sistemas financeiros. Antes de trabalhar na Morgan Stanley, criou uma
variedade de aplicações móveis e da Web. O mestrado de Matthew centrou-
se principalmente na segurança, o que o levou a trabalhar no espaço de
segurança para a criação de APIs.
Colofão
O animal na capa do Mastering API Architecture é um lagarto cingido de
tatu(Ouroborus cataphractus), anteriormente no género Cordylus.
Os lagartos cingidos vivem no deserto da costa ocidental da África do Sul.
A sua aparência é muitas vezes comparada à de um dragão em miniatura:
escamas castanhas claras ou escuras e ventre amarelo com padrões pretos.
Quanto ao tamanho, têm tipicamente entre 7,5 e 9 centímetros de
comprimento da abertura do focinho (que não inclui a cauda).
Vivem em grupos e estão em atividade durante o dia, embora a maior parte
do seu tempo ativo seja passado tomando banho de sol. A sua dieta consiste
principalmente em pequenos insectos (sobretudo térmitas) e entram em
brumas (hibernação parcial) durante o inverno. Ao contrário da maioria dos
lagartos, que põem ovos, os lagartos cingidos de tatu dão à luz filhotes
vivos, um ou dois de cada vez, cerca de uma vez por ano. As fêmeas
também podem alimentar os filhotes, outro comportamento incomum para
os lagartos.
O seu mecanismo de defesa contra os predadores consiste em enrolar-se
numa bola e segurar a cauda com a boca. Isto faz com que se pareçam com
o mítico ouroboros, que é um símbolo de totalidade ou infinito. Este
comportamento único é a razão do seu nome, uma vez que os tatus
mamíferos também se enrolam numa bola.
O estado de conservação do lagarto cingido do tatu é "quase ameaçado".
Muitos dos animais das capas de O'Reilly estão em perigo de extinção;
todos eles são importantes para o mundo.
A ilustração da capa é da autoria de Karen Montgomery, baseada numa
gravura a preto e branco do Museu de História Natural. Os tipos de letra da
capa são Gilroy Semibold e Guardian Sans. O tipo de letra do texto é Adobe
Minion Pro; o tipo de letra do cabeçalho é Adobe Myriad Condensed; e o
tipo de letra do código é Ubuntu Mono de Dalton Maag.