Integration Patterns in Microservices World
In this in-depth article, architects and developers can use this information to guide their integration solutions.
Join the DZone community and get the full member experience.
Join For FreeIntegration, Events, and Microservice Patterns
Overview
It is intended for architects and developers to use this information to guide their integration solutions. Once an integration style has been selected, they should review the associated integration style section to understand the typical patterns relevant to that integration style, abide by the constraints and review the implementation considerations.
Understanding “Integration” – Applications, Integration, and Microservices
There is an important distinction around the responsibilities of an integration system and applications. Integration facilitates the transmission of information between systems and may be realized through the use of technologies such as messaging systems, API gateways, and their associated protocols (MQ, AMQP, HTTP, FTP). Over the years, many technology vendors have implemented additional capabilities within their integration products that have enabled developers to add business logic embedded within the integration solution. This has resulted in business logic being spread outside of the application layer and integration an integration system that is often managed and maintained by a single team resulting in a resource bottleneck.
In following a microservice-based architecture that supports a decentralized development model, applications are implemented as independently developed and operated modules that encapsulate business logic. Whilst microservices may connect with other microservices or other systems of record they do so via a communication mechanism that does not hold business logic or manage business state.
Business logic is the programmatic encoding of real-world business rules that govern the access and lifecycle of business domain data. Simply, if an action requires the processing of business rules against business information then it constitutes business logic.
Business logic includes:
- Semantic Transformation – requires an interpretation of business entities and their attributes following business rules
- Process, Orchestration, or Workflow – requires the execution of the steps of a business process, with business context, rules and management of state.
- Data Enrichment – requires business context, state and/or rules.
Business logic should only be implemented within an application, not within an integration layer. The integration layer facilitates the exchange of information between applications and includes the following technical components: API gateways, ESBs, File Transfer Systems and Messaging Systems. Syntactic transformation, the straight through mapping of attributes with the same business meaning, may be implemented within the integration layer.
Synchronous vs Asynchronous Integration
Synchronous communication involves the consumer submitting a request to a service and waiting for the service to respond before the consumer can continue executing its process. The technical implementation of this form of communication has evolved over time with sophisticated frameworks and computing capabilities so that an application does not necessarily need to block in whole. From a user experience perspective, a User Interface (UI) may continue to be responsive to interaction whilst a synchronous request has been submitted.
Whilst a synchronous process may utilise different integration styles a common synchronous communication protocol is HTTP, used with the API style of integration. HTTP by nature is synchronous in that a request is submitted (either requesting information or submitting information) and the submitting application waits for the response (either a simple OK or some data in the payload is returned). Modern frameworks ensure the UI or process can continue to operate in parallel to perform other tasks however some thread of execution is blocked to await the response. Typical request/response time frame is ideally measured in milliseconds to a few seconds with timeout set to 30-60 seconds.
Asynchronous communication involves the consumer submitting a message to a service but not needing to wait for the service to respond. A consequence of the message in the form of a new message may be returned to the consumer at some point in the future or not at all. The consumer often does not know the destination service and simply submits the message to a messaging system which then delivers the message to one or more destination services. Asynchronous communication may be realised through different integration styles but is typically implemented using asynchronous protocols such as AMQP, MQ, MQTT, Web Sockets or proprietary binary protocols over TCP sockets such as with Kafka.
Web browsers largely use the HTTP protocol and web applications will include JavaScript that execute within the browser to make API calls over HTTP. Modern JavaScript frameworks can ensure the UI is not blocked when making these synchronous calls. For cases where an asynchronous interaction is required, polling is used by the JavaScript code to determine the presence of response data from the service however asynchronous integration may also be used such as web sockets and MQTT.
Integration Styles and Patterns
An overview of the identified styles and patterns adopted within the Digital Platform are shown in Figure 1 using the definition of style and pattern as:
Style — High level, abstract, approaches to integration that represent a number of specific patterns
Patterns — Technology agnostic, generic designs that address common business problems/scenarios
The following integration styles will be supported by the Digital Platform going forward:
- API
- Messaging
- File Transfer
For each of these styles there are various patterns and constraints that will be defined. There are situations where some or all participants in an integration do not support directly connecting with a messaging system. These participants may utilise an intermediary service to perform a translation between an API integration to a messaging interface.
Figure 1 Integration Styles and Patterns
Selecting Integration Style
The following table provides a set of scenarios under each integration style to help select a suitable style. Identify a matching scenario to select the matching integration style.
API |
Messaging | File Transfer |
Application submits data, requests data or issues command to an internal or external application or service that requires immediate processing of submitted data or command and subsequent near-immediate response is expected. | Application submits data or issues command to an internal application or service that does not require a near-immediate response. | Transfer large data set to one or more applications as a bulk data set as part of a batch process. |
Application submits data or issues command to an internal application or service that is likely to have an on-going planned or unplanned outages and does not require a near-immediate response. | Existing application only supports file transfer-based integration. | |
Application submits data or issues command to multiple internal applications or services but does not require near-immediate response. | ||
Application submits a high volume of data or commands to one or more internal applications or services and does not require a near-immediate response. | ||
Example | Example | Example |
Customer requests an account via web application in digital channel. The customer has submitted their details and is awaiting a response. The response time requirement is < 3 seconds. A number of components are integrated through a series of API-based calls. This example illustrates a synchronous interaction with an end user and supporting systems that follow the API style integration. | An update to a customer’s profile is made via a web application in the digital channel. A number of systems must be notified of the changes in order for them to change their own records. This example illustrates an asynchronous update of multiple systems that does not require a response to be returned to the initiating system. | A large number of charging requests are generated on a nightly basis and must be issued to the financial system once a night for processing. A file transfer style of integration may be used to transfer the payment requests within one or more files that are transferred as part of a batch process to the financial system. This example illustrates a file transfer style integration. |
General Integration Principles
Principle |
Condition | Guidelines | Reasoning |
Business logic should not be implemented within the integration technology layer. The integration layer includes the following technical components: API gateways, ESBs, File Transfer Systems or Messaging Systems. (Think dumb pipes, smart end points) |
All | Integration should facilitate the exchange of information between applications. Integration components should not include any business logic or state. Integration adapters used as a façade to API providers should not include any business logic or state. Syntactic transformation for the purpose of implementing an integration adapter is not considered business logic. Data enrichment is considered business logic and must not be implemented within the integration layer. This may be implemented by a package application or a microservice. Orchestration is considered business logic and must not be implemented within an integration layer. This may be implemented by a package application or microservice. |
Microservices are components of an application, not an integration in of itself. Integration technologies are primarily designed for data transfer and have significantly less capability in solving the complex and broad set of business problems when compared with an application technology that is programmable using a general programming language. Placing business logic in an integration technology mixed with the responsibility of data transfer causes a high risk of the logic being “orphaned’ outside of the applications and/or microservices that have clearly been marked as encapsulating/owning the logic for a particular business function/capability. This leads to both overhead and confusion when maintaining and extending this capability. |
Packaged application suites comprising individually deployed applications should not have an intermediary service inserted between inter-application integration. | Packaged suite inter-application integration deemed internal or private by the vendor. | Packaged suite applications may integration directly via point-to-point interface as inherent within the product. | The integration between packaged application suite components have typically been built and tested by vendors to operate in a tightly integrated fashion. Inserting intermediary (e.g. API Gateways, microservices) components between pre-built components may affect performance, reliability and support. Interface contracts between suite applications are volatile and may change with version updates to the products causing additional effort to update the intermediate components. |
Business capabilities may be exposed by packaged applications or custom microservices. | All | Business capabilities such as Risk Engines and Product Pricing may be realised through a packaged application, a custom microservice or a combination of both. | Leverage the value provided by investments in strategic package solutions. Minimise the impact on costs and supportability of modifying strategic package solutions. |
Related Enterprise Architecture Principles
Principle |
Condition | Guidelines | Reasoning |
Capability that exists within a strategic packaged application should not be hollowed out into an independent microservice if the capability does not need to be independently managed or developed and at the expense of significant cost and supportability of the package. | All | Packaged applications should not be modified to extract and disable business capability that is central to the package operation if the capability does not need to be independently managed or developed. Package applications should not be modified to extract and disable business capability if by doing so significant cost and supportability is incurred. Capabilities within a packaged application may be enhanced or extended within a reasonable cost (balance cost/return). Capabilities within a packaged application may be realised by complementing the inherent features within the packaged application or microservice or other systems. |
Leverage the value provided by the investments in strategic packaged solutions. Minimise the impact on cost and supportability of modifying strategic packaged solutions. It takes significant engineering effort to implement the equivalent of packaged solutions that have had years of development. |
Integration Patterns – API
API may be invoked to initiate behaviour and/or exchange information. A consumer may call a target system API directly or through an intermediary.
This style of integration is synchronous in nature and is used where a response is required within a short time frame, typically as a result from a user action or a step in an executing process. API calls may also be used to trigger processes, expose interfaces externally in a secure and restricted manner or act as an intermediary translation style for the messaging integration style.
Patterns
Pattern |
Description | When to use | Considerations |
Request/response | A consumer submits a request to an application that processes the request and returns the result over the same client connection. | When the response from the request is required within a short time frame and the consumer cannot continue without the result. (Short means less than 60 seconds) |
This pattern results in temporal coupling between the consumer and the API provider. If the API provider is not available, the consumer is unable to submit requests. |
Request/Acknowledge/ Poll |
A consumer submits a request to an application that is processed in the background. The application returns a response acknowledging receipt of the request. | When the response from the request is not required within a short time frame. The consumer may periodically submit a request for the status or result of the processing of the request. (Short means less than 30 seconds) |
The acknowledgement response to the request should include a link for the consumer to submit requests for status or the full results of the processing of the request. The pattern is suitable for device-side (browser or mobile app) integration with Systems of Engagement (SoE). |
Request/Acknowledge/ Call-back |
A consumer submits a request to an application that is processed in the background. The application returns a response acknowledging receipt of the request. The application calls the consumer when the action is completed. |
When the response from the request is not required within a short time frame but the consumer needs to be notified when the result is ready. The consumer requires to be called by the provider when the result is available. (Short means less than 30 seconds) |
The initial request should include a link for the provider to perform a call-back to the consumer when it has completed processing the request. The provider will call the consumer using the provided call-back link, passing the result. |
Consumer Adapter | A component implemented to map between the consumer’s own information model and protocol to that of the APIs. | A consumer cannot consume an API directly and requires transformation to map from its own domain model to that of the API it is consuming. | Whilst the consumer adapter could be implemented as part of the provider (microservice or packaged application) it is strongly encouraged to be implemented by the consumer. |
Constraints
Constraint |
Condition | Rules | Reasoning |
APIs must confirm to the REST architectural style | Developing a new API as part of bespoke application or microservice | APIs must be stateless. APIs must conform to a uniform interface based on HTTP operations. Resources must be identified in the request. Support Hypermedia as the engine of application state (HATEOS). Resources may be cacheable. Refer to API Standards document for further constraints. |
Ensure a consistent implementation of APIs improving supportability and implementation efficiency. |
Payload schema must be participant independent. | Developing a new API as part of a bespoke application or microservice. | The payload schema must be based on a system independent information model. | Provides decoupling between applications. |
Payload schema must be defined. | Participant is an external vendor’s System of Record. | Payload exchanged with an external vendor’s System of Record must be based on a client defined system independent information model. | Provides decoupling between application and external provider. |
API payloads must be in JSON format | Developing a new API as part of a bespoke application or microservice. | Request and response payloads must be in JSON format. Refer to API Standards document for further constraints. |
Provides a consistent and easy to consume and manage format. |
Syntactic and/or semantic transformation of downstream provider data is the responsibility of the API intermediary (application/microservice) | Developing a new application or microservice that consumes one or more downstream providers with fixed APIs. | API consumers must adopt the independently defined information model and schema. The API intermediary will perform syntactic and/or semantic transformation from the independently defined information model and schema to a downstream provider system’s information model and schema. Downstream providers that require custom built interfaces may expose system independent information model to avoid API intermediary transformation as provider system owners know their system best. |
Provides decoupling between consumer applications and provider applications. |
Internal consumer of external system must call external provider APIs via the DMZ Web Proxy. | All | Internal applications consuming APIs of external systems must call the external provider APIs via the DMZ Web Proxy. | Provides a secure, demarcation between internal and external provider systems. |
External consumers of internal systems must call the internal provider APIs via the external API Gateway. | All | External consumers must call internal APIs via the external API gateway. | Provides a secure, demarcation between internal and external providers systems where security controls and policies may be enforced. |
Existing internal systems must expose their API services using either HTTP based (with XML or JSON payload) OR SOAP based (with XML payload) end points. | All | Service contract specifications must be documents. Service contracts must have defined schemas. SOAP services must have published WSDL files. |
Limit the number of API end point types reducing the need for too many connector frameworks. |
Business logic should not be implemented within the integration layer. | All | Integration should facilitate the exchange of information between applications. Integration should not include any business logic or persistence. |
Microservices are components of an application. |
Application APIs must be registered with a service registration and its documentation published to a developer portal. | All | Exposed application APIs (packaged or microservice) must be registered. Point-to-point internal package or microservice to microservice within a bounded context does not need registration with a service registry. |
Internal package to package point-to-point registries that will not be consumed by other components will not require discovery services. Microservice-to-microservice point to point will be managed through a service mesh. |
Internal consumers of internal microservices must call the APIs via the internal API Gateway. | All | Internal Application or microservice APIs may be exposed via an internal API gateway. | Consistent policy, security and management of APIs within the organisation. |
Integration Patterns – Messaging
A connection between applications via a common messaging system is used to exchange data or invoke behaviour using messages of a pre-defined format. The messaging style maximises decoupling between systems not only from the interface perspective but also from a time-based perspective. The messaging system includes queueing to allow for a consumer reading a message from the messaging system when it is ready, allowing for the handling of high-volume spikes.
Patterns
Pattern |
Description | When to use | Considerations |
Publish-Subscribe | An application submits a message of which one or more applications may receive the message. | One or more applications need to receive the message. The publisher does not need to know who will consume the message. The publisher does not block waiting for a response. |
The order of which the subscriber receives and processes the messages will not be guaranteed. |
Point-to-Point | An application submits a message targeted for only one application. | A command is given to a system with sole responsibility for processing the command (e.g. payment processing). High volume load on target system may impact system’s capacity to process messages. Availability of target system may fluctuate and require a buffer to allow publishing system to continue sending messages even if the target system is not available. |
Sufficient queue depth of message channel should be used to protect target system from high volume spikes. |
Event Message | An application submits a notification of the occurrence of an event of which one or more applications may be interested in receiving the event. | One or more applications need to know when a specific business event has occurred in a time sensitive manner. The emitter of the event does not need to know who will consume the event. The event content typically contains a small payload to describe the state change. |
If the event message does not include the details of the state and only indicates that the state has changed the receiver will need to perform a query against the source system to retrieve the state details. To avoid this extra call, include state information in the event message payload. |
Channel Adaptor | Proxy client bridging between non-messaging to messaging systems. | Support for applications that do not support interfacing directly to messaging system. May implement syntactic transformation. |
HTTP based Channel Adaptors must not be used to implement a synchronous use case. |
Dead Letter Channel | A channel for messages that cannot be delivered. | The messaging system is unable to deliver the message due to invalid configuration, message expiry or invalid header. | Once misconfiguration or availability of consuming system is restored the message can be consumed by replaying it. |
Invalid Letter Channel | A channel for messages that a receiver cannot process. | When an application retrieves a message from the channel but is unable to parse the message. | Where a Channel Adaptor is utilised the Channel, Adaptor is responsible for putting an invalid message onto the Invalid Letter Channel. Message schema/content should be corrected by publisher before re-publishing message. |
Constraints
Constraint |
Condition | Rules | Reasoning |
Message schema must be participant independent. | Multiple Consumers or Multiple Providers | The schema must be based on a system independent information model. | Provides decoupling between applications. |
Message schema may be consumer or provider based. | Consumer and Provider interfaces are custom developed and unlikely to introduce other participants. | The schema may be based on a system independent information model if the effort to prepare the schema is cost effective. The schema may be based on the consumer or the provider system. |
Avoids effort of creating participant independent model if there is unlikely to be another participant to benefit from the common information model-based mapping. |
Message schema must be defined. | Participant is an external vendor’s System of Record. | Messages exchanged with an external vendor’s System of Record must be based on a defined system independent information model. | Provides decoupling between client system and external provider. |
Payload must be in JSON format. | All | The message payload must be in JSON format with a defined JSON schema. | Provides a consistent and easy to consume and manage format. |
Semantic transformation is the responsibility of the applications. | All | Publishers or subscribers must adopt the independently defined information model and schema. Syntactic transformation may be implemented by the integration layer. |
Provides decoupling between applications. Avoids embedding syntactic transformation mapping logic for each application within messaging system. |
Channel Adaptors for external systems must call external provider APIs via the DMZ Web Proxy | All | Internal channel adaptors consuming APIs of external systems must call the external provider APIs via the DMZ Web Proxy. | Provides secure decoupling between client and external providers. |
Integration Patterns – File
Information is exported from a source application to a file system as a file in a format such as CSV and picked up by the target system for processing. The file can be directly imported by the consuming file system or transported to a destination file system for the consuming system to retrieve. This style of integration is used where a bulk amount of information may be transferred as part of a batch process often executing at pre-defined times. File Transfer must not be used where API or messaging styles of integration are available and suitable for participant applications.
Patterns
Pattern |
Description | When to use | Considerations |
Point-to-point | An application creates one or more files to be consumed by a single target system. | Only one target is required to consume the file and it is highly unlikely any other target will require the file in the future. | |
One-to-Many | An application creates one or more files to be consumed by multiple target systems. | Multiple applications need to receive the file. The source system does not need to know who will consume the message. |
|
File Transport | Files are transferred between source and target system via an intermediary file transport system. | The source and target system do not have access to a shared file system. | |
Shared File System | Files are transferred between source and target system via a shared file system. | The source and target system have access to a shared file system. |
Constraints
Constraint |
Condition | Rules | Reasoning |
File format must be defined by the source system. | All | The file format must be defined by the source system. Target systems are responsible for any steps necessary for the parsing of the files including transformation and mapping. |
Avoid introducing an intermediary to perform file transformation. |
File transferred from internal systems to external systems must be transported by SFTP via the DMZ Web Proxy. | All | Files to be transported to an external system must be done so via the SFTP protocol. | Provides secure transport across organisation boundaries. |
Files transferred from an external system to an internal system must be transported by SFTP. | All | Files to be transported from an external system to an internal system must be done so via the SFTP protocol. | Provides secure transport across organisation boundaries. |
File formats must be either CSV, XML or JSON format. | All | The format of files transferred between source and target systems must be either CSV, XML or JSON. | Provides a consistent, compressible and easy to consume and mange format. |
Application Architecture Styles and Patterns
Microservices
In a microservices application architecture style an application is composed of many discrete network-connected components termed microservices. Each component is a small application itself that implements a part of the overall application. They are independently developed, packaged, deployed, scaled and managed. This is in contrast to monolithic applications that are developed as a single application that is packaged and deployed as a single unit.
Application Boundary
In order to provide some level of organisational alignment in terms of ownership and accountability, a collection of microservices may be logically grouped to form an application boundary. The application boundary may align to a domain or subdomain, defined by a bounded context through Domain Driven Design. Within this grouping a single or small selection of microservices may be exposed as service interfaces for consumption outside the domain/subdomain. The service interfaces may be API or messaging based. Some service interfaces may be exposed to external parties via an external facing API gateway or even exposed internally via an internal API gateway as managed APIs. Within an application boundary, microservice to microservice communication may be established through a service mesh under a cloud deployment environment where the service mesh provides capabilities such as service discovery and load balancing.
Ideally microservices should be independent, with their own persisted data where appropriate and not relying on calling downstream services in order to fulfil their responsibilities. However, there are cases where some microservices do integrate with other packaged applications or microservices some of which may be provided by external parties.
Co-existing with packaged applications
Packaged applications are typically implemented as monolithic applications. Even though their internal structure may be divided as modules that communicate through some form of inter-process communication or internal messaging system. They are more or less deployed as a single deployment unit and require a vendor to incorporate changes through a re-deployment of the entire package as a whole or through patches. Microservices and packaged applications may co-exist simple through decisions around the allocation of domain responsibilities and associated service composition.
A packaged solution may be responsible for an entire domain of which it provides one or more service interfaces as part of its bounded context. In these cases, an adaptor is often used as a façade to avoid directly coupling to the packaged application’s specific interface. This provides a level of protection from having to change consumer integrations if the packaged application is eventually changed. A packaged application may also be “hollowed out” where certain modules are disabled and bypassed, or it lacks some capability that may be provided by one or more custom built microservices. The microservices complement the packaged application and collectively they form the logical application represented by the dotted bounded box in the diagram below. The packaged application could expose an interface as of which the microservice consumes. The microservice’s interface would be exposed a business API at the application boundary.
The diagram below illustrates a generalised example of an application architecture that comprises applications integration through the invocation of APIs and/or event based.
Figure 2 - Packaged Application & Microservices Architecture Example
Microservices Patterns
The patterns defined in the table below provide a refence for commonly used arrangements of microservices with their associated consumers/providers. Whilst a persistent storage is included with each pattern and is typical of an ideal microservice it does not mandate the need for one as some microservices may not need to hold state.
There are a number of microservice implementation patterns however the focus of this section is around the integration between the microservices and consumers/provider. The purpose is to clarify the options for how they are arranged and highlight areas where data transformation is required and where it should be implemented.
Other microservice implementation patterns include:
- Service Discovery
- External Configuration
- Database per Service
- Distributed Tracing
- Health Check
- Circuit Breaker
- Blue-Green Deployment
Microservice Pattern – API consumer with persistence
- Consumer initiates communication through an API call directly with the microservice.
- Microservice interface exposes defined common information model, that is, it is not specific to any packaged solution information model. A custom built microservice API information model may be driven by the needs of the consumer.
- The consumer is typically custom developed as it does not require transformation to map to its own information model.
- Consumer may submit data or request data. In some cases, submitting data will return a result with data.
- This is an API style of integration following a request/response or request/acknowledge pattern.
- The microservice preforms a function following business rules.
- The microservice state is persisted in a storage component such as a database (e.g. SQL or NoSQL).
- The microservice is independent. Everything it requires to operate is contained within its runtime and linked persistent store.
Event processing with persistence
- Microservice subscribers to events received via a messaging system (e.g. IBM MQ, Rabbit MQ, Kafka)
- Microservice performs a function following business rules.
- As a result of executing its function, the microservice may publish a message via a messaging system.
- The microservice state is persisted in a storage component such as a database (e.g. SQL or NoSQL).
- The microservice is independent. Everything it requires to operate is contained within its runtime and linked persistent store.
- No data transformation is required.
Downstream Provider
- Microservice is dependent on a downstream provider.
- Microservice calls provider API directly and performs any necessary mapping to its own information model internally.
- Provider is a strategic component and is unlikely to be replaced, thus not requiring a facade or abstraction layer.
Downstream Provider Adaptor
- Microservice is dependent on a downstream provider.
- Provider may be replaced in the future. In order to protect impact of replacing provider, an abstraction component is implemented as a provider adaptor. This allows for the majority of code within the microservice to remain unchanged.
- The adaptor provides transformation from provider specific interface and information model to the generalised common information model supported within the microservice.
Consumer Adaptor
- Consumer requires transformation of Microservice API data model to its own information model with semantic and/or syntactic transformation and some level of business logic/rules.
- Where it is not viable to implement transformation within consumer application run-time a consumer adaptor may be developed. The adaptor would be developed by the consumer application team and be deployed alongside the application either within the runtime or outside.
- If it is not viable for the consumer application team to implement the consumer adaptor it can be developed by another team. The consumer adaptor is an independent component that logically remains part of the consumer application boundary but would be deployed independently of the consumer application.
Event-Driven Architecture and Event Based Patterns
In an event-driven architecture, applications interact by producing and consuming events. An event is an immutable notification of the change of state of a business entity or user action within an application. One or more applications may subscribe to events of interest. Events are typically communicated via a messaging system. A number of application architecture patterns may be built upon events including:
- Events – basic form of communicating events between applications via a messaging system and typically does not persist events in the long term.
- Event Streams – a continuous flow of events that may be used to derive valuable business insights utilising event processing analysing, combining and enriching event data from which a subsequent stream may be derived, or an action may be performed.
- Clickstreams – events representing user interactions with a user interface including clicks, mouse-movements and gestures that may be analysed to gain a deeper understanding of user behaviour. Analysis may be offline or in real-time that results in actions.
- CQRS – Command Query Responsibility Segregation establishes different models for reading and writing information, gaining the opportunity to independently optimise each path. A combination of API style integration (for reads) and Messaging style (for writes, in the form of commands) are typically used with this approach.
- Event Sourcing – each change of state of a business entity is stored as an immutable event from which an aggregate may be formed by reading back the events in a sequence to derive the final representation.
Events
An event may be transferred between applications using an asynchronous, messaging style of integration following a publish-subscribe pattern. The level of event detail may vary within the message payload. The publishing application is not aware of the consuming applications and the consuming applications are not aware of the publisher. This provides the basis of decoupling between the applications. The messaging system does not provide a long-term persistence of the messages but may provide an optional persistence to facilitate delivery assurance in case of a breakdown in communication. Once a message is consumed by the subscribers the message is typically removed from the messaging system. It is the responsibility of the subscribers to persist and/or perform the necessary action upon receiving the event.
The diagram below illustrates an application publishing an event (or emitting an event) to a topic through a messaging system. One or more applications may subscribe to the topic and receive the event.
Figure 3 - Application Architecture - Events Pattern
Command Query Responsibility Segregation (CQRS)
In separating the read and write models CQRS requires a mechanism to provide updates between them. This can be achieved through the use of an asynchronous messaging style of integration following a point-to-point pattern or publish/subscribe pattern. A command may be submitted via a synchronous API style o integration following a request/response pattern to update the write-optimised data store. Alternatively, an event may also be submitted to update an event store. When the data or event store are updated an event is emitted comprising the change details from which a read optimised data store will receive. The read-optimised store will persist the change in a materialised view appropriate for supporting queries. An application may perform a query against the read optimised store using an API style of integration following a request/response pattern.
Figure 4— Application Architecture - CQRS Pattern
Event Sourcing
An event sourced system persists a sequence of events rather than repeatedly overwriting a single state. The state is kept in-memory and is updated by events generated as a consequence of processing commands. A command may be submitted via a synchronous API style of integration following the request/response pattern where it is checked if it can be applied. If it can an event is created from which the state is changed. The event is persisted in an event journal and published to a topic using an asynchronous message style of integration following a publish/subscribe pattern from which other subscribers may also receive the event. The in-memory state machine may be recreated through replaying of the event history. Event Sourcing is typically complemented by the CQRS pattern to provide materialised views from the update events.
Figure 5 — Application Architecture - Event Sourcing Pattern
Event Driven Architecture – Synchronous and Asynchronous Combination Patterns
UI Interaction – API end to end
• UI Application makes API Backend for Frontend service that in turn makes API call to Microservice.
• User is waiting for response (e.g. submitted scheduled payment – you want to know it was successfully scheduled)
• Microservice either retrieves data from its own data store or calls a downstream provider via API call.
• Suitable for low volume scenarios.
• Direct coupling between components.
UI Interaction – API with message queue buffer
- UI Application makes API Backend for Frontend service that in turn makes API call to Microservice.
- User is waiting for response (e.g. submitted scheduled payment – you want to know it was successfully scheduled)
- Suitable for high volume scenarios where buffering is required.
- Microservice responsible for correlating response messages to request messages.
- Adapter required to pick messages off queue and make API calls to downstream provider.
- Messaging/Adapter/Queue components could be implemented using Integration Bus.
UI Interaction – API Polling
- UI Application makes API Backend for Frontend service that in turn makes API call to Microservice.
- UI Application receives immediate response from API with status “In progress”.
- UI Application does not block, user may continue to utilize other app features.
- Microservice processes request, calls downstream provider via API-to-messaging system adapter system.
- UI Application makes background API requests polling for status to determine if result of previous operation is completed.
- Microservice updates internally stored state to reflect completed operation.
UI Interaction – Async Update
- UI Application makes API Backend for Frontend service that in turn makes API call to Microservice.
- UI Application receives immediate response from API with status “In progress”.
- UI Application does not block, user may continue to utilize other app features.
- UI Application registers with Async Gateway using async technology such as Web Sockets, MQTT, socket.io.
- Microservice processes request, calls downstream provider via API-to-messaging system adapter system.
- UI Application receives response message via subscribed topic.
- Microservice also updates internally stored state to reflect completed operation.
- UI Application in future may retrieve stored state via API call.
UI Interaction – Assumed Success
- UI Application makes API Backend for Frontend service that in turn makes API call to Microservice.
- UI Application receives immediate response from API with status “Change Accepted”.
- UI Application does not block, user may continue to utilize other app features assuming change has been received.
- Microservice processes request, calls downstream provider via API-to-messaging system adapter system.
- Microservice only interested in failure messages otherwise it is assumed action performed successfully.
- Microservice updates state and initiates user communication of failure.
- Adapter publishes message to failure queue that microservice subscribes to.
Event Driven Architecture – Transactions
Transactions executed across microservices as part of a long running process can be implemented using the Saga pattern. The Saga pattern relies on each microservice performing a step in the process, updating its own data from which triggers the subsequent step to be completed by another microservice. There are two types of implementations for the Saga pattern: Choreography and Orchestration.
Transaction Pattern – Choreography
- There is no central coordinator.
- Each service operates independently.
- The sequence is inherent in the predefined events and system responsibilities.
- Changes within one microservice may be marked as temporary until a confirmation event is received later to ensure consistency across states.
- Changing the process requires changes to potentially multiple services.
- Roll back requires separate event.
- Used where number of steps in process is low < 5.
- Risk of cyclic dependency.
Transaction Pattern – Orchestration
- Centralized controller (orchestrator). Could be implemented as:
- custom microservice
- BPM (headless)
- Custom microservice with embedded process engine.
- Packaged application
- The sequence is defined within the orchestrator.
- Orchestrator maintains running state.
- Changing the process requires changes only to orchestrator.
- Roll back managed by Orchestrator.
- Used where number of steps in process is high > 5.
Opinions expressed by DZone contributors are their own.
Comments