Xin chào các bạn, đây là Series Architecture Pattern!
Trong bài trước Architecture Pattern - Phần 2, tôi đã giới thiệu kiến trúc "quốc dân" là kiến trúc phân lớp (Layered Architecture).
Trong bài này, chúng ta sẽ cùng tìm hiểu kiến trúc hướng sự kiện (Event-driven architecture). Đây là mẫu kiến trúc phần mềm trở thành trào lưu trong những năm trở lại đây nhờ sự loose coupling, xử lý event thời gian thực cùng khả năng phục hồi và dễ dàng tích hợp vào các hệ thống khác nhau.
1. Kiến trúc hướng sự kiện là gì?
Kiến trúc hướng sự kiện (Event-driven architecture - EDA) là một mô hình kiến trúc phần mềm trong đó các thành phần hoặc dịch vụ của hệ thống giao tiếp với nhau chủ yếu thông qua việc sản xuất và tiêu thụ các sự kiện.
Các "sự kiện" (event) này có thể là các hành động người dùng, cập nhật dữ liệu, hoặc các thông báo từ các hệ thống khác. EDA giúp tạo ra các hệ thống linh hoạt, mở rộng và dễ tích hợp.
2. Phân loại kiến trúc hướng sự kiện
EDA được phân loại dựa trên cấu trúc liên kết (topology) giữa các component trong hệ thống với nhau, bao gồm hai mô hình phổ biến là Broker topology và Mediator topology.
Giờ chúng ta sẽ cùng tìm hiểu về hai mô hình này cũng như các trường hợp nên và không nên sử dụng chúng.
2.1. Broker topology
Trong Broker topology, luồng tin nhắn sẽ phân phối đều tới các event processor qua messsage broker mà không cần tới một trung tâm điều phối event.
2.1.1. Các thành phần chính của broker topology
Các thành phần chính của Broker topology bao gồm:
- Initiating event: sự kiện ban đầu bắt đầu toàn bộ luồng sự kiện
- Event channel: được sử dụng để lưu trữ các sự kiện được tạo ra và phân phối các sự kiện đó đến một service phản hồi chúng. Event channel có thể ở dạng topic hoặc queue.
- Event broker: chứa các event channel tham gia vào một luồng sự kiện.
- Event processor: service chịu trách nhiệm xử lý sự kiện
- Processing event: là sự kiện được tạo khi trạng thái của một số service thay đổi và gửi thông báo cho phần còn lại của hệ thống về sự thay đổi trạng thái đó. Event này được gửi theo cơ chế fire-and-forget broadcasting, tức là gửi và sau đó không cần xác nhận việc gửi có thành công hay không.
2.1.2. Luồng tin nhắn trong broker topology
Luồng tin nhắn trong broker topology hoạt động theo thứ tự sau:
- Một initiating event được gửi tới một event channel nằm trong event broker để xử lý.
- Một event processor lấy event đó về từ event channel để xử lý và thực hiện nhiệm vụ cụ thể liên quan đến việc xử lý event đó.
- Khi xử lý xong, event processor gửi một processing event tới event channel nhằm thông báo rằng event đã xử lý xong.
- Các event processor khác sẽ lắng nghe processing event này và phản ứng lại bằng cách tạo ra event processing khác. Quá trình này lặp lại cho tới khi event processor cuối xử lý xong.
Hãy để ý trong luồng tin nhắn, khi xử lý xong event, event processor sẽ luôn gửi tới broker một processing event để thông báo đã xử lý xong dù chúng có được tiêu thụ hay không. Nếu một event không có ai lắng nghe thì nó sẽ bị bỏ qua.
Điều này tưởng chừng là lãng phí tài nguyên, tuy nhiên, trong thực tế, đây là thiết kế đảm bảo khả năng mở rộng hệ thống. Lý do là nếu hệ thống phát sinh nghiệp vụ mới, cần tới event này thì bạn chỉ cần cho Event Processor lắng nghe thay vì phải sửa logic trong code.
2.1.3. Trường hợp nên dùng broker topology
- Cần giảm sự phụ thuộc lẫn nhau (loose coupling): Đối với các hệ thống mà các thành phần cần hoạt động độc lập, không cần biết về nhau, broker topology cung cấp khả năng tách rời cần thiết.
- Định tuyến đơn giản: các event processor giao tiếp với nhau bằng event mà không cần thông qua một trung gian quản lý nào nên phù hợp với hệ thống có định tuyến đơn giản, không cần đảm bảo đúng trình tự.
2.1.4. Trường hợp không nên dùng broker topology
- Xử lý logic phức tạp giữa các thành phần: Nếu hệ thống yêu cầu xử lý logic phức tạp, biến đổi dữ liệu, hoặc điều phối quy trình làm việc giữa các nhà sản xuất và người tiêu dùng, broker topology có thể không đủ linh hoạt. mediator topology thường phù hợp hơn trong trường hợp này.
- Tích hợp và chuẩn hóa dữ liệu từ nhiều nguồn: Trong trường hợp cần tích hợp dữ liệu từ nhiều nguồn khác nhau với các định dạng và giao thức không đồng nhất, Broker Topology có thể không cung cấp đủ khả năng xử lý và chuẩn hóa dữ liệu cần thiết.
- Cần kiểm soát trung tâm và quản lý workflow: Nếu hệ thống cần một mức độ kiểm soát trung tâm cao đối với luồng sự kiện và quản lý luồng, Broker topology có thể không phù hợp. Mediator Topology, với khả năng điều phối và quản lý trung tâm, có thể là lựa chọn tốt hơn trong trường hợp này.
2.2. Meditator topology
Trong Meditator topology có một thành phần trung gian, thường được gọi là "mediator", được sử dụng để điều phối và quản lý luồng sự kiện giữa các service hoặc component khác nhau trong hệ thống.
2.2.1. Các thành phần chính của Meditator topology bao gồm:
- Initiating event: sự kiện ban đầu bắt đầu toàn bộ luồng sự kiện
- Event queue: lưu trữ các sự kiện ban đầu, đảm bảo chúng không bị mất mát trong quá trình xử lý. Queue giúp xử lý các sự kiện tuần tự, đảm bảo tính nhất quán trước khi event được chuyển tới Meditator.
- Event meditator: nơi điều phối và quản lý luồng sự kiện, là trung tâm của mô hình Meditator.
- Event channel: tương tự broker topology
- Event processor: tương tự broker topology
2.2.2. Cách hoạt động của Meditator topology được mô tả thông qua ví dụ về hệ thống bán lẻ sau:
- Bước 1: Tạo đơn hàng
Sau khi nhận được event khởi tạo PlaceOrder
, Meditator tạo ra event create-order
, rồi gửi nó tới order-placement
queue. OrderPlacement
event processor sẽ nhận event này, xác thực thông tin và tạo order, trả cho Meditator thông báo đã xử lý xong kèm ID của order (acknowledment). Tuỳ vào nghiệp vụ cụ thể, Meditator có thể gửi lại event cho client để thông báo đã tạo order.
- Bước 2: Xử lý đơn hàng
Meditator tạo và gửi 3 event đồng thời là email-customer
, apply-payment
và adjust-inventory
tới các queue tương ứng là notification
, payment
và inventory
. Meditator cần phải chờ cho các event processor xử lý thành công tất cả event trước khi chuyển sang bước 3.
- Bước 3: Thực hiện đơn hàng
Tương tự bước 2, các event fulfill-order
và order-stock
được gửi tới các queue tương ứng là order-fulfillment
và warehouse
.
- Bước 4: Giao hàng
Meditator thông báo trạng thái sẵn sàng giao hàng cho khách hàng bằng gửi event email-customer
và ship-order
tới các queue notification
và shipping
.
- Bước 5: Thông báo cho khách hàng
Thông báo cho khách hàng trạng thái đơn hàng qua email bằng event email-custormer
.
2.2.3. Trường hợp nên dùng meditator topology:
- Cần quản lý tập trung: Phù hợp với các hệ thống cần quản lý tập trung, cần sự tích hợp chặt chẽ để đảm bảo các sự kiện được điều phối và xử lý theo đúng trình tự. Nếu hệ thống yêu cầu kiểm soát chặt chẽ về quyền truy cập và bảo mật dữ liệu, mediator topology có thể cung cấp một lớp kiểm soát bổ sung.
- Cần xử lý logic phức tạp: Khi hệ thống yêu cầu xử lý logic nâng cao hoặc biến đổi sự kiện trước khi chúng được gửi đến người tiêu dùng cuối cùng. Mediator có thể thực hiện các tác vụ như lọc, biến đổi dữ liệu, hoặc ánh xạ sự kiện.
- Tích hợp hệ thống đa dạng: Khi cần tích hợp nhiều hệ thống khác nhau với các giao thức và định dạng tin nhắn không đồng nhất, mediator topology cho phép biến đổi và chuẩn hóa dữ liệu giữa các hệ thống.
2.2.4. Trường hợp không nên dùng meditator topology:
- Yêu cầu hiệu suất cao và độ trễ thấp: Mediator Topology có thể tạo ra độ trễ bổ sung do xử lý trung gian. Trong các hệ thống cần xử lý tin nhắn cực kỳ nhanh và độ trễ thấp, việc thêm một mediator có thể không phù hợp.
- Cần tính đơn giản và dễ mở rộng: Nếu mục tiêu là xây dựng một hệ thống đơn giản, dễ hiểu và dễ mở rộng, việc thêm một mediator có thể làm tăng độ phức tạp không cần thiết.
- Tách biệt và độc lập giữa các thành phần: Trong các hệ thống yêu cầu mức độ tách biệt cao giữa các thành phần, việc sử dụng mediator có thể tạo ra sự phụ thuộc trung tâm, làm giảm khả năng tách biệt và độc lập của các thành phần.
- Khả năng chịu lỗi và phục hồi: Mediator trở thành điểm trung tâm có thể gây ra sự cố. Nếu mediator gặp sự cố, toàn bộ hệ thống có thể bị ảnh hưởng. Trong các hệ thống cần khả năng chịu lỗi cao, việc phụ thuộc vào một điểm trung tâm có thể không phải là lựa chọn tốt nhất.
3. Xử lý mất dữ liệu trong kiến trúc hướng sự kiện
Một trong những vấn đề trọng tâm trong EDA là mất dữ liệu. Lỗi này có thể xảy ra ở các thời điểm sau:
- Event processor đẩy event vào Event channel: Broker lỗi khiến cho dữ liệu bị mất.
- Event channel đẩy event tới Event Processor: Event processor lỗi trước khi nhận được event, gây mất dữ liệu.
- Event processor lưu trữ dữ liệu đã xử lý vào database: dữ liệu bị lỗi không lưu vào database được hoặc database bị lỗi không nhận được dữ liệu.
Việc mất dữ liệu ở các thời điểm có thể giải quyết bằng các biện pháp sau:
- Synchronous send (Gửi đồng bộ): Triển khai Persisted message queues hỗ trợ tính năng guaranteed delivery. Khi nhận một event, broker sẽ lưu dữ liệu cả ở memory và ở kho chứa vật lý như filesystem hoặc database. Nhờ vậy, nếu broker bị lỗi, khi trở lại hoạt động bình thường, nó hoàn toàn có thể lấy event ở kho chứa vật lý để xử lý tiếp.
- Client acknowledge mode (Chế độ xác nhận): Khi một event được lấy ra từ queue, nó sẽ bị xoá khỏi queue. Tuy nhiên, với chế độ client acknowledge mode, event sẽ không bị xoá khỏi queue và được gắn client ID, đánh dấu nó đã được tiêu thụ, nhằm không consumer nào có thể đọc nó. Nếu Event processor A bị lỗi khi đang xử lý event X, thì X vẫn còn tồn tại trong queue, đảm bảo dữ liệu không bị mất.
- Last participant support (LPS): Việc data lỗi không lưu được vào database có thể xử lý bằng cách tận dụng ACID. Nếu có lỗi xảy ra khi transaction đã được commit thì dữ liệu sẽ được. Các event được xác nhận sau khi data được lưu thành công vào database.
4. Tổng kết
Kiến trúc hướng sự kiện EDA là một mô hình kiến trúc phần mềm trong đó các thành phần hoặc dịch vụ của hệ thống giao tiếp với nhau chủ yếu thông qua việc sản xuất và tiêu thụ các sự kiện.
EDA bao gồm hai mô hình chính là broker topology và meditator topology.
EDA đem lại khả năng phản ứng nhanh và linh hoạt, làm tăng hiệu suất xử lý trong các hệ thống phức tạp. Tuy nhiên, việc áp dụng EDA cần cân nhắc kỹ lưỡng về quản lý sự phụ thuộc và đảm bảo tính nhất quán dữ liệu.
5. Tài liệu tham khảo
- Fundamentals of Software Architecture - Mark Richards
- Software Architecture Patterns - Mark Richards
- Software Architecture Monday - Mark Richards
- Microservices - Martin Flower
Bài viết liên quan
AWS là gì? Top những services AWS được sử dụng nhiều nhất
Jul 04, 2024 • 14 min read
Giải thích các ký hiệu trong class diagram
May 02, 2024 • 7 min read
Giải thích các ký hiệu trong use case diagram
Apr 11, 2024 • 7 min read
UML là gì? Giới thiệu các loại UML hay dùng
Apr 11, 2024 • 14 min read
Phỏng vấn Software Engineer tại Google diễn ra như thế nào?
Mar 12, 2024 • 12 min read
Architecture Pattern - Phần 6: Kiến trúc hướng không gian (Space-based architecture)
Mar 05, 2024 • 11 min read