Learn what domain events are. When and why domain events should be used. • Learn how to model domain events as objects and when to create unique identifiers for domain events. • Learn a lightweight publish-subscribe pattern in Gamma et al. • Learn which components are used to publish events and which components are used to subscribe to events. • Learn why we need an event store. How to implement the event store and how to use it. • Learn how the ASA Ovation team can publish domain events to autonomous systems in different ways
When and why are domain events used?
1.1 define
Use domain events to model something that happens in a domain. This is a powerful modeling tool that you can’t put down. When using domain events, the first step is to define the different events.
Domain events are not defined in Domain-Driven Design. The model was proposed after the book was published. Current definition of domain events: events that occur in a domain that are of concern to domain experts. Activities occurring in a field are modeled as a series of discrete events. Each event is represented by a domain object… Domain events are part of the domain model and represent what happens in the domain. [Evans, Ref, P-20] one
Domain events will lead to further business operations, enabling business decoupling while also contributing to a complete business closed loop.
A domain event can be a step in a business process, such as a subsequent action triggered after an event occurs, such as an account locking action triggered by three consecutive incorrect password entries.
1.2 Identify domain events
- “If it happens… , then…”
- “When done… Please let me know…” (The notification here does not constitute an event in and of itself, but merely indicates that we need to notify the outside world.)
In these scenarios, if an event occurs that triggers further action, it is likely to be a domain event. Because domain events need to be published to external systems, such as to another bounded context. Because such an event is handled by the subscriber, it can have a profound impact on both local and remote contexts.
Why do domain events use final consistency instead of direct invocation of traditional SOA?
One rule of aggregation: You can only change a maximum of one aggregation instance in a transaction. so
- Other aggregation instances in the local bounded context can then be synchronized as domain events
- Used to align remote dependent systems with local systems. Decoupling local and remote systems also helps to improve the scalability of the services collaborating on both sides.
Aggregation creates and publishes events. Subscribers can store events and then forward them to remote subscribers, or forward them directly without storing them. Instant forwarding requires XA (two-phase commit) unless MQ shares the data store of the model.
Consider that during off-peak periods, batch processes typically perform some system maintenance work, such as removing expired objects, creating new objects to support new business requirements, or notifying users of important events. Such batch processes typically require complex queries and large transaction support. What happens if these batch processes are redundant? Can we simplify the system by capturing everything that happens in the system as an event and then publishing the event to subscribers? For sure! It eliminates complex queries from previous batch processes because we know exactly when something is happening, and the bounded context knows what to do next. When a domain event is received, the system processes it immediately. The original batch centralized processing process can be dispersed into many small-grained processing units, so that business requirements can be met more quickly and users can perform next operations in a timely manner.
Domain-event-driven design can cut off strong dependencies between domain models. After the event publishing is completed, the publisher does not need to care about whether the event processing of the subsequent subscribers is successful or not to realize the decoupling of the domain model and maintain the independence and data consistency of the domain model. When domain models are mapped to microservices architecture, domain events decoupled microservices, and data between microservices does not require strong consistency, but is based on the ultimate consistency of events.
Triggering domain events
Domain events are triggered by external commands. The trigger command can be a domain service or a method or behavior of an entity.
The use of trigger events
Synchronizes database data incrementally through canal and triggers calls to generate events by listening for data changes to specific tables. This helps to decouple mainstream services, improve maintenance and readability. (Of course, the specific operation of generating events is still placed in the microservice of the corresponding domain, and the Canal listening consumer terminal can be understood as a task scheduling platform). The implementation logic is relatively simple.
So how do you deal with events in different domains?
3 Handle domain events
3.1 Inside microservices
Domain events occur between aggregations within microservices. After the occurrence of domain events, event entity construction and event data persistence are completed. Publisher aggregations publish events to event bus, and subscribers receive event data to complete subsequent business operations.
Most of the integration of events within microservices occurs in the same process, and the process itself can control the transaction. However, if an event updates multiple aggregations at the same time, according to the principle of updating only one aggregation at a time, the event bus can be considered.
Application services within microservices can be accessed through service invocation through service orchestration and composition across aggregation, which is usually applied to scenarios requiring high real-time performance and data consistency. This process uses distributed transactions to ensure that both publisher and subscriber data are updated successfully.
Within microservices, it is not recommended to use domain events less, but rather the event bus less. DDD manages data by aggregation. If multiple aggregated data in the same microservice is modified in one operation, ensure data consistency between these aggregated data. To decoupage different aggregations, a distributed transaction or event bus is needed, which is not convenient for managing the relationship between services and data, and distributed transaction technologies such as Saga can be used. In summary, ensure business rules and data consistency across different aggregations.
3.2 Microservice room
Domain events across microservices enable business collaboration between different bounded contexts or domain models, primarily to decouple and reduce real-time service access pressure between microservices.
Domain events occur more frequently between microservices and the event handling mechanism is more complex. Cross-microservice events facilitate the direct flow of business processes or data between different subdomains or microservices.
Event mechanisms across microservices consider event building, publish and subscribe, event data persistence, MQ, and even event data persistence may need to consider the introduction of distributed transactions.
The access between microservices can also be directly invoked by application services to achieve real-time access to data and services. The disadvantage is that the simultaneous change of data across microservices requires the introduction of distributed transactions. Distributed transactions can affect system performance, increase coupling between microservices, and avoid them as much as possible.
5 domain event design
5.1 Build and Release
Basic attributes
At least include the following:
- Event unique identifier (globally unique, events can be passed unambiguously across multiple bounded contexts)
- Time of occurrence
- The event type
- The event source
That is, the data that mainly records the event itself and the background of the event.
Business attribute
Business data is recorded at the time of the event, which is transferred to subscribers with the event for subsequent business operations.
Event base attributes and business attributes together constitute event entities that depend on the aggregation root. After a domain event occurs, the business data in the event is not modified, so the business data can be stored as serialized value objects, a storage format that is easier to parse and retrieve in messaging middleware.
To ensure a uniform event structure, it is common to create a base class for the event, and subclasses can inherit the extension themselves. Since events don’t have much business activity, implementation is generally simple.
Event entities are built and persisted before an event is published. Service data of event entities are recommended to be released on demand to avoid unnecessary service information leakage.
Event Publishing Mode
- It can be published to the event bus or MQ through application services or domain services
- Incremental event data can also be retrieved from event tables using timer or database log capture techniques and published to MQ
5.2 Persisting Event Data
meaning
- Data reconciliation between systems
- Implement audits of publisher and subscriber event data
In the event of MQ or subscriber system outages or network outages, subsequent service flows can continue after the problem is resolved to ensure data consistency. After all, although MQ has persistence capabilities, something goes wrong in the middle or after the data is subscribed to and before it is processed, requiring data reconciliation, which makes it impossible to find the published and processed versions of the data. Key business data is recommended for warehousing.
Implementation scheme
- Persisting event tables to local business DB, using local transactions to ensure consistency between business and event data
- Persist to the shared event DB. Service and event DBS are not in the same DB, and their data persistence operations are cross-DB. Therefore, distributed transactions are required to ensure strong consistency between service and event data, which affects system performance
5.3 EventBus
meaning
Implement domain events between aggregations within the same microservice, providing services such as event distribution and reception. Is an in-process model that traverses the subscriber list between aggregations within microservices, passing data synchronously or asynchronously.
Because the event bus is relatively easy to configure within the microservice within the same process, it can be configured as either asynchronous or synchronous. If it is synchronous, there is no need to drop the library. Minimizing domain events between aggregations within microservices is recommended as it can increase development complexity. Events between microservices, after the event data is dropped into the repository, are published directly to MQ through application services.
Event Distribution Process
- If there are subscribers within the micro-service (other aggregations), it will be distributed directly to the designated subscribers
- Subscribers outside the microservice, save event data to an event library (table) and send it asynchronously to MQ
- If there are both internal and external subscribers to the microservice, the event message is first distributed to the internal subscribers, saved to the event library (table), and then asynchronously sent to MQ
5.4 the MQ
MQ is used for most domain events across microservices, enabling event publishing and subscription across microservices. Although MQ has persistence capabilities of its own, problems occur in the middle or after the data is subscribed to and before processing, and data reconciliation is required, making it impossible to find the published and processed versions of the data. Key business data is recommended for warehousing.
5.5 Receiving && Processing
The microservice subscriber uses a listening mechanism at the application layer to receive event data in MQ, and after the event data is persisted, further business processing can begin. Domain event processing can be implemented in domain services.
- Whether the event was consumed successfully (the consumer successfully received the message or the consumer successfully processed the business), how to notify the message producer?
Because the event publisher has the raw persistent data of the event entity, the event subscriber also has the persistent data it receives. Generally, you can check data consistency by checking accounts periodically.
- In the case of final consistency, if an error occurs on the event consuming end and consumption fails, but the previous business is successful. Although the event dB is recorded, how to deal with the subsequent process? Is there any manual intervention? If manual intervention and then solve, will front-end users see inconsistent data, bad experience?
Failure should be rare. The failed message can be retried several times. If this cannot be resolved, the data in question can only be placed in a problem data area for manual resolution. Of course, you have to make sure that the data is sequential and not overwrite the generated data.
Publishers generally do not wait for feedback from subscribers. The publisher has a table of published events, and the subscriber has a table of consumption events, which can be reconciled to find problem data.
management
There are many domain events for large systems:
- Reconcile the source and destination data, find and identify abnormal data in the process
The asynchronous mode is generally the mechanism of regular reconciliation between the active end and the destination end. For example, the adoption of similar financial correction. If the asynchronous data in the event table between publication and subscription is found to be faulty and needs to be rolled back, the corresponding code will process the data. However, the business logic will be different in different scenarios and the processing method will be different. Some even need to turn to manual processing.
- When abnormal data is found, a corresponding processing mechanism should be in place
- Choose the technology suitable for your scenario to ensure proper data transmission
6 summarizes
In the design of domain events, we should focus on domain events, use domain events to drive the flow of business, try to adopt event-based final consistency, reduce the pressure of direct access between micro-services, realize the decoupling between micro-services, and maintain the independence of domain model and data consistency.
The domain event-driven mechanism enables a publisher with N subscribers pattern, which is essentially impossible in traditional direct service invocation designs.
Domain event v.SCqRS
CQRS is primarily intended for read-write separation, separating query functions without domain models from commands. The main purpose of domain events is the decoupling of microservices. In the continuous business process, the next business process is completed in an asynchronous way, and the direct connection between microservices is reduced. What they have in common is the interaction and separation of data from source to destination through message-oriented middleware.
If you simply don’t want to use domain events, aggregations can also be coordinated and interworked through the application layer. Application services are services on top of all aggregations and are responsible for composing and orchestrating services, as well as coordinating them.
reference
- Implementing Domain-Driven Design
- Domain-driven Design