Quay lại blogEvent-Driven Architecture: Kiến trúc của những hệ thống có khả năng mở rộng

Event-Driven Architecture: Kiến trúc của những hệ thống có khả năng mở rộng

Nguyễn Trung Dũng

KafkaSystem DesignScalabilityEvent-Driven ArchitectureArchitectural StylesArchitecture

Kiến trúc đóng vai trò cực kì quan trọng trong những hệ thống lớn. Làm sản phẩm công nghệ cũng như xây một toà chung cư, scale càng lớn thì ảnh hưởng của kiến trúc lên thành quả cuối cùng càng được thể hiện rõ. Các kiến trúc sư xây dựng sẽ phải tính toán về hạ tầng, tải trọng, các vị trí đặt đường điện nước sao cho tối ưu..., cũng như các kiến trúc sư phần mềm sẽ quan tâm tới khả năng mở rộng, bảo trì hay bảo mật...

Trong bài Kafka, chúng ta đã được giới thiệu về Kafka qua một ví dụ đơn giản để hiểu nó có thể giúp ích gì trong một bài toán thực tế. Hôm nay, chúng ta sẽ cùng nhìn rộng hơn, để nghiên cứu về một nền tảng kiến trúc được ứng dụng rộng rãi trong gần như tất cả các hệ thống lớn hiện đại - Event-Driven Architecture (EDA) - nơi Kafka đóng vai trò cốt lõi trong toàn bộ hệ thống.

Kafka là công cụ, Event-Driven Architecture mới thực sự là tư duy thiết kế.


Hãy cùng nhắc lại một chút về kiến trúc của một website bán hàng đơn giản.

Giai đoạn đầu, kiến trúc đồng bộ (synchronous) là tối ưu, workload đủ thấp để việc các service gọi nhau trực tiếp không tạo vấn đề gì lớn. Lợi thế của kiến trúc này:

  • Hệ thống cực kì đơn giản, data flow rõ ràng, ít node trung gian

  • Event được xử lý ngay lập tức, dẫn tới khả năng debug trên từng service rất nhanh và tiện (dựa trên event timestamp)

Giai đoạn tiếp theo, khi scale lớn hơn một chút là lúc các vấn đề của kiến trúc đồng bộ dần thể hiện ra. Một trong những vấn đề là về tính phụ thuộc (service dependency): một đơn hàng thành công sẽ kéo theo một loạt các nghiệp vụ bên dưới, bao gồm: recommendation, loyalty, voucher, fraud detection... Order service dần trở thành điểm tích hợp của toàn hệ thống khi phải gọi qua tất cả các API này. Latency tăng lên khi có bất kì service nào bị chậm, khả năng mở rộng (maintainablity) cũng vì thế càng ngày càng bị giới hạn vì mỗi khi thêm các tính năng, order service sẽ phải sửa code để gọi thêm API mới.

Liệu order service có cần thiết phải biết về tất cả các service bên dưới? Và đây là lúc chúng ta nhận ra root cause của các vấn đề trên: service coupling.

Hãy thử suy nghĩ một chút, thứ order service quan tâm không phải là: "báo với loyalty là hãy cộng điểm cho customer này", hay "chạy recommendation đi"... Order service không nên là orchestrator của toàn hệ thống, mà nhiệm vụ của nó đơn giản chỉ là thông báo: "một order đã được tạo thành công!". Tất cả các service khác có thể dựa vào thông báo đó để quyết định sẽ xử lý tiếp như thế nào.

Khi order service không còn là trung tâm, vậy hệ thống mới sẽ xoay quanh điều gì? Chúng ta đi tới khái niệm "event" - E trong EDA.

Thứ nằm ở trung tâm của hệ thống chính là Order Event, được tiếp nhận và phân phối bởi Event Broker (mà đại diện tiêu biểu nhất chính là Kafka). Order service là Event Producer, các service còn lại là Event Consumer.

Có thể thấy, Event Broker chính là trạm trung chuyển đưa những event tới các địa chỉ trên toàn bộ hệ thống. Các service không còn phụ thuộc vào nhau, chỉ giao tiếp thông qua event. Không chỉ thế, kiến trúc mới đã sử dụng cơ chế xử lý bất đồng bộ (asynchronous) khi mà pha event processing tách biệt với event producing, làm giảm coupling và dependency trên toàn hệ thống.

Chúng ta có gì mới ở kiến trúc EDA?

  • Khi một service mới tham gia vào hệ thống, hay một service cũ được scale để tăng khả năng xử lý, nó chỉ cần connect tới Event Broker để nhận được event, tất cả các service còn lại không bị ảnh hưởng

  • Order, hay tất cả các service, chỉ làm đúng công việc nó được thiết kế để làm, không có service nào đóng vai trò orchestrator như trước, dẫn đến việc triển khai các service mới đơn giản hơn rất nhiều

Điều quan trọng cần chú ý là EDA không phải lời giải cho mọi bài toán, nó không thay thế API call, cũng như synchronous processing vẫn cần thiết cho nhiều thao tác cần phản hồi ngay lập tức, ví dụ xác thực thanh toán - khách hàng sẽ rất băn khoăn nếu phải chờ 5 phút sau khi thanh toán xong mới nhận được thông báo xác nhận.


Đối với các kiến trúc truyền thống, chúng ta bắt đầu bằng việc phân tích thiết kế API, lựa chọn database. Trong EDA, chúng ta bắt đầu bằng câu hỏi: "Business này tạo ra những event nào?"

Điểm khởi đầu của EDA không xuất phát từ API, Database, mà là business event. Event là ngôn ngữ chung của toàn hệ thống, quyết định các service sẽ được thiết kế và cách chúng giao tiếp với nhau.

Cũng chính vì thiết kế dựa trên business event, nên khi business mở rộng, hệ thống cũng sẽ phát triển theo cùng một cách: bổ sung các event mới nếu cần, tạo ra các service mới lắng nghe và xử lý chúng, thay vì luôn phải động vào phần core mỗi khi có thay đổi. Trong một thế giới mà yêu cầu về business thay đổi chỉ trong cái chớp mắt, khả năng mở rộng một cách độc lập này có thể mang lại lợi thế đáng kinh ngạc khi phát triển trên một hệ thống lớn đã tồn tại.

EDA không phải một tư duy mới, tuy nhiên sự xuất hiện của Kafka đã giúp việc xây dựng kiến trúc ở quy mô lớn đơn giản và hiệu quả hơn, đó cũng là lý do khiến Kafka trở thành Event Broker phổ biến nhất, góp phần đưa EDA trở thành kiến trúc được sử dụng rộng rãi và rất phổ biến trong các hệ thống của Big Techs thời đại ngày nay.

API là ngôn ngữ của các ứng dụng, Event là ngôn ngữ của những hệ thống có khả năng mở rộng.

Share

Bài viết liên quan