Especificação AsyncAPI 2.0

Introdução

AsyncAPI é uma iniciativa open source que tem o objetivo de descrever e documentar APIs orientadas a mensagens em um formato legível. A especificação AsyncAPI é agnóstica de protocolo, ou seja, pode ser utilizada com qualquer protocolo, como por exemplo, AMQP, MQTT, SQS, WebSockets, Kafka, JMS, STOMP, HTTP, etc.

O objetivo do AsyncAPI é tornar o trabalho com arquitetura orientada a mensagens tão simples quanto trabalhar com APIs REST. É importante ressaltar que a especificação não assume nenhum tipo de arquitetura ou padrão de software, ao que amplia a sua gama de utilização, assim como descrito em sua especificação: “…parte deste conteúdo foi retirado do excelente trabalho realizado pelo pessoal da Iniciativa OpenAPI. Principalmente porque é um ótimo trabalho e queremos manter o máximo de compatibilidade possível com a Especificação OpenAPI”.

Conceitos importantes

Mensageria

Consiste da utilização de mensagens para estabelecer uma comunicação entre aplicações, ou seja, é um sistema que tem o objetivo de realizar a integração entre serviços através de mensagens. Com ele, você envia a mensagem e não espera por uma resposta, pois sabe que o destinatário a recebeu.

É importante ressaltar que a mensageria é uma abordagem utilizada para comunicações assíncronas entre aplicações, o que permite um maior desacoplamento entre sistemas.

Filas e Pilhas

Antes de definir os modelos de mensageria, vamos relembrar os conceitos de FIFO e LIFO.

FIFO – First In, First Out,  ou “Primeiro a entrar, Primeiro a sair”, é o conceito aplicado para a fila. Nele, o primeiro elemento a entrar é o primeiro elemento a sair. Um exemplo simples disso é a fila de um banco, onde a primeira pessoa a chegar será a primeira a ser atendida.

LIFO – Last In, First Out, ou “Último a entrar, Primeiro a sair”, é o conceito aplicado para a pilha. Nele, o último elemento a entrar será o primeiro a sair. Um exemplo interessante é o do restaurante, quando o garçom recolhe os pratos, geralmente os empilha, um sobre o outro. O primeiro prato a ser lavado será o que está no topo, que é o que foi empilhado por último.

Esses são dois conceitos de estrutura de dados que são aplicados em mensageria, uma vez que ambos possuem apenas um consumer, assim como o modelo ponto a ponto.

Modelo ponto a ponto

O modelo ponto a ponto trata da entrega da mensagem para um único consumidor, ou seja, ela será processada apenas uma vez e por um único consumidor. As mensagens ficam na fila até serem processadas e excluídas.

Imagem 1: Modelo ponto a ponto.

  • Permite o envio de mensagem de forma síncrona e assíncrona.
  • Utiliza como canal (channel) de comunicação a fila (Queue).
  • A mensagem enviada a Queue será recebida por somente um Receiver/Consumer.
  • Modelo Publish / SubscribeO modelo pub/sub permite que um aplicativo envie mensagens para vários consumidores. Neste modelo, um componente publica uma mensagem em uma fila, normalmente chamada de tópico, e outro componente consome essa mensagem. Nele, as mensagens não são direcionadas para determinados consumidores, então para ler é necessário se inscrever no tópico. Assim, permite que múltiplos consumidores se inscrevam e recebam a mesma mensagem.Neste modelo, é importante ressaltar que podemos ter a cardinalidade 1 -> N, onde temos um publisher que envia a mensagem para o tópico e vários subscribers consomem a mensagem. Porém, também existem cenários onde teremos cardinalidade N -> N, onde vários sistemas publicam a mensagem, em um mesmo tópico, e outros sistemas a consomem. Para exemplificar este cenário, vamos pensar em um fluxo de frete, no qual temos várias etapas e sistemas envolvidos (estoque, faturamento, despacho, entrega, etc.). Nesse contexto, cada um dos sistemas poderia ser um publisher de um mesmo tópico, informando quando um determinado pedido iniciou ou terminou uma etapa do processo.

Imagem 2: Modelo pub/sub.

  • Publisher é o responsável por publicar as mensagens em um broker;
  • Broker é um intermediário entre o Publisher e o Consumer;
  • Tópico é o recurso nomeado para o qual as mensagens são enviadas;
  • Subscriber é quem se inscreve para receber e consumir as mensagens de um determinado tópico.

AsyncAPI

Teve o seu início como um projeto paralelo na Hitch (API Changelog), onde os desenvolvedores identificaram a falta de ferramentas para documentar os serviços orientados a mensagem, uma vez que um conjunto de ferramentas não supria as necessidades da mesma forma como atendiam as APIs REST. A partir dessa necessidade, eles começaram a trabalhar em uma solução para padronizar a documentação de APIs orientadas a mensagem.

O objetivo do projeto era o de criar uma estrutura para unificar diversos formatos, protocolos e especificações. Assim, permitiria uma comunicação padronizada para os sistemas orientados a mensagens. O projeto ganhou ainda mais força com a liberação da versão 2.0, que trouxe muitas melhorias realizadas pela comunidade e empresas parceiras (Salesforce, SAP, Slack, Solace, Tibco, MuleSoft, IQVIA Technologies), que fornecem apoio financeiro ou delegam funcionários para apoiar a evolução da A2S.

A especificação AsyncAPI é um projeto utilizado para documentar e descrever APIs orientadas a mensagens, sendo agnóstica de protocolo, sem topologia, arquitetura ou padrão de software. Ela permite utilizarmos APIs que funcionem em qualquer um dos protocolos já citados.

AsyncAPI (A2S) vs OpenAPI (OAS)

Ambas as soluções geram documentação, porém é importante entender que são duas opções extremamente divergentes. Isto porque, a OAS gera documentação de APIs REST e A2S gera documentação para APIs orientadas às mensagens. Então, por mais que os nomes soem semelhantes, as suas aplicações são diferentes, usadas para documentar aplicações distintas. Dito isso, devemos mudar o “vs” e considerar “A2S e OAS”, pois como é dito na página da própria especificação:

Parte deste conteúdo foi retirado do excelente trabalho realizado pelo pessoal da Iniciativa OpenAPI . Principalmente, porque é um ótimo trabalho e queremos manter o máximo de compatibilidade possível com a Especificação OpenAPI ”

O que nos leva à percepção de que as duas soluções não são concorrentes, tendo cada uma um nicho no qual auxiliam o processo de criação de documentação de funcionalidades de fácil leitura e visualização.

Quando olhamos a estrutura lado a lado, de ambas as especificações, podemos facilmente visualizar a similaridade. Isto mostra a real compatibilidade que os desenvolvedores buscaram manter com o OAS.

Resumindo, a adoção de A2S para documentar APIs orientadas a mensagem é o mesmo que adotar OAS para APIs REST, e inversamente não há razão para A2S aparecer em uma conversa sobre APIs REST ou OAS ser discutido no contexto de arquiteturas orientadas à mensagem.

Exemplo na prática

Para exemplificar a utilização da A2S 2.0, vamos construir uma documentação simples, utilizando o playground da página.

Iniciamos o documento informando a versão 2.0.0 do A2S, seguida de informações de cabeçalho como título, versão da API que estamos documentando e uma descrição. Além dessas informações, podemos definir uma URL com os termos de uso, dados de contato e qual licença é aplicada a API.

Imagem 3: Cabeçalho de informações gerais.

Na sequência, preenchemos informações sobre os servidores, que podem ser development, staging, production. Em cada servidor especificamos a URL de conexão, protocolo utilizado e a versão do protocolo. Ela permite que configuremos variáveis como porta de acesso, além de parâmetros que podemos receber via URL ou headers, e outras informações de acordo com a necessidade de cada serviço.

Imagem 4: Seção de informações sobre servidores.

Definimos o tipo de conteúdo padrão, que em nosso caso é application/json, logo após iniciarmos a descrição dos nossos channels (tópicos), criamos o nome (em nosso exemplo usamos sms/send e sms/success) e inserimos a descrição. Posteriormente, informamos se é um publish ou subscribe, definimos um operationId e podemos referenciar o tipo de mensagem utilizando o $ref: ‘#components/messages/{nomeMensagem}’, esta referência deve ser declarada em schemas.

Imagem 5: Seção de definição de channels (tópicos).

Os objetos referenciados em nossos channels (tópicos) devem ser detalhados na seção components. Definimos os nomes (notification e notificationSuccess), descrevemos os atributos como name, title, summary, content-type e definimos um payload, que em nosso exemplo estamos referenciando como smsPayload e smsSuccessPayload, usando $ref: ‘#/componentes/schemas/{nomeComponente} ambos serão especificados na seção de schemas.

Imagem 6: Seção de componentes de mensagem.

Na seção schemas, efetivamente definimos os objetos que referenciamos em nossos tópicos. Aqui, informamos o tipo de objeto, atributos e validações. A AsyncAPI fornece uma gama de validadores como: pattern, maxLength, minLength, maximum, exclusiveMaximum, minimum, exclusiveMinimum, uniqueItems, readOnly, entre outros.

Os objetos de payload das mensagens que referenciamos anteriormente são smsPayload que contém os atributos ddd, telefone e mensagem, e o objeto smsSuccessPayload com os atributos id, envio, mensagem e sistema.

Imagem 7: Início da seção schemas e definição do payload – objeto smsPayload.

Imagem 8: Definição do payload – objeto smsSuccessPayload.

A documentação exibe, ainda, exemplos de payload de mensagens, de acordo com a definição que inserimos. Abaixo podemos ver exemplos dos dois payloads de mensagens que especificamos.

Imagem 9: Exemplos do payload no formato json

Conclusão

Podemos verificar o quão interessante é a utilização da especificação AsyncAPI 2.0 e o quanto ela pode nos auxiliar no dia a dia. Entendemos que não existe “A2S vs OAS”, e sim “A2S e OAS”, pois elas não são concorrentes e sim complementares. A2S foi inspirada e baseada na OAS, e tem feito o possível para manter a compatibilidade, com o objetivo de tornar o trabalho de documentar arquiteturas orientadas a mensagens tão “fácil/simples” de se trabalhar quanto com APIs REST.

Referências

[AsyncAPI specification 2.0.0]

https://www.asyncapi.com/docs/specifications/2.0.0

[AsyncAPI playground]

https://playground.asyncapi.io/?load=https://raw.githubusercontent.com/asyncapi/asyncapi/master/examples/2.0.0/simple.yml

[AsyncAPI Initiative]

https://github.com/asyncapi

[Changelog]

https://github.com/asyncapi/spec/releases

[AsyncAPI and OpenAPI: an API Modeling Approach]

https://engineering.salesforce.com/asyncapi-and-openapi-an-api-modeling-approach-db9873695910

[Padrão Publisher-Subscriber]

https://docs.microsoft.com/pt-br/azure/architecture/patterns/publisher-subscriber

[Filas de mensagens]

https://aws.amazon.com/pt/message-queue/

[#01 – Mensageria]

https://medium.com/@devbrito91/mensageria-1330c6032049

[Introducing the AsyncAPI specification]

https://blog.hitchhq.com/introducing-the-asyncapi-specification-7feb57b460ae

[Whats’s new on AsyncAPI? Lots!]

https://medium.com/asyncapi/whats-new-on-asyncapi-lots-2d9019a1869d

 

 

Comment Area

  1. Excelente artigo Paulo, Parabéns! Bem fundamentado e descontruindo essa idéia de “concorrência” muito comum na nossa área entre duas coisas completamente distintas. Acho importante trazer à tona esse tipo de perspectiva.