Synchronous Response Deferred Processing
How can we allow a service consumer to deal with a synchronous interface whilst protecting the underlying service infrastructure from unacceptable load?
When a service operation carries out a large amount of work that would involved slow response time and or high load on the service infrastructure we would typically apply the Asynchronous Queuing pattern. To apply this pattern requires that the service consumer must be able to deal with an asynchronous response from the service to a separate response handler. In some circumstances it is not practical for the service consumer to deal with the service response asynchronously and it needs to deal with the success or failure of the call immediately. This leads to a conflict in that the service provider needs to protect their systems from excessive load by dealing with service request asynchronously but the service consumer needs to be able to deal with a synchronous service.
Provide a synchronous service façade that abstracts away the validation logic for the service call into a shared call and then stage the inbound request on a message queue for processing at a later date. If the service request validates successfully then the request can be placed on the queue for processing and a 'success' response issued to the caller immediately. A failure will prevent the message from being placed on the queue and an immediate 'failure' response is issued to the service consumer.
Allowing the service consumer to deal with synchronous service calls whilst applying the pattern of Asynchronous Queuing.
There is a need to ensure that all validation logic for the underlying service call is abstracted into a shared component that is accessible by both the initial service façade and the internal service that will process the request on the message queue.
This cannot be used if there is need to immediately see the changes that have occurred in the receiving system since there is no guarantee as to when those changes will be persisted.
PrinciplesStandardized Service Contract, Service Statelessness, Service Abstraction, Service Loose Coupling
Figure 1 - Asynchronous Queuing Problem.
- If the Asynchronous Queuing pattern is used, Service A accepts the inbound request from the service consumer and places the request on a message queue for processing by Service B at a later stage. There is a conflict in that the service consumer requires a synchronous response but it will not receive a response until sometime later when Service B has processed the request.
- Service B will process the request and put the response on the message queue.
- Service A reads the response message from the queue and would normally forward this to the endpoint defined in the request message. There is however a problem in handling the response message by the service consumer because it is unable to handle an asynchronous response.
Figure 2 - Synchronous Response Deferred Processing Solution
- Service A accepts the request message from the service consumer and applies the logic to validate the request. If the request is valid then it is placed on the message queue and an immediate 'success' response is returned to the service consumer. If the request if not valid then an immediate 'failure' response is returned to the service consumer and no request is placed on the message queue.
- Service B reads and processes the message but this can then be dealt with as a one-way service call.
Often in scenarios where a piece of legacy code is leveraged to perform a service function the implementation may performing a number of resource intensive operations. It is not good practice to expose this code as a synchronous service as it could mean that the underlying system may go through periods of heavy utilization at inconvenient times of the day. In an integration scenario where the service consumer does not have the ability to deal with an asynchronous web service call, the service interface may need to be exposed via a synchronous capability. In order to do this the validation logic of the underlying legacy service needs to be separated out into a shared component that can be used by both the legacy service and the external service interface. Some applications may be calling the legacy service directly so to prevent logic duplication it needs to be separated into a shared service or component. Service consumers can then call the service synchronously and the request can be validated in real time but processed later. The service consumer is then safe to assume that the request will be processed at some time in the near future but its responsibility at this stage is complete.
- Difficulty in separating the underlying validation logic into a shared component.
- Changes are not immediately visible in the target systems as the processing is deferred.
- All validation logic must be separated from the processing and persistence logic to minimize the risk of a processing failure on a valid request.
Case Study Example
Airline X and Airline Y need to transfer and synchronise certain data between their two systems. Airline X wishes to transfer data triggered by an event change so that the data is pushed to a service hosted by Airline Y. Airline Y needs to protect it's services from being overloaded by requests because the processing involved in the data transfer is resource intensive. Airline X has no experience or ability to deal with an asynchronous service call and as such require that Airline Y exposes only a synchronous interface so that Airline X receives an immediate valid/not valid response to the service call request. Airline Y has determined that the underlying legacy service that does the processing is also being consumed by other legacy applications. In order to satisfy both Airlines requirements, Airline Y decides to separate the validation logic of the legacy service into a separate validation component. Another synchronous Service Façade is implemented that uses the separated validation logic to validate the inbound request. A message queue is implemented that is written to by the newly created Service Façade only if the request is deemed valid. A second one-way service is implemented to accept the request from the message queue and call the legacy service to process the request. The processor is then decoupled from the service that accepts and validates the request and is free to process the request when the system is under low load. The service consumer receives and immediate response as to the validity of the request.