Bắt đầu với kiến trúc hướng sự kiện (Event-driven architecture)

bởi  Talia Nassi | vào 06 APR 2022 | in Amazon EventBridge, Events, Serverless | Permalink |

Trong phát triển ứng dụng hiện đại, kiến trúc hướng sự kiện (Event-driven architecture hay EDA) đang ngày càng trở nên phổ biến bởi vì nó có thể giúp việc xây dựng các ứng dụng trên đám mây dễ dàng hơn. EDA cho phép bạn tách rời các dịch vụ của mình, điều này làm tăng tốc độ của developer, và giúp bạn dễ dàng debug các ứng dụng hơn. Nó cũng có thể giúp loại bỏ tắc nghẽn xảy ra khi các tính năng mở rộng trên các nhóm khác nhau, cho phép các nhóm tiến triển độc lập hơn.

Một cách để suy nghĩ về cách hoạt động của một ứng dụng là coi nó như một hệ thống phản ứng với các sự kiện từ các vị trí khác, chẳng hạn như từ bên trong ứng dụng của bạn. Trong cách tiếp cận này, bạn tập trung vào sự tương tác của hệ thống với môi trường xung quanh như một quá trình truyền tải các sự kiện. Ứng dụng nhận và tạo các sự kiện. Đầu vào cho ứng dụng và đầu ra từ ứng dụng hoạt động như các sự kiện. Về cốt lõi, đây là kiến trúc hướng sự kiện (EDA).

Kiến trúc hướng API (API-driven architecture) vs. Kiến trúc hướng sự kiện

Câu lệnh/ gọi APISự kiện
Đồng bộBất đồng bộ
Có mục đíchGọi thẳng đến điểm đíchLà một sự việc xảy raXảy ra ở quá khứ
“Tạo tài khoản””Thêm sản phẩm”“Tài khoản đã được tạo””Sản phẩm đã được thêm”

Một cách phổ biến để các thành phần của ứng dụng hoạt động cùng nhau là thông qua kiến trúc theo yêu cầu-phản hồi được điều khiển bằng API, nơi bạn có các yêu cầu và phản hồi. Ví dụ: bạn truy vấn danh sách các đơn hàng từ API Đơn hàng và API Đơn hàng trả về danh sách các đơn hàng. Đây là một ví dụ về kiến trúc đồng bộ. Hệ thống yêu cầu đặt hàng sẽ đợi phản hồi. Bạn không thể tiếp tục cho đến khi nhận được phản hồi. Trong cách tiếp cận này, bạn gửi các lệnh được hướng đến một mục tiêu (ví dụ: “đặt hàng này” hoặc “thêm bản ghi này vào cơ sở dữ liệu”).

Trong mô hình đồng bộ, client gửi yêu cầu đến Dịch vụ A. Dịch vụ A gọi Dịch vụ B, nhưng sau đó Dịch vụ A sẽ chờ Dịch vụ B phản hồi trước khi nó tiếp tục và cuối cùng trả lời cho client.

Trong kiến trúc hướng sự kiện phi đồng bộ, không có đường dẫn phản hồi. Dịch vụ thông báo sự kiện và sau đó lập tức tiếp tục hoạt động. Sự đánh đổi ở đây là không có kênh trực tiếp để Dịch vụ B truyền thông tin trở lại Dịch vụ A, bên cạnh việc xác nhận nó đã nhận được sự kiện. Nhưng trong nhiều trường hợp, bạn không cần sự kết hợp rõ ràng giữa các kênh yêu cầu và phản hồi.

Sự kiện là một điều gì đó đã xảy ra. Ví dụ: một tài khoản mới được tạo hoặc một mặt hàng được đưa vào Amazon S3 bucket. Sự kiện không thể thay đổi (immutable), nghĩa là bạn không thể thay đổi chúng. Một khi sự kiện xảy ra, bạn không thể hoàn tác nó. Ví dụ: nếu có một sự kiện được kích hoạt khi đặt hàng, thì có thể có một sự kiện khác để hủy đơn hàng. Sự kiện có thể đến từ các nguồn khác nhau như hệ thống nhắn tin hoặc cơ sở dữ liệu.

Sự kiện là các đối tượng JSON cung cấp cho bạn thông tin về một điều gì đó đã xảy ra trong ứng dụng của bạn. Trong kiến trúc hướng sự kiện, sự kiện đại diện cho các sự thật. Mỗi thành phần của ứng dụng sẽ kích hoạt một sự kiện bất cứ khi nào có gì thay đổi. Các thành phần khác lắng nghe và quyết định cách xử lý sự kiện đó và cách chúng phản ứng.

Trong ví dụ trên, S3 kích hoạt sự kiện khi bạn đặt hình ảnh vào thùng Amazon S3. Nguồn sự kiện là một bucket S3 có tên sam-app-sourcebucket. Đối tượng được đưa vào thùng được gọi là “brad.jpeg”.

Các ứng dụng theo yêu cầu thường sử dụng các lệnh được hướng dẫn để phối hợp các chức năng phụ trợ để hoàn thành một hoạt động và thường được kết hợp chặt chẽ. Điều này làm cho việc xác định thời điểm xảy ra lỗi trong ứng dụng của bạn khó khăn hơn. Các ứng dụng theo sự kiện tạo ra các sự kiện có thể quan sát được bởi các dịch vụ và hệ thống khác. Tuy nhiên, bộ phát sự kiện không biết người dùng nào, nếu có, đang lắng nghe. Thông thường, chúng được kết hợp lỏng lẻo.

Sự kiện có thể quan sát được. Bất kỳ dịch vụ được ủy quyền nào cũng có thể theo dõi một sự kiện. Hãy xem xét ví dụ về một quán cà phê, nơi có một barista pha cà phê và một đầu bếp bánh ngọt làm bánh ngọt. Khi khách hàng bước vào quán cà phê và gọi một tách cà phê, barista bắt đầu pha cà phê và đầu bếp bánh ngọt không có bất kỳ hành động nào.

Tuy nhiên, nếu một khách hàng đến quán cà phê và gọi một chiếc bánh sừng bò chocolate, thì đầu bếp bánh ngọt bắt đầu làm bánh sừng bò chocolate, còn barista không có bất kỳ hành động nào. Đầu bếp bánh ngọt chỉ quan tâm đến các đơn hàng liên quan đến bánh ngọt và barista chỉ quan tâm đến các sự kiện liên quan đến cà phê.

Trong một ứng dụng thương mại điện tử, như Amazon.com, có các bộ phận khác nhau phản hồi các sự kiện khác nhau. Bạn có thể đặt hàng thông qua Whole Foods, Amazon Fresh và Amazon.com. Khi bạn đặt hàng với Amazon Fresh, những người đăng ký sự kiện đó sẽ thực hiện hành động và hoàn thành đơn hàng của bạn.

(Ví dụ về các câu lệnh trực tiếp và các sư kiện gián tiếp)

Kiến trúc hướng sự kiện và kiến trúc hướng lệnh cũng khác nhau về cách chúng lưu trữ trạng thái. Trong một kiến trúc hướng lệnh điển hình, bạn chỉ có một thành phần lưu trữ một phần dữ liệu cụ thể và các thành phần khác yêu cầu thành phần đó cung cấp dữ liệu khi cần.

Trong kiến trúc hướng sự kiện, mỗi thành phần lưu trữ tất cả dữ liệu cần thiết và lắng nghe các sự kiện cập nhật cho dữ liệu đó. Trong kiến trúc hướng lệnh, thành phần lưu trữ dữ liệu chịu trách nhiệm cập nhật dữ liệu đó. Trong kiến trúc hướng sự kiện, tất cả những gì nó phải làm là đảm bảo các sự kiện mới được kích hoạt khi có cập nhật.

Lợi ích của việc sử dụng kiến trúc hướng sự kiện

Phân tách nguồn sự kiện (Decoupling) và mục tiêu sự kiện

Nhiều ứng dụng được xây dựng theo kiểu monolith, trong đó các thành phần được gắn chặt chẽ ( tightly coupled) và phụ thuộc nhiều vào nhau. Điều này gây ra vấn đề khi có lỗi và bạn đang cố gắng xác định chính xác phần nào của ứng dụng bị lỗi. Kiến trúc tách rời được cấu thành từ các thành phần hoặc dịch vụ được gắn lỏng lẻo (loosely coupled). Trong kiến trúc tách rời hướng sự kiện, bạn phát các sự kiện mà không cần quan tâm đến ai phản hồi chúng. Điều này giúp tiết kiệm thời gian vì các sự kiện có thể được xếp hàng đợi và chuyển tiếp bất cứ khi nào người nhận sẵn sàng xử lý chúng. Điều này cho phép xây dựng các hệ thống có khả năng mở rộng, có thể sửa đổi cao.

Các ứng dụng được tách rời cho phép các nhóm hoạt động độc lập hơn, điều này làm tăng tốc độ của họ. Ví dụ, với tích hợp dựa trên API, nếu nhóm của tôi muốn biết về một số thay đổi xảy ra trong microservice của nhóm khác, tôi phải yêu cầu nhóm đó thực hiện cuộc gọi API đến dịch vụ của tôi. Điều đó có nghĩa là tôi phải xử lý xác thực, phối hợp với nhóm khác về cấu trúc của cuộc gọi API, v.v. Điều này gây ra sự qua lại giữa các nhóm, làm chậm thời gian phát triển. Với ứng dụng hướng sự kiện, bạn có thể đăng ký các sự kiện được gửi từ microservice và bộ định tuyến sự kiện (ví dụ: Amazon EventBridge) sẽ xử lý việc định tuyến sự kiện và xử lý xác thực.

Các ứng dụng tách rời cũng cho phép bạn xây dựng các tính năng mới nhanh hơn. Thêm các tính năng mới hoặc mở rộng các tính năng hiện có đơn giản hơn với kiến trúc hướng sự kiện. Điều này là do bạn chỉ cần chọn sự kiện bạn cần để kích hoạt tính năng mới của mình và đăng ký với sự kiện đó. Không cần sửa đổi bất kỳ dịch vụ hiện có nào của bạn để thêm chức năng mới.

Viết ít mã hơn

Khi bạn xây dựng ứng dụng sử dụng kiến trúc hướng sự kiện, thường bạn sẽ viết ít mã hơn vì bạn chỉ cần cân nhắc các sự kiện mới, cũng như dịch vụ nào được đăng ký với các sự kiện đó. Ví dụ: nếu bạn đang xây dựng các tính năng mới cho ứng dụng của mình, tất cả những gì bạn phải làm là xem xét các sự kiện hiện có và sau đó thêm người gửi và người nhận nếu cần. Theo cách này, bạn tăng tốc thời gian phát triển vì mỗi đơn vị chức năng nhỏ hơn và thường có ít mã hơn.

Mở rộng tốt hơn

Trong ví dụ trên, bạn đã xây dựng một ứng dụng có khả năng mở rộng cao. Các nhóm khác có thể mở rộng các tính năng và thêm chức năng mà không ảnh hưởng đến các microservice khác. Bằng cách phát hành các sự kiện của EventBridge, ứng dụng này tích hợp với các hệ thống hiện có, nhưng cũng cho phép bất kỳ ứng dụng nào trong tương lai tích hợp như một người tiêu dùng sự kiện. Bên sản xuất sự kiện không có kiến ​​thức về người tiêu dùng sự kiện, điều này có thể giúp đơn giản hóa logic của microservice.

Cải thiện sự cộng tác nhóm

Một quy trình phổ biến để xây dựng ứng dụng là làm việc với các Giám đốc sản phẩm và bên liên quan trong doanh nghiệp để thu thập yêu cầu. Sau đó, các nhà phát triển dịch các yêu cầu đó thành mã. Tuy nhiên, có thể có sự mất kết nối giữa các yêu cầu sản phẩm và mã. Khi bạn sử dụng các sự kiện, mọi người trong doanh nghiệp đều hiểu logic. Bạn xác định các sự kiện trong một ứng dụng (ví dụ: khách hàng thêm một mặt hàng vào giỏ hàng của họ hoặc tài khoản khách hàng được tạo) và đó trở thành yêu cầu sản phẩm của bạn. Bất cứ khi nào hành động đó xảy ra, nó sẽ tạo ra một sự kiện và bất kỳ ai quan tâm đều có thể thực hiện hành động trên sự kiện đó.

Ví dụ: Giám đốc marketing có thể quan tâm bất cứ khi nào khách hàng tạo tài khoản mới. Một cách để lên lịch điều này trong kiến trúc hướng sự kiện là có một bus sự kiện Marketing lắng nghe sự kiện Tài khoản mới. Ngoài ra, có thể có các nhóm khác quan tâm, chẳng hạn như nhóm Phân tích, những người cũng đăng ký sự kiện đó. Mỗi nhóm/dịch vụ có thể đăng ký các sự kiện có liên quan đến họ. Kiến trúc hướng sự kiện là một cách tuyệt vời để các doanh nghiệp mô tả các vấn đề kinh doanh của họ và thể hiện chúng.

Kết luận

Bài đăng này giới thiệu về các sự kiện và sau đó so sánh kiến trúc hướng sự kiện với kiến trúc theo yêu cầu-phản hồi được điều khiển bằng lệnh. Nó cũng giải thích những lợi ích của kiến trúc hướng sự kiện, bao gồm tách rời nguồn sự kiện và mục tiêu sự kiện, viết ít mã hơn, có khả năng mở rộng tốt hơn và cải thiện sự cộng tác nhóm.

Để biết thêm tài nguyên học tập không server, hãy truy cập Serverless Land.

Leave a comment