AsyncAPI

AsyncAPI is a standard for documenting contracts for asynchronous APIs. Let’s say, you connect multiple services via Apache Kafka or RabbitMQ, AsyncAPI is there to provide information about available servers, topics, queues and payload structures. If you already heard about „OpenAPI“ before: AsyncAPI is the counterpart for asynchronous APIs.

Main Concepts

The four main concepts in AsyncAPI are Server, Producer, Consumer and Channel.
As I introduced this blog article by mentioning two concrete messaging systems, you might be irritated by the term Server now – at least I was :). The reason for this confusion is that AsyncAPI is not limited to APIs that build on top of messaging systems but also supports client/server models as it is known from WebSockets.

Producers are components which create and send data. Consumers receive and process exactly that data from the server. Channels are a concept of organizing different types of messages into separate units – like directories on a file system.

To get a little bit more concrete, just imagine an online payment service just like PayPal. It has a User Accounts Service which publishes events when users sign up or sign out. A Newsletter Service wants to know both about sign ups and sign outs in order to maintain its own user database. The invoice Service needs to know about sign outs, because this should send back the remaining credits of a user.

AsyncAPI Definition File

AsyncAPI definitions are YAML or JSON files. The top-level sections servers and channels refer to AsyncAPI’s main concepts already mentioned above. The other two terms from the main concepts, Producer and Consumer do not occur in the AsyncAPI document.

asyncapi: 2.5.0
info:
  title: SuperPay
  version: '1.0.0'
servers:
  production:
    url: rabbitmq.superpay.com
    protocol: amqp
    description: This is SuperPays central RabbitMQ production deployment.
    security:
      - user-password: []
channels:
  signups:
    bindings:
      amqp:
        is: routingKey
        exchange:
          name: myExchange
          type: topic
          durable: true
          autoDelete: false
        bindingVersion: 0.2.0
    publish:
      description: When a user signs up, a message MUST be published on this channel.
      message:
        $ref: '#/components/messages/signup-msg'
    subscribe:
      message:
        $ref: '#/components/messages/signup-msg'
  signouts:
    publish:
      message:
        $ref: '#/components/messages/signout-msg'
    subscribe:
      message:
        $ref: '#/components/messages/signout-msg'
components:
  messages:
    signup-msg:
      name: Signup message
      summary: >-
        Informs about a new user has signed up in the system. 
      payload:
        type: object
        additionalProperties: false
        properties:
          id:
            type: integer
          fullName:
            type: string
          email:
            type: string
            format: email
          age:
            type: integer
            minimum: 18
    signout-msg:
      name: Signout message
      summary: >-
        Informs about a user signed out the system
      payload:
        type: object
        additionalProperties: false
        properties:
          userId:
            type: integer

  securitySchemes:
    user-password:
      type: userPassword

Components is just a container for re-useable snippets of the definition file. In the example snippet above, I re-used the payload definition for signup messages by referencing it from channels/signups/publish and channels/signups/subscribe with $ref: '#/components/messages/signup-msg'.

How does AsyncAPI integrate protocol-specific concepts?

A client that should consume data from Apache Kafka needs to know the name of the topic that holds the data. In another scenario, it might not be Kafka but RabbitMQ. Now, there are no topics but queues and exchanges, because, although they are both message brokers, the protocols used under the hood are different.
AsyncAPI integrates these protocol/broker-specific data via so-called bindings. Examples for available bindings are AMQP, JMS, Kafka, NATS, Google Pub/Sub, AWS SQS or WebSocket.

AMQP specific data inside a rendered html documentation

Tooling

Just to get hands dirty as fast as possible, I recommend AsyncAPI Studio (beta). By combining a text editor and a live html documentation generator, it is a good starting point with a low entry barrier to start fiddling with your first AsyncAPI document.

AsyncAPI Studio

While AsyncAPI Studio might serve as a good starting point, there will rise more advanced requirements when you start using AsyncAPI in your project. The following list contains just a few examples.

  • Code-first tools
    • Create AsyncAPI Documents via code
  • Code Generators
    • Generate a html or markdown documentation
    • Generate project stubs in several platforms (spring, node, python, Typescript…. )
    • Generate just payload data models for your programming language
  • Converters
    • Migrates AsyncAPI documents from older to newer versions
    • Formatters
  • Validators

More related tools can be found here.

Data Model Generator: Modelina

Right now, Modelina allows you to quickly generate data models for TypeScript, Java, Go, Javascript and C#. The tool is available as an npm package and can be installed via npm install @asyncapi/modelina. Similar to AsyncAPI Studio, a handy browser-based instance is available here. Side note: Modelina is not limited to AsyncAPI. OpenAPI and JSON Schema documents are also supported inputs.

Kommentar verfassen

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Scroll to Top