Request-Response Using Azure Service Bus
Request-Response is most obvious type of communication if you are doing any kind of web development. Mostly it is related to web development but it is not limited to that only. For any communication if you calling any method and if you are waiting for response from that method then it also falls into same category. Sometime It may also refer as Request-Reply as well.
In distributed environment sometime request-response pattern is not good fit for some use case. For Example if you request and it requires more time to process request or processing request is costly component in that case if there are too many request then it will increase cost and response time. Also operation behavior is not such that it requires immediate processing instead client want that request is accepted or not. In this case request is accepted and put into some queue for processing. Later stage that request get process and response is provided either by some notification.
Now Azure Service Bus is a message broker component offering from Azure. Mainly Azure Service Bus get involve when there is any asynchronous type of communication get involved. This is some what similar what above image try to explain.
Now question is, is it possible to use Azure Service Bus for request-response pattern. Let's explore the option.
Simple answer is Yes. It is possible to do so. By this we can benefited that same event driven flow can be used to achieve request-response functionality yet overall flow still remain decoupled.
For this article, I will be using Azure Service Bus as Message Broker so solution will be remain in that context. I am sure other message broker also have same functionality.
Solution 1 : With Help Of Temporary Queue
In this scenario for every request, there is one temporary queue is being created. This queue is response holder for every request. Let me try to explain by image.
Following are steps.
Client Make API Call.
In API Call following steps performed.
For request handling there is fix queue.
Create temporary queue. ( With some guid)
Create Message to send to request queue. This message contains "ReplyTo" property with temporary queuename.
Send Message to request queue.
- 6.a. Now wait for message on temporary queue.
Request processor process the request and as request has information for temporary queue.
After successful processing of message, processor send message or response to response queue. ( Now flow go back to 6.a).
Note: Also make sure that it is possible that Step 7 and Step 8 performed by separate application.
Pros
This solution is good enough when there are less no of request to process.
Also due to separate temporary queue, it is more isolated per request so less security issue as there are less chances of another message in same queue.
Temp queue automatically get deleted after 5 minutes so this is also handle by service bus it self.
Cons
Temporary queue is being created for each request and this will slow down the response for request.
It is required special permission to perform create queue operation. As this falls under management activity.
Solution 2: With Help of Session Enabled Response Queue
In this scenario we try to overcome issue that present in previous solution. Main issue with above solution is to create temporary queue. This raise some elevated permission so it is security issue.
In this solution we will create response queue just like we are creating request queue. Only difference is that It must have session enabled. Now for each message to request queue contain information for response queue message and session id as well.
Following are steps.
Client Make API Call.
In API Call following steps performed.
For request handling there is fix queue.
Create Message to send to request queue. This message contains "ReplyTo" property with response queue name and replyToSessionId with sessionId set .
Send Message to request queue.
- 6.a. Now wait for message with specific sessionId on response queue.
Request processor process the request and as request has information for response queue and sessionId.
After successful processing of message, processor send message or response to response queue with sessionId available in replyToSessionId. ( Now flow go back to 6.a).
This solution comparatively better then previous solution. One more things keep into mind that this will not give native request-response performance in which request directly process instead of via message broker (Azure Service Bus).
Source code
It is available for download at following location.
Configuration
For temporary queue.
builder.Services.AddScoped<IServiceBusRequestResponse, ServiceBusRequestResponseWithTemporaryQueueClient>();
For Session
builder.Services.AddScoped<IServiceBusRequestResponse, ServiceBusRequestResponseWithSessionClient>();
Get connection for service bus with management capabilities. Configure it in appsettings.json of web api and console application ( request processor).
"ServiceBusConnectionString": "Endpoint=sb://<<yournamespace>>.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=<<key>>"
Overall this will look something like this.
builder.Services.AddScoped<IServiceBusRequestResponse, ServiceBusRequestResponseWithSessionClient>();
builder.Services.AddSingleton<ManagementClient>(new ManagementClient(builder.Configuration.GetValue<string>("ServiceBusConnectionString")));
builder.Services.AddSingleton<ServiceBusClient>(new ServiceBusClient(builder.Configuration.GetValue<string>("ServiceBusConnectionString")));
At Azure Following component needs to create.
Request Queue Name: myrequest
AutoDeleteOnIdle : False
SessionEnable : False
MaxDeliveryCount: 1
MessageTimeTolive : 5 minutes
Response Queue : myrequest-response
SessionEnable: True
AutoDeleteOnIdle : False
MaxDeliveryCount: 1
MessageTimeTolive : 5 minutes
For temporary queue option, that queue created automatically by code.
Summary
Overall, It is completely possible to use Azure Service Bus for request-response pattern. By this we can enable single flow can be utilize as request-response and event-driven approach.