In this tutorial, you'll learn how to implement the request/reply pattern in an AsyncAPI document using a straightforward ping-pong example.
Before we begin, it would be beneficial for you to have a basic understanding of AsyncAPI and Event-Driven Architectures (EDA). If you need a refresher, refer to our Event-Driven Architecture document.
Request/reply is a messaging pattern involving two key components: the requester, which sends a request message, and the replier, responsible for receiving this request and responding with a reply. This pattern fundamentally revolves around these two roles, requester and replier.
Static reply address
Here's how you can implement the request/reply pattern when the response address is known at the compile or design time.
A requester can be configured with the send
operation, where it dispatches a message to the ping
channel and anticipates receiving a response through the pong
channel.
In the below example, the Operation Reply
object within the pingRequest
operation provides essential details, like the destination for the reply, which is the pong
channel. Since the pong
channel is configured with only one message, there's no need to explicitly define the reply message. Similarly, the ping
channel has just one message, eliminating the need to specify the message sent in the request.
1asyncapi: 3.0.0
2info:
3 title: Ping/pong example with static reply channel
4 version: 1.0.0
5 description: Requester example that initiates the request/reply pattern on a different channel than the reply is using
6channels:
7 ping:
8 address: /ping
9 messages:
10 ping:
11 $ref: '#/components/messages/ping'
12 pong:
13 address: /pong
14 messages:
15 pong:
16 $ref: '#/components/messages/pong'
17operations:
18 pingRequest:
19 action: send
20 channel:
21 $ref: '#/channels/ping'
22 reply:
23 channel:
24 $ref: '#/channels/pong'
25components:
26 messages:
27 ping:
28 payload:
29 type: object
30 properties:
31 event:
32 type: string
33 const: ping
34 pong:
35 payload:
36 type: object
37 properties:
38 event:
39 type: string
40 const: pong
Dynamic reply address
Occasionally, the destination for a reply cannot be predetermined during the design or compile phase. In such cases, the address for the reply is dynamically determined at runtime, allowing for more flexible and adaptive communication.
In scenarios where the address or reply channel is unknown at design time, the address
property can either be set to null
or omitted entirely. To define the reply address dynamically, the Operation Reply Address
object can be used, allowing for runtime expressions. That enables the requester
to specify where the replier
should send the reply, detailing the address's location and its specific position within the request.
In this situation, the location
property is assigned the runtime expression $message.header#/replyTo
. Such an expression indicates that the address for the reply is located within the header of the request, specifically in the replyTo
field. This method dynamically determines the reply address based on the content of the request header.
1asyncapi: 3.0.0
2info:
3 title: Ping/pong example with reply specified as dynamic information provided in the runtime
4 version: 1.0.0
5 description: Example document for an application that processes ping requests and replies to the address dynamically specified by the requestor in the message header
6channels:
7 ping:
8 address: /ping
9 messages:
10 ping:
11 $ref: '#/components/messages/ping'
12 pong:
13 address: null
14 messages:
15 pong:
16 $ref: '#/components/messages/pong'
17operations:
18 pingRequest:
19 action: receive
20 channel:
21 $ref: '#/channels/ping'
22 reply:
23 address:
24 description: Reply is sent to topic specified in 'replyTo' property in the message header
25 location: "$message.header#/replyTo"
26 channel:
27 $ref: '#/channels/pong'
28components:
29 messages:
30 ping:
31 headers:
32 type: object
33 properties:
34 replyTo:
35 type: string
36 description: Provide path to which reply must be provided
37 requestId:
38 type: string
39 format: uuid
40 description: Provide request id that you will use to identify the reply match
41 payload:
42 type: object
43 properties:
44 event:
45 type: string
46 const: ping
47 correlationId:
48 $ref: "#/components/correlationIds/pingCorrelationId"
49 pong:
50 headers:
51 type: object
52 properties:
53 requestId:
54 type: string
55 format: uuid
56 description: Reply message must contain id of the request message
57 payload:
58 type: object
59 properties:
60 event:
61 type: string
62 const: pong
63 correlationId:
64 $ref: "#/components/correlationIds/pingCorrelationId"
65 correlationIds:
66 pingCorrelationId:
67 location: '$message.header#/requestId'
While the above examples are a simple implementation of the request/reply pattern, in a protocol-agnostic world there are many different ways to represent the request/reply pattern. All of which are supported by AsyncAPI.