Kiến Trúc Hướng Sự Kiện (Event-Driven Architecture)
Trong bức tranh kiến trúc phần mềm hiện đại, Kiến Trúc Hướng Sự Kiện (Event-Driven Architecture - EDA) và Domain-Driven Design (DDD) là hai khái niệm thường xuyên xuất hiện cùng nhau. Tuy nhiên, cũng chính vì sự phổ biến đó mà rất nhiều kỹ sư thường nhầm lẫn giữa chúng — đặc biệt là đánh đồng kiến trúc hướng sự kiện với mẫu hình Event Sourcing.
Thực tế, Event Sourcing và Event-Driven Architecture là hai mẫu hình hoàn toàn khác biệt nhau về cả mục đích lẫn phạm vi:
- Event Sourcing: Là một mẫu hình chiến thuật nội bộ nhằm lưu trữ trạng thái của một Aggregate dưới dạng chuỗi các biến cố quá khứ, nằm trọn vẹn bên trong ranh giới của một Bounded Context.
- Event-Driven Architecture: Là một phong cách kiến trúc hệ thống định nghĩa cách thức các thành phần hoặc các Bounded Context giao tiếp, tích hợp và phối hợp bất đồng bộ với nhau xuyên qua các ranh giới.
Trong chương này, chúng ta sẽ phân tích bản chất của EDA, phân loại rõ ràng 3 kiểu thông điệp sự kiện cốt lõi, vạch trần những sai lầm chết người dẫn đến "Bãi bùn phân tán" (Distributed Big Ball of Mud), và rút ra các nguyên tắc thực nghiệm để thiết kế nên những hệ thống hướng sự kiện linh hoạt, tự chủ và có khả năng chống chịu lỗi cao.
Kiến Trúc Hướng Sự Kiện Là Gì?
Theo cách giao tiếp truyền thống, các thành phần hệ thống thường tích hợp với nhau một cách đồng bộ (synchronously): Thành phần A gọi trực tiếp một API endpoint hoặc phương thức của Thành phần B và bị chặn (blocked) chờ đợi phản hồi. Mô hình này tạo ra sự phụ thuộc thời gian trực tiếp: nếu B bị sập hoặc nghẽn mạng, A sẽ lập tức bị ảnh hưởng theo.
Ngược lại, trong một hệ thống Event-Driven Architecture (EDA), các thành phần giao tiếp với nhau bằng cách phát đi và lắng nghe các sự kiện (events) một cách bất đồng bộ (asynchronously). Thay vì gọi trực tiếp các endpoint của nhau, các dịch vụ phát ra các thông điệp sự kiện để thông báo rằng: "Một điều gì đó có ý nghĩa vừa mới xảy ra trong miền nghiệp vụ của tôi!", như được minh họa trong Hình 15-1.
Các thành phần khác trong hệ thống quan tâm đến biến cố đó — gọi là các bên đăng ký (subscribers) — sẽ tự động tiếp nhận sự kiện và thực thi logic tương ứng của riêng mình. Bên phát sự kiện (publisher) không cần biết và không cần quan tâm có những ai đang lắng nghe mình; nó hoàn toàn được giải phóng khỏi sự phụ thuộc vào các bên tiêu thụ.
Sự Kiện (Event) Là Gì? Cấu Trúc Schema Của Sự Kiện
Về mặt kỹ thuật, một sự kiện là một bản ghi dữ liệu (data record) có thể được tuần tự hóa (serialized thành JSON, Protobuf, Avro...) và truyền tải qua nền tảng nhắn tin trung gian (như Apache Kafka, RabbitMQ, AWS SNS/SQS, Azure Event Hubs).
Một cấu trúc schema điển hình của một thông điệp sự kiện bao gồm hai phần chính: metadata (siêu dữ liệu định tuyến và nhận dạng) và payload (phần tải dữ liệu chứa thông tin thực sự được truyền tải).
{
"type": "delivery-confirmed",
"event-id": "14101928-4d79-4da6-9486-dbc4837bc612",
"correlation-id": "08011958-6066-4815-8dbe-dee6d9e5ebac",
"delivery-id": "05011927-a328-4860-a106-737b2929db4e",
"timestamp": 1615718833,
"payload": {
"confirmed-by": "17bc9223-bdd6-4382-954d-f1410fd286bd",
"delivery-time": 1615701406
}
}
Phần payload của sự kiện không chỉ chứa thông tin được truyền đạt, mà cấu trúc và ý đồ của nó còn định hình nên loại sự kiện (event type). Việc lựa chọn loại sự kiện nào để giao tiếp là một trong những quyết định thiết kế quan trọng nhất định đoạt sự thành bại của một kiến trúc phân tán.
Ba Loại Sự Kiện Cốt Lõi (Types of Events)
Trong một hệ thống hướng sự kiện, tất cả các thông điệp sự kiện đều có thể được phân loại chuẩn xác vào một trong ba loại chính:
- Thông Báo Sự Kiện (Event Notification)
- Chuyển Giao Trạng Thái Qua Sự Kiện (Event-Carried State Transfer - ECST)
- Sự Kiện Miền (Domain Event)
1. Thông Báo Sự Kiện (Event Notification)
Một Event Notification là một thông điệp ngắn gọn thông báo rằng vừa có một thay đổi xảy ra trong miền nghiệp vụ mà các thành phần khác có thể muốn phản hồi lại (ví dụ: PaycheckGenerated, CampaignPublished).
Đặc điểm nhận dạng cốt lõi của Event Notification là tính súc tích tối đa (succinct): mục đích duy nhất của nó là báo hiệu cho các bên quan tâm, chứ nó không hề mang theo đầy đủ thông tin để bên nhận có thể xử lý xong xuôi ngay lập tức.
{
"type": "paycheck-generated",
"event-id": "537ec7c2-d1a1-2005-8654-96aee1116b72",
"delivery-id": "05011927-a328-4860-a106-737b2929db4e",
"timestamp": 1615726445,
"payload": {
"employee-id": "456123",
"link": "/paychecks/456123/2021/01"
}
}
Trong ví dụ trên, sự kiện chỉ báo rằng một phiếu lương đã được tạo cho nhân viên 456123. Nếu bên nhận muốn biết chi tiết về số tiền hay các khoản khấu trừ thuế, họ bắt buộc phải dùng đường dẫn link để thực hiện một truy vấn đồng bộ ngược lại dịch vụ phát ra nó (Hình 15-2).
Cách tiếp cận này rất giống với Hệ thống Cảnh báo Khẩn cấp Không dây (Wireless Emergency Alert - WEA) tại Mỹ hoặc EU-Alert tại Châu Âu (Hình 15-3): các tháp phát sóng gửi đi một tin nhắn ngắn gọn (tối đa 360 ký tự) tới điện thoại của người dân để báo hiệu nguy hiểm. Bạn biết có sự cố xảy ra, nhưng bạn phải chủ động mở tivi hoặc đài báo để xem chi tiết tình hình.
- Bảo mật thông tin (Security): Tránh việc phát tán dữ liệu nhạy cảm (như tiền lương, thông tin y tế) trôi nổi trên hạ tầng nhắn tin dùng chung. Bên nhận phải có quyền xác thực và phân quyền hợp lệ mới được truy vấn chi tiết.
- Tính đồng thời & tránh dữ liệu lỗi thời (Concurrency & Freshness): Trong môi trường bất đồng bộ, dữ liệu đính kèm sự kiện có thể đã bị cũ khi tới tay bên nhận. Việc truy vấn trực tiếp giúp lấy được trạng thái mới nhất tuyệt đối tại thời điểm xử lý, đồng thời có thể áp dụng khóa bi quan (pessimistic locking) để ngăn chặn xung đột giữa các bên tiêu thụ đồng thời.
2. Chuyển Giao Trạng Thái Qua Sự Kiện (Event-Carried State Transfer - ECST)
Trái ngược hoàn toàn với Event Notification, Event-Carried State Transfer (ECST) là thông điệp mang theo toàn bộ dữ liệu phản ánh sự thay đổi trạng thái của thực thể. Bên nhận không cần phải gọi ngược lại bên phát mà có thể cập nhật trực tiếp dữ liệu vào kho lưu trữ nội bộ của mình.
ECST thường xuất hiện dưới hai biến thể:
Biến thể 1: Bản chụp toàn phần (Full State Snapshot):
{
"type": "customer-updated",
"event-id": "6b7ce6c6-8587-4e4f-924a-cec028000ce6",
"customer-id": "01b18d56-b79a-4873-ac99-3d9f767dbe61",
"timestamp": 1615728520,
"payload": {
"first-name": "Carolyn",
"last-name": "Hayes",
"phone": "555-1022",
"status": "follow-up-set",
"follow-up-date": "2021/05/08",
"birthday": "1982/04/05",
"version": 7
}
}
Biến thể 2: Bản cập nhật các trường bị thay đổi (Delta Update): Khi cấu trúc dữ liệu quá lớn, thông điệp ECST có thể chỉ chứa những trường dữ liệu thực sự bị sửa đổi kèm theo số phiên bản (version):
{
"type": "customer-updated",
"event-id": "6b7ce6c6-8587-4e4f-924a-cec028000ce6",
"customer-id": "01b18d56-b79a-4873-ac99-3d9f767dbe61",
"timestamp": 1615728520,
"payload": {
"status": "follow-up-set",
"follow-up-date": "2021/05/10",
"version": 8
}
}
Về mặt khái niệm, sử dụng ECST chính là một cơ chế nhân bản dữ liệu bất đồng bộ (asynchronous data replication). Luồng sự kiện này cho phép các bên tiêu thụ duy trì một bản sao bộ nhớ đệm (local cache) về trạng thái của thực thể để làm việc độc lập.
Cách tiếp cận này mang lại khả năng chống chịu lỗi vượt trội (fault tolerance): bên nhận vẫn tiếp tục hoạt động trơn tru ngay cả khi dịch vụ bên phát bị sập nguồn hoàn toàn! Nó cũng là vũ khí đắc lực để tối ưu hiệu năng cho các thành phần như Backend for Frontend (BFF) — nơi cần tổng hợp dữ liệu từ nhiều nguồn khác nhau mà không phải thực hiện hàng loạt lời gọi mạng tốn kém mỗi khi có truy vấn (Hình 15-4).
3. Sự Kiện Miền (Domain Events)
Loại sự kiện thứ ba chính là Domain Event mà chúng ta đã làm quen ở Chương 6 và Chương 7. Sự kiện miền nằm ở khoảng giao thoa giữa Event Notification và ECST: nó vừa mô tả một sự kiện quan trọng trong miền nghiệp vụ, vừa mang theo dữ liệu chi tiết mô tả biến cố đó. Tuy nhiên, Domain Event có những điểm khác biệt mang tính bản chất:
- Khác với Event Notification: Domain Event mang đầy đủ thông tin về sự cố nghiệp vụ vừa diễn ra; bên nhận không cần phải gọi API ngược lại để hỏi thêm. Quan trọng hơn, ý đồ mô hình hóa (modeling intent) là khác nhau: Event Notification được sinh ra để phục vụ việc tích hợp hệ thống bên ngoài, còn Domain Event được sinh ra để mô tả chính xác những gì xảy ra trong bài toán nghiệp vụ nội bộ — nó có giá trị ngay cả khi không có bất kỳ hệ thống bên ngoài nào đăng ký lắng nghe!
- Khác với ECST: Dữ liệu trong Domain Event mô tả hành động nghiệp vụ vừa xảy ra chứ không phải là bản chụp trạng thái thực thể. Không một Domain Event đơn lẻ nào được thiết kế để cung cấp đầy đủ dữ liệu cho bên ngoài cache lại toàn bộ thực thể.
So Sánh Trực Quan: Bài Toán Ghi Nhận Kết Hôn
Hãy xem xét một ví dụ thực tế vô cùng trực quan để phân biệt rạch ròi ba loại sự kiện này: làm thế nào để mô hình hóa biến cố "Một người đăng ký kết hôn"?
// 1. EVENT NOTIFICATION
eventNotification = {
"type": "marriage-recorded",
"person-id": "01b9a761",
"payload": {
"person-id": "126a7b61",
"details": "/01b9a761/marriage-data"
}
};
// 2. EVENT-CARRIED STATE TRANSFER (ECST)
ecst = {
"type": "personal-details-changed",
"person-id": "01b9a761",
"payload": {
"new-last-name": "Williams"
}
};
// 3. DOMAIN EVENT
domainEvent = {
"type": "married",
"person-id": "01b9a761",
"payload": {
"person-id": "126a7b61",
"assumed-partner-last-name": true
}
};
Hãy phân tích sự khác nhau:
marriage-recorded(Event Notification): Chỉ thông báo rằng người này đã kết hôn và đính kèm đường dẫndetails. Bên ngoài muốn biết thông tin hôn phối bắt buộc phải click vào link.personal-details-changed(ECST): Chỉ mô tả trạng thái thay đổi — họ của người này đã đổi thành "Williams". Thông điệp này hoàn toàn không giải thích lý do tại sao họ thay đổi (do kết hôn, ly hôn, hay đổi tên theo sở thích?).married(Domain Event): Mô hình hóa sát sao nhất với bản chất của biến cố nghiệp vụ: người này đã kết hôn với ai và có chọn mang họ của bạn đời hay không.
Thiết Kế Tích Hợp Hướng Sự Kiện
Như chúng ta đã nhấn mạnh trong suốt cuốn sách: thiết kế phần mềm chủ yếu là câu chuyện về các ranh giới. Ranh giới quyết định cái gì nằm bên trong, cái gì nằm bên ngoài, và điều gì được phép băng qua ranh giới.
Trong một hệ thống EDA, các sự kiện là những phần tử thiết kế hạng nhất (first-class design elements). Việc lựa chọn loại sự kiện chuẩn xác là yếu tố quyết định hệ thống của bạn sẽ được tháo rời (decoupled) linh hoạt hay sẽ bị trói chặt (coupled) thành một mớ hỗn độn.
Cạm Bẫy: "Bãi Bùn Phân Tán Khổng Lồ" (Distributed Big Ball of Mud)
Nhiều người ngây thơ tin rằng: cứ nhét Message Broker vào và bắn sự kiện đi khắp nơi là hệ thống sẽ tự động "loose coupling" (ghép nối lỏng). Đó là một ảo tưởng tai hại! Hãy cùng mổ xẻ một câu chuyện có thật trong Hình 15-5.
Trong hệ thống này:
- Bounded Context CRM được triển khai bằng Event-Sourced Domain Model.
- Khi ngữ cảnh Marketing cần tích hợp, nhóm quyết định tận dụng "tính linh hoạt" của Event Sourcing: cho Marketing đăng ký lắng nghe toàn bộ các Domain Events nội bộ của CRM và tự xây dựng phép chiếu (projection) thành bảng dữ liệu khách hàng.
- Khi ngữ cảnh AdsOptimization ra đời, nhóm cũng làm tương tự: đăng ký toàn bộ Domain Events của CRM để chiếu ra cùng một cấu trúc bảng dữ liệu khách hàng y như Marketing!
- Ngữ cảnh Reporting cần lấy kết quả tính toán từ AdsOptimization. Nhưng vì cả hai đều lắng nghe cùng sự kiện từ CRM, để đảm bảo Reporting không chạy trước khi AdsOptimization tính xong, đội ngũ đã "sáng tạo" ra một giải pháp: cho Reporting hoãn lại (delay) 5 phút sau khi nhận sự kiện mới chạy!
Thiết kế này là một cơn ác mộng kiến trúc toàn diện. Hãy cùng vạch trần 3 loại ghép nối chết người đang tàn phá hệ thống này.
1. Ghép Nối Thời Gian (Temporal Coupling)
AdsOptimization và Reporting bị trói chặt vào nhau về mặt thời gian: chúng phụ thuộc vào thứ tự thực thi nghiêm ngặt. AdsOptimization buộc phải tính toán xong thì Reporting mới được phép đọc.
Việc cài đặt "delay 5 phút" là một trò lừa dối ngây thơ và không hề giải quyết được tận gốc vấn đề:
- Nếu AdsOptimization bị quá tải và mất 6 phút để xử lý? → Dữ liệu của Reporting sẽ lập tức bị sai lệch!
- Nếu mạng bị trễ hoặc nghẽn hàng đợi thông điệp gửi tới AdsOptimization? → Thứ tự thực thi bị đảo lộn hoàn toàn!
- Nếu dịch vụ AdsOptimization bị sập đột ngột? → Reporting vẫn cứ thế chạy với dữ liệu rác!
2. Ghép Nối Chức Năng (Functional Coupling)
Cả Marketing và AdsOptimization đều đăng ký lắng nghe cùng một tập Domain Events từ CRM và cùng tự viết logic để chuyển đổi thành một bản chụp dữ liệu khách hàng.
Nói cách khác, logic nghiệp vụ chiếu hình (projection logic) đã bị nhân bản ở hai Bounded Context khác nhau. Mỗi khi có một yêu cầu nghiệp vụ thay đổi cách hiển thị dữ liệu khách hàng, cả hai đội ngũ đều phải đồng thời chỉnh sửa mã nguồn và deploy cùng lúc! Đó chính là định nghĩa chuẩn xác của ghép nối chức năng (Functional Coupling).
3. Ghép Nối Triển Khai (Implementation Coupling)
Đây là loại ghép nối tinh vi và nguy hiểm nhất. Vì Marketing và AdsOptimization đăng ký trực tiếp vào các Domain Events nội bộ của CRM, nên mọi chi tiết triển khai bên trong CRM đều bị lộ ra ngoài:
- Nếu nhóm CRM thêm một Domain Event mới hoặc đổi tên trường trong schema sự kiện, logic của cả Marketing và AdsOptimization sẽ lập tức lăn ra lỗi (crash)!
- Ngay cả khi nhóm CRM bổ sung một sự kiện nghiệp vụ mới mà hai dịch vụ kia phớt lờ không cập nhật theo, dữ liệu mà họ chiếu ra sẽ bị sai lệch trạng thái một cách âm thầm (silent inconsistency)!
Tái Cấu Trúc Tích Hợp Hệ Thống
Việc tưới đẫm sự kiện lên một hệ thống không hề tự động làm cho nó trở nên lỏng lẻo hay bền bỉ. Để cứu vãn hệ thống, chúng ta áp dụng các nguyên tắc DDD để tái cấu trúc lại toàn bộ, như minh họa trong Hình 15-6:
- Xử lý Ghép nối Triển khai & Chức năng: Đưa toàn bộ logic chiếu hình (projection) về đóng gói bên trong CRM. CRM áp dụng mẫu Open-Host Service và phát ra các thông điệp ECST nằm trong Published Language công khai của nó. Marketing và AdsOptimization chỉ việc tiêu thụ thông điệp ECST này mà không cần biết CRM dùng Event Sourcing hay Relational Database bên trong.
- Xử lý Ghép nối Thời gian: Xóa bỏ hoàn toàn trò "delay 5 phút"! Thay vào đó, khi AdsOptimization hoàn tất tính toán, chính nó sẽ phát ra một thông điệp Event Notification để kích hoạt Reporting sang lấy dữ liệu. Mối quan hệ nhân quả được bảo đảm tuyệt đối về mặt kiến trúc.
Các Nguyên Tắc Thực Nghiệm Thiết Kế EDA (Design Heuristics)
Để xây dựng các hệ thống hướng sự kiện bền bỉ, hãy luôn khắc cốt ghi tâm 3 nguyên tắc thực nghiệm vàng dưới đây:
1. Luôn Chuẩn Bị Cho Tình Huống Xấu Nhất (Assume the Worst)
Như cựu CEO của Intel, Andrew Grove, từng viết trong cuốn sách nổi tiếng: "Chỉ những kẻ hoang tưởng mới sống sót" (Only the Paranoid Survive). Hãy mang tư duy hoang tưởng đó vào thiết kế hệ thống phân tán:
- Đường truyền mạng chắc chắn sẽ bị chậm hoặc đứt kết nối.
- Máy chủ chắc chắn sẽ sập vào những thời khắc bất tiện nhất.
- Các thông điệp sự kiện chắc chắn sẽ đến sai thứ tự.
- Các thông điệp sự kiện chắc chắn sẽ bị gửi trùng lặp nhiều lần.
- Và định mệnh trớ trêu: tất cả những thảm họa này sẽ xảy ra thường xuyên nhất vào các kỳ nghỉ lễ và đêm cuối tuần!
Từ "Driven" trong Event-Driven Architecture có nghĩa là toàn bộ hệ thống của bạn sống còn dựa trên việc truyền tải thông điệp. Đừng bao giờ mang tâm lý "mọi chuyện rồi sẽ ổn". Hãy bảo vệ hệ thống bằng các mẫu hình vững chắc:
- Sử dụng Outbox Pattern để đảm bảo việc lưu dữ liệu và phát sự kiện luôn diễn ra trong một giao dịch nguyên tử, không bao giờ làm mất thông điệp.
- Bên nhận phải được thiết kế để có khả năng khử trùng lặp (deduplication) và xắp xếp lại thứ tự các thông điệp bị đảo lộn (idempotent consumers).
- Sử dụng mẫu hình Saga hoặc Process Manager khi điều phối các quy trình nghiệp vụ xuyên suốt nhiều Bounded Context đòi hỏi các hành động bù trừ (compensating actions).
2. Phân Định Rạch Ròi Sự Kiện Công Khai & Sự Kiện Nội Bộ
Hãy hết sức cẩn trọng khi phát các Domain Events ra thế giới bên ngoài. Sự kiện là một phần không thể tách rời của giao diện công khai (public interface) của Bounded Context.
- Sự kiện nội bộ (Private Events): Dành riêng cho logic nội tại của Bounded Context (chẳng hạn như các sự kiện lưu trong Event Store của Aggregate). Chúng được phép thay đổi tự do theo sự tiến hóa của mã nguồn.
- Sự kiện công khai (Public Events): Phải là một phần của Published Language theo mẫu Open-Host Service. Chúng phải được thiết kế tinh gọn, mang tính hợp đồng bền vững và không để lộ chi tiết cấu trúc dữ liệu nội bộ.
3. Đánh Giá Yêu Cầu Nhất Quán Dữ Liệu
Hãy dựa vào mức độ đòi hỏi về tính nhất quán của bên tiêu thụ để lựa chọn loại sự kiện chuẩn xác:
| Yêu Cầu Nhất Quán | Loại Sự Kiện Phù Hợp | Cơ Chế Hoạt Động |
|---|---|---|
| Nhất quán cuối cùng (Eventual Consistency) chấp nhận được độ trễ nhỏ | Event-Carried State Transfer (ECST) | Bên nhận duy trì một bản sao cache cục bộ, tự động cập nhật khi có bản chụp trạng thái mới gửi đến. |
| Bắt buộc đọc trạng thái mới nhất tuyệt đối (Read-your-own-write / Latest state) | Event Notification + Truy Vấn Đồng Bộ | Sự kiện chỉ đóng vai trò tín hiệu kích hoạt; bên nhận ngay lập tức gọi API đồng bộ để lấy dữ liệu tươi mới nhất từ nguồn gốc. |
Tổng Kết Chương (Conclusion)
Chương này đã tiếp cận Kiến trúc Hướng Sự Kiện như một khía cạnh bản chất trong việc thiết kế giao diện công khai của các Bounded Context. Chúng ta đã cùng nhau làm sáng tỏ:
- Ba loại sự kiện cốt lõi: Event Notification (thông báo kích hoạt), Event-Carried State Transfer (nhân bản trạng thái), và Domain Event (mô hình hóa biến cố nghiệp vụ).
- Hiểm họa ghép nối: Sử dụng sai loại sự kiện sẽ làm suy thoái hệ thống thành một Bãi Bùn Phân Tán với 3 loại ghép nối độc hại: ghép nối thời gian, ghép nối chức năng và ghép nối triển khai.
- Sức mạnh kết hợp DDD và EDA: Tận dụng Published Language để nén sự kiện công khai, đóng gói phép chiếu vào bên phát, và xây dựng hệ thống với tư duy "luôn chuẩn bị cho điều tồi tệ nhất" để đạt được tính tự chủ và khả năng chịu lỗi cao độ.
Trong Chương 16: Data Mesh, chúng ta sẽ bước sang mảnh ghép cuối cùng của Phần IV: áp dụng các nguyên lý Domain-Driven Design vào việc quản trị và phân tích dữ liệu phân tán quy mô lớn.
Bài Tập Ôn Tập & Củng Cố Tri Thức (Exercises)
Dưới đây là 4 câu hỏi trắc nghiệm chuyên sâu giúp bạn đánh giá mức độ thấu suốt kiến trúc Hướng Sự Kiện và DDD, đi kèm đáp án và lời giải thích chính thức từ tác giả Vlad Khononov (Appendix B).
Giải thích chi tiết từ Tác giả (Appendix B): Event Sourcing là một mẫu hình triển khai nội bộ dùng để lưu trữ trạng thái của Aggregate dưới dạng chuỗi các sự kiện quá khứ (không nên để lộ ra bên ngoài). Ngược lại, Event-Driven Architecture là phong cách kiến trúc hệ thống phục vụ việc giao tiếp và tích hợp xuyên qua các ranh giới giữa các thành phần khác nhau.
Giải thích chi tiết từ Tác giả (Appendix B): ECST được thiết kế chuyên biệt như một cơ chế nhân bản dữ liệu bất đồng bộ. Nó mang theo bản chụp trạng thái (hoặc các trường vừa thay đổi) giúp bên nhận có thể trực tiếp cập nhật bản sao cache nội bộ mà không cần phải gọi API ngược lại bên phát.
Giải thích chi tiết từ Tác giả (Appendix B): Mẫu Open-Host Service đòi hỏi phía thượng nguồn phải tách biệt mô hình nội bộ khỏi giao diện công khai bằng cách định nghĩa một Published Language chuẩn tắc. Trong ngữ cảnh EDA, các sự kiện công khai chính là một phần của Published Language đó, đảm bảo không làm rò rỉ chi tiết triển khai bên trong ra ngoài.
Giải thích chi tiết từ Tác giả (Appendix B): Trong giao tiếp bất đồng bộ, thông điệp ECST có thể bị trễ trên đường truyền dẫn đến việc dữ liệu nhận được đã bị cũ so với trạng thái tức thời ở nguồn. Khi một use case đòi hỏi tính nhất quán cao (phải đọc được thay đổi mới nhất vừa ghi), cách tiếp cận chuẩn xác là dùng Event Notification làm chuông báo, và bên tiêu thụ lập tức gọi API trực tiếp để đọc trạng thái tức thời, có thể kết hợp khóa bi quan nếu cần.