AsyncAPI: Diseña APIs asíncronas

La especificación AsyncAPI está en el foco en el mundo de la integración de software, ya que permite especificar APIs orientadas a eventos de manera estandarizada. En este artículo de explica el concepto de Event Driven Architecture (EDA), se describe la especificación AsyncAPI y se muestra un ejemplo de código.

Introducción

AsyncAPI es una especificación liderada por Fran Méndez que permite definir APIs y que se enfoca en arquitecturas orientadas en eventos (EDA).

La OpenAPI Specification (anteriormente Swagger) es junto a RAML uno de los principales estándares utilizados para definir APIs. Aunque con OpenAPI 3.0 es posible describir callbacks – de tal manera que a la hora de invocar a una API se pueda especificar una URL a la que enviar la respuesta – las capacidades de OpenAPI para describir escenarios asíncronos orientados a eventos son bastante limitadas.

Event Driven Architecture

Una arquitectura orientada a eventos es un paradigma de diseño en el que una pieza de software (un consumidor de eventos) recibe una notificación de que un evento o mensaje ha sido publicado en un canal por otra pieza de software (un generador de eventos, o publicador).

A diferencia de un modelo clásico petición respuesta como el que caracteriza a las APIs RESTful tradicionales, en una EDA el generador de eventos no se queda bloqueado en espera a que el consumidor responda a su mensaje. Es un modelo mucho menos acoplado que el modelo petición / respuesta, ya que el publicador de eventos no conoce siquiera la identidad del consumidor de los eventos. En una EDA cobra mucha importancia el Canal, que normalmente suele ser un message bróker como RabbitMQ o Apache Kafka:

 

Event Driven Architecture

Las arquitecturas orientadas a eventos disfrutan de una alta escalabilidad y una mejor tolerancia a fallos. Así, ante una situación imprevista de elevada carga, una arquitectura tradicional basada en un modelo petición / respuesta suele bloquearse, ya que ante un componente saturado (una base de datos, un microservicio) los demás componentes que interactúan con dicha pieza de manera síncrona también se saturarán, produciendo problemas de escasez de hilos, timeouts, etc. Sin embargo, en una arquitectura orientada a eventos, los componentes con pobre rendimiento no bloquean a sus consumidores, sino que estos simplemente generan más eventos que son encolados, facilitando que se pueda reaccionar y mejorar el rendimiento de la solución sin rediseñarla, tan solo ampliando o escalando los recursos del sistema saturado.

AsyncAPI

El objetivo de la iniciativa AsyncAPI es conseguir que trabajar con EDA sea tan fácil como es hoy en día trabajar con APIs RESTful. Uno de los motivos del éxito de las APIs REST ha sido entre otros la existencia de estándares como OpenAPI que permiten editar especificaciones, generar documentación automáticamente, portales de desarrollo, generadores de código, generadores de mocks, etc.

AsyncAPI

Se trata de una especificación que es amigable tanto para máquinas como para humanos. Es agnóstica del protocolo, de tal manera que se puede utilizar para describir APIs que funcionan sobre diferentes protocolos como MQTT o WebSockets.

Estos son los principales elementos de la especificación:

 

Principales elementos de la especificación

Es posible definir esquemas de seguridad que se pueden utilizar para proteger operaciones. Algunos de los esquemas son: usuario y contraseña, API keys, certificados, flujos OAuth / OIDC, etc.

La especificación es extensible. Así, es posible añadir nuevas propiedades, las cuales deben llevar siempre el prefijo “x-“, como por ejemplo “x-internal-id”.

Ejemplo de código

La mejor manera de entender AsyncAPI es viendo un ejemplo. Así, supongamos que necesitamos definir una API que describa un escenario asíncrono mediante el cual cada vez que un cliente nuevo hace una compra, un consumidor es avisado mediante un evento, de tal manera que este puede realizar algún tipo de acción. Podemos utilizar el editor online de AsyncAPI para teclear este código:

asyncapi: '2.0.0'
info:
  title: Customer API
  version: '1.0.0'
  description: |
    The Customer API sends an async message
    when a new customer makes a purchase.
  license:
    name: Apache 2.0
    url: 'https://www.apache.org/licenses/LICENSE-2.0'

servers:
  example:
    url: mqtt://example.org
    protocol: mqtt

channels:
  customers:
    publish:
      summary: Notifies a new customer has done a purchase.
      operationId: onNewCustomer
      message:
        payload:
          type: object
          properties:
            id:
              type: integer
              minimum: 0
              description: Id of the new customer.
            purchaseAmount:
              type: integer
              minimum: 0
              description: Amount of the purchase.
            name:
              type: string
              description: Name of the new customer.

 

Vemos a continuación cuales son las principales secciones del código:

  • El campo asyncapi indica que se trata de un documento que sigue la especificación 2.0 de AsyncAPI.
  • El campo info contiene información sobre la API de Customers, incluyendo en este caso el nombre de la API, su versión, la descripción y el tipo de licencia.
  • La sección servers indica el servidor al que enviar los mensajes y el protocolo (MQTT).
  • La sección channels describe los mensajes que se publican en esta API, en este caso indicando que en su payload hay tres atributos: id, purchaseAmount y name.

Conclusión

Hemos visto cuales son las principales características de las arquitecturas orientadas a eventos y como la especificación AsyncAPI permite definir APIs asíncronas de una manera agnóstica al protocolo, documentando las propiedades de los mensajes intercambiados.