1. Trang chủ
  2. » Luận Văn - Báo Cáo

Tìm hiểu về event sourcing

90 12 2

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Tiêu đề Tìm hiểu về Event Sourcing
Tác giả Nguyễn Thái Tuấn
Người hướng dẫn ThS. Nguyễn Công Hoan
Trường học Đại học Quốc gia Thành phố Hồ Chí Minh
Chuyên ngành Công nghệ thông tin
Thể loại Đồ án
Năm xuất bản 2023
Thành phố Tp. Hồ Chí Minh
Định dạng
Số trang 90
Dung lượng 16,32 MB

Cấu trúc

  • Chương 1: GIỚI THIỆU TỔNG QUAN (12)
    • 1.1 Thông tin người thực hiện (12)
    • 1.2 Tổng quan đề tài (12)
      • 1.2.1 Giới thiệu đề tài (12)
      • 1.2.2 Lý do chọn đề tài (13)
      • 1.2.3 Phạm vi nghiên cứu (13)
      • 1.2.4 Đối tượng nghiên cứu (13)
      • 1.2.5 Kết quả hướng tới (14)
    • 1.3 Công cụ sử dụng (15)
  • Chương 2: KIẾN THỨC NỀN TẢNG (16)
    • 2.1 Event sourcing (16)
      • 2.1.1 Event sourcing là gì? (16)
      • 2.1.2 Event (17)
      • 2.1.3 Stream (18)
      • 2.1.4 Thông tin đại diện một Event (Event representation) (20)
      • 2.1.5 Lấy trạng thái hiện tại tổng hợp từ những Event (21)
      • 2.1.6 Nơi lưu trữ Event (Event store) (25)
    • 2.2 Tính năng (26)
      • 2.2.1 Chịu lỗi và phục hồi hệ thống (Complete rebuild) (26)
      • 2.2.2 Quay lại quá khứ và xem những gì xảy ra (Temporal query) (26)
      • 2.2.3 Lặp lại và phân tích (Event replay) (27)
      • 2.2.4 Tối ưu với snapshot (28)
    • 2.3 Lợi ích và bất lợi (30)
      • 2.3.1 Kiểm kê (Audit) (30)
      • 2.3.2 Xử lí đồng thời (Parallel processing) (0)
      • 2.4.1 Projections (33)
      • 2.4.2 Subscription (35)
      • 2.4.3 Revision (39)
      • 2.4.4 Etag (40)
    • 2.5 Các thành phần quan trọng khi cài đặt microservice (41)
      • 2.5.1 Mẫu thiết kế Saga (Saga pattern) (41)
      • 2.5.2 Kiến trúc hướng sự kiện (Event Driven Architecture) (46)
      • 2.5.3 Mẫu thiết kế Pub/sub (Pub/sub pattern) (52)
      • 2.5.4 Message broker (message queue) (53)
      • 2.5.5 API gateway (54)
      • 2.5.6 Service discovery (56)
  • Chương 3: XÂY DỰNG HỆ THỐNG (59)
    • 3.1 Giới thiệu chung về bài toán (59)
      • 3.1.1 Phát biểu bài toán (59)
      • 3.1.2 Hướng giải quyết (60)
      • 3.1.3 Công cụ, công nghệ sử dụng (60)
      • 3.1.4 Mã nguồn (0)
    • 3.2 Phân tích (61)
      • 3.2.1 Danh sách các yêu cầu (61)
      • 3.2.2 Sơ đồ use case (62)
      • 3.2.3 Đặc tả (63)
    • 3.3 Thiết kế (68)
      • 3.3.1 Thiết kế kiến trúc (68)
      • 3.3.2 Thiết kế dữ liệu (72)
      • 3.3.3 Thiết kế API (81)
      • 3.3.4 Triển khai (83)
  • Chương 4: KẾT LUẬN (88)

Nội dung

GIỚI THIỆU TỔNG QUAN

Thông tin người thực hiện

20522122 Nguyễn Thái Tuấn 20522122@gm.uit.edu.vn

Bảng 1 1 Thông tin người thực hiện

Tổng quan đề tài

Trong các hệ thống lớn hiện nay, đặc biệt đối với các kiến trúc microservice khi mà các service đã được chia rất nhỏ để dễ dàng mở rộng, khôi phục, kiểm kê, tương tác với các service của hệ thống khác … Như vậy làm sao để làm được điều đó Kỹ thuật Event Sourcing ra đời để đáp ứng về mặt kỹ thuật cũng như là về mặt kinh doanh trong các doanh nghiệp Có thể kể đến các ý nghĩa về cả 2 khía cạnh này như sau:

Lịch sử dữ liệu: Event Sourcing cho phép lưu trữ toàn bộ lịch sử của các sự kiện trong hệ thống Điều này giúp giải quyết các vấn đề liên quan đến ghi lại, theo dõi, và kiểm tra lại các thay đổi trong dữ liệu Bằng cách phát lại chuỗi sự kiện, ta có thể tái tạo lại trạng thái của ứng dụng tại bất kỳ điểm thời gian nào, giúp tạo ra khả năng phục hồi dữ liệu và giải quyết vấn đề ghi lại lịch sử của hệ thống.

Cung cấp audit trail: Với Event Sourcing, ta có khả năng theo dõi và kiểm tra lại mọi hành động và thay đổi trong hệ thống Điều này có lợi cho việc theo dõi và kiểm soát quy trình kinh doanh, tuân thủ pháp lệnh và quy định, cũng như giải quyết các vấn đề liên quan đến sự phân tán và ghi lại lịch sử. năng phân tích, đưa ra quyết định dựa trên dữ liệu lịch sử, và phát hiện xu hướng và mẫu thông qua các sự kiện.

Sự nhất quán và phục hồi: Event Sourcing đảm bảo tính nhất quán của dữ liệu và khả năng phục hồi sau các sự cố Bằng cách lưu trữ các sự kiện, ta có thể phục hồi dữ liệu và trạng thái của hệ thống trong trường hợp xảy ra sự cố, lỗi hoặc thất bại.

Hợp tác và tích hợp: Event Sourcing cung cấp khả năng chia sẻ sự kiện giữa các ứng dụng và hệ thống khác nhau Điều này tạo điều kiện cho tích hợp linh hoạt và giao tiếp giữa các thành phần trong một hệ thống phân tán và kết nối với các ứng dụng bên ngoài.

Tóm lại, nhờ vào kỹ thuật EventSourcing các dữ liệu về doanh nghiệp sẽ không bị mất đi Mỗi hành động, thao tác trên dữ liệu đều được lưu lại trong CSDL Điều này cho phép kiểm tra và dự đoán (cả về mặt kỹ thuật và kinh doanh)

1.2.2 Lý do chọn đề tài

Với mong muốn tìm hiểu về một hệ thống được xây dựng trên kiến trúc microservice sẽ bao gồm các thành phần nào, các design pattern nào có thể được sử dụng để có thể xây dựng hệ thống, tại sao lại có hệ thống microservice, và nó ra đời để giải quyết vấn đề gì?

Event Sourcing là một từ khóa trong microservice Thật may mắn, Event Sourcing là một đề tài có trong đồ án 1 của môn học Chính vì thế em đã quyết định chọn Event Sourcing làm đề tài đồ án 1 để có thể nghiên cứu.

Trong đồ án lần này, em sẽ tâm trung nghiên cứu về các thành phần có trong Event Sourcing, tìm hiểu các khái niệm liên quan, và áp dụng những nghiên cứu vào một ứng dụng thực tế để có thể hiểu sâu hơn các kiến thức đã tìm hiểu.

Em sẽ tiến hành nghiên cứu các thành phần có trong Event Sourcing, ưu khuyết điểm,cách hoạt động, tính năng mang lại, cài đặt với kỹ thuật Event sourcing, cài đặt với các microservice tương tác với nhau thông qua message broker

1.2.5 Kết quả hướng tới Ở vai trò cá nhân, em mong muốn mở rộng kiến thức trong lĩnh vực xây dựng hệ thống trong việc áp dụng kỹ thuật EventSourcing đặc biệt là các hệ thống hướng sự kiện Có được một góc nhìn trong tổng thể bức tranh của các hệ thống với kiến trúc microservice ngày nay Cá nhân em đã tự thu thập cho mình những kỹ năng liên quan trong quá trình thực hiện đồ án bao gồm: các phương pháp tiếp cận, công nghệ xây dựng kỹ thuật EventSourcing, quản lí thời gian, thực hiện các khâu trong hệ thống với nhiều công cụ và thư viện Đối với các bạn khác sử dụng tài liệu này như một tài liệu tham khảo; em tin chắc rằng tài liệu này là một bước đệm tốt để có thể dễ dạng định hướng cho việc tìm hiểu sâu thêm.

Công cụ sử dụng

Trong quá trình xây dựng hệ thống, em đã sử dụng phần mềm và công cụ sau:

 Visual Studio Code: IDE hỗ trợ xây dựng ứng dụng

 Postman: Hỗ trợ kiểm thử các API và xem Postman như là một người dùng cuối.

 Pgadmin4: là một công cụ quản lý CSDL mã nguồn mở được phát triển để quản lý và tương tác với CSDL PostgreSQL pgAdmin 4 cung cấp một giao diện đồ họa dễ sử dụng để quản lý các CSDL PostgreSQL.

 MongoDB Compass, MongoExpress: o Là một công cụ quản lý và trực quan hóa CSDL MongoDB, cung cấp giao diện đồ họa dễ sử dụng để khám phá, truy vấn và tương tác với CSDL MongoDB. o MongoDB Compass (DesktopApp) được em sử dụng trong quá trình phát triển, còn MongoExpress (WebApp) được sử dụng sau khi đã đóng gói ứng dụng với Docker.

 Docker: Công cụ đóng gói các stack của ứng dụng.

 EventStore UI: o EventStore là một event database được thiết và lưu trữ quản lí các sự kiện Được xây dựng trên mô hình Event Sourcing và CQRS (Command Query Responsibility Segregation), cho phép lưu trữ dưới dạng chuỗi sự kiện (event stream) thay vì chỉ lưu trữ trạng thái hiện tại của dữ liệu như các database thông thường khác. o EventStore cung cấp một giao diện người dùng cho việc theo dõi các sự kiện diễn ra trong hệ thông, hỗ trợ truy vấn, …

 RabbitMQ UI: o RabbitMQ là một hệ thống phần mềm mã nguồn mở dựa trên mô hình hàng đợi tin nhắn (message queue hay còn gọi là message broker) để quản lý và chuyển giao thông tin giữa các ứng dụng và dịch vụ khác nhau Nó cung cấp một giải pháp cho việc truyền thông bất đồng bộ và phân tán giữa các thành phần của một hệ thống phân tán.

KIẾN THỨC NỀN TẢNG

Event sourcing

Event sourcing là một mẫu thiết kế khi mà tất cả các thao tác nghiệp vụ trên dữ liệu đều được lưu trữ dưới dạng một chuỗi các Event.

Nó được xem là một cách lưu trữ dữ liệu Trái ngược so với cách lưu trữ trước đây, chỉ lưu trạng thái mới nhất của một dòng dữ liệu, thay vào đó Event sourcing lưu trữ trạng thái khi một dòng dữ liệu có sự thay đổi, và mỗi lần thay đổi tương ứng với một Event, một dòng dữ liệu sẽ tương ứng với một chuỗi các Event.

Hình 2 1 Lưu trữ truyền thống với MongoDB

Hình 2 3 Thông tin bên trong một Event

Nhờ vào kỹ thuật này, dữ liệu về nghiệp vụ sẽ không bao giờ bị mất đi Mỗi tác vụ thay đổi dữ liệu đều được đính kèm trong mỗi Event được lưu trữ trong CSDL Điều này cho phép chúng ta xem lại lịch sử dữ liệu thay đổi và dự đoán, là một yếu tố tốt cho cả về vấn đề về kỹ thuật và kinh doanh trong doanh nghiệp.

Event được định nghĩa là một sự thật trong quá khứ Chúng mang một thông tin nào đó được xem đã hoàn thành và dữ liệu được mang theo không bao giờ có thể thay đổi Có thể lấy một ví dụ về Event như “Chiến dịch Điện Biên Phủ năm 1954” được quân dân Việt Nam dành chiến thắng Đây là một sử kiện lịch sử mang thông tin “Việt Nam dành chiến thắng” và sự kiện này không bao giờ có thể thay đổi được Bởi vì những gì xảy ra ở quá khứ nó luôn đúng.

Hình 2 4 Minh họa về chiến thắng điện biên phủ

Tên của Event nên đặt như là đã hoàn thành ở trong quá Ví dụ: “user added”, “order tâm thì nhìn và không quan tâm thì thôi Event trong các hệ thống cũng vậy, được phát đi, các service nào quan tâm đến Event này thì có lắng nghe và phản hồi nếu cần thiết.

Hình 2 5 Minh họa về các event

Tóm lại, các tính chất của Event:

 Bất biến (không thể thay đổi một quá khứ đã diễn ra)

 Có thể hiểu theo nhiều cách khác nhau Ví dụ: Chiến thắng 2-1 của đội tuyển nữ Đức trước đội tuyển nữ Việt Nam ở lượt trận giao hữu đêm ngày 24/06/2023 có thể diễn giải với người hâm mộ ở Đức như là “đây là một chiến thắng bình thường vì chúng ta ở TOP 5”, nhưng đối với người hâm mộ Việt Nam thì xem đây như là một kỳ tích vì “có bàn thắng” trước các đội tuyển hàng đầu thế giới. Event được phát đi trong hệ thống các service khác nhau có thể tiêu thụ Event theo một cách khác nhau. Đây là một khái niệm đơn giản, nhưng có tầm quan trọng rất lớn đối các hệ thống lớn hiện nay.

Stream là một nhóm các Event có cùng logic, liên quan với nhau Trong Event sourcing, stream được đại diện những thực thể (Entity) hoặc cứ hiểu đơn giản Entity như là một dòng dữ liệu trong một bảng Với mỗi Entity thì có một stream, được lưu

Hình 2 6 Stream trong Event store

Event Store hay còn có thể gọi là Event Log được xây dựng để lưu trữ một lượng lớnEvent Chúng ta không cần sợ rằng việc phải tạo quá nhiều stream, tuy nhiên, chúng ta nên xem xét trong một stream có bao nhiêu Event Việc stream có vòng đời ngắn và ítEvent có thể giúp theo dõi và bảo trì hơn.

2.1.4 Thông tin đại diện một Event (Event representation)

Về mặt kỹ thuật có thể coi Event như là một message.

Thông tin Event có thể được mô tả trong các định dạng như JSON, Binary, XML Các định dạng này thường mô tả thông tin như sau:

 id: một id duy nhất đại diện cho một event.

 type: tên của Event, ví dụ: "invoice issued".

 stream id: Một object id, nơi event thuộc về nhóm logic event nào.

 stream position: số thứ tự được sử dụng để quyết định vị trí của của Event trong một stream.

 timestamp: đại diện thời gian tại thời điểm Event xảy ra.

 những metadata như: correlation id, causation id,….

Một ví dụ về thông tin đại diện một Event bởi định dạng JSON.

2.1.5 Lấy trạng thái hiện tại tổng hợp từ những Event

Trong Event Sourcing, trạng thái dữ liệu thay đổi được lưu trữ trong những Event. Event có liên quan đến nhau thì nhóm lại thành một stream Stream được đại diện như một Entity hay có thể hiểu nó là một dòng dữ liệu trong các hệ quản trị CSDL (Relational hoặc document database), mỗi Entity được lưu trữ một chuỗi các Event.

Bảng 2 1 Dữ liệu lưu trữ Entity

Trong ví dụ này, Entity được lưu trữ dưới dạng một chuỗi các Event xảy ra Tương ứng với bản trên sẽ là: ShoppingCartOpened, ProductItemAdded, ProductItemAdded, ProductItemRemoved, ShoppingCartConfirmed.

Một chuỗi Event có thể được mô tả như bên hình dưới:

Hình 2 8 Lưu trữ thông tin "shopping-cart-opened" Event

Hình 2 9 Lưu trữ thông tin "product-item-added" Event

Hình 2 10 Lưu trữ thông tin "product-item-added" Event

Hình 2 11 Lưu trữ thông tin "product-item-removed" Event

Hình 2 12 Lưu trữ thông tin "shopping-cart-confirmed" Event

Vì tất cả thao tác trên đều có liên quan đến thao tác trên cart, cùng một user, tại một khoảng thời điểm Nên tất cả các Event đều có cùng stream: "streamId":

"CART/2023/06/25" , và chúng có “streamPosition” tăng dần. Để có được Entity như bảng trên chúng ta cần phải tính toán tổng hợp lại từ các Event đã có Mỗi Event đều có thứ tự xuất hiện dựa trên “streamPosition”. Để có thể được trạng thái hiện tại của một Entity chúng ta cần thực hiện các bước

“stream aggregation” Dựa trên “stream aggregation” này chúng chúng ta tổng hợp các Event thành một Entity duy nhất Các bước như sau:

 Đọc tất cả Event từ một stream cụ thể.

 Sắp xếp chúng tăng dần theo thứ tự xuất hiện (dựa trên stream position).

 Duyệt qua từng Event theo thứ tự và tính toán tăng dần.

Các bước này được gọi là “stream aggregation” hoặc “state rehydration” Trong mục2.4 chúng ta sẽ đi chi tiết cài đặt với mẫu aggregation.

2.1.6 Nơi lưu trữ Event (Event store)

Nơi lưu trữ Event không cố định bất kỳ trên CSDL nào, miễn là nó đáp ứng được các giả định cơ bản như ban đầu đặt ra Nơi lưu trữ có thể là một CSDL quan hệ (SQL) hoặc CSDL dạng Document (NoSQL như MongoDB), hoặc có thể lưu nó vào một file,

Cách đơn giản nhất là lưu trữ trên ram (in-memory) Event Store có thể được định nghĩa như sau:

Hình 2 13 Đoạn code minh họa lưu trữ trên Ram Đây cũng là một cách lưu trữ nhưng trong các ứng dụng thực tế sẽ không làm như vậy.Bởi vì một Entity có rất nhiều dữ liệu Event, như vậy sau một khoảng thời gian ngắn,service của chúng ta sẽ bị chết do không còn đủ ram, ngoài ra một lý do nữa để từ chối lưu trên ram đó chính là Event được coi là một “Source of truth”, nơi ghi lại những sự kiện sự thật, đây là một tính chất dùng để tái tạo lại hệ thống nếu như hệ thống đó bị chết Nên có thể nói là “Cái gì có thể mất nhưng nơi lưu trữ Event phải luôn sống” Vì vậy khi đi qua phần cài đặt chúng ràng buộc rất chặt chẽ về tính thứ tự xuất hiện của các Event trong mỗi request gửi đi đến phía server.

Trong các CSDL để lưu trữ Event có rất nhiều CSDL được thiết kế chỉ để lưu Event. Một trong số đó có thể kể đến EventStoreDB, được hỗ trợ trong môi trường gRPC và có thể cài đặt được với NodeJS.

Tính năng

Chúng ta luôn có thể tính toán lại lại trạng thái tại bất kỳ thời điểm nào, miễn là những dữ liệu chúng vẫn còn tồn tại trên Event Log (Event Store)

Hình 2 14 Tính năng complete rebuild

Ví dụ trên có thể thấy có 3 Event xảy ra lần lượt đó chính là ProductAdded(10), ProductPurchased(1), ProductPurchased(1) Có thể diễn giải là thêm 10 sản phẩm vào kho và lần lượt trừ đi 1 và 1 bởi một ai đó mua hàng Chúng ta luôn luôn có thể tính toán lại trạng thái hiện tại Đây là một tính năng quan trọng giúp chúng ta có thể phục hồi lại hệ thống.

2.2.2 Quay lại quá khứ và xem những gì xảy ra (Temporal query) Đôi lúc chúng ta cần xem lại những gì đã xảy ra trong quá khứ Đây là một tính năng tuyệt vời có ý nghĩa về mặt kỹ thuật và kinh doanh trong doanh nghiệp.

Hình 2 15 Tính năng Temporal query

Ví dụ: Vào ngày đầu tiên chúng ta thêm một sản phẩm có id = 1, số lượng là 10 vào kho (Inventory) Ngày sau đó có một khách hàng mua một sản phẩm với số lượng là 1, id = 1, customerId = 7 Tiếp tục ngày thứ 3, có một khách hàng khác mua cùng sản phẩm này và có số lượng là một Sản phẩm này tại thời điểm đang xét có tồn kho là 8. Chúng ta có thể quay lại ngày 2 và kiểm tra ai là người mua sản phẩm này, số lượng bao nhiêu, và tại ngày 2 số lượng tồn kho là bao nhiêu.

2.2.3 Lặp lại và phân tích (Event replay)

Với tính chất có thể lặp lại từ các Event đầu tiên trong hệ thống Miễn là Event Store (Event Log) vẫn còn và không bị mất đi dữ liệu trong hệ thống Thì chúng ta đều có thể sử dụng lại và lặp đi lặp lại từng Event để biến đổi thành một thông tin có ích cho mục đích chiến lược kinh doanh, phân tích đánh giá dữ liệu và hành vi người dùng Dự đoán kết quả trong tương lai và phân tích những rủi ro cho mục đích kinh doanh.

Hình 2 16 Minh họa về Event replay

Hệ thống với Event Sourcing có một điểm cần khắc phục là việc quá nhiều Event cần được tổng hợp Như vậy, hệ thống sẽ mất thời gian xử lí.

Có thể lấy ví dụ hệ thống thương mại điện tử của Tiki có hơn 10 năm tồn tại, hệ thống này có thể chứa đến hàng 100 triệu đến 1 tỷ dòng dữ liệu lưu Event Như vậy, một lần tổng hợp để lấy được trạng thái hiện tại của hệ thống là điều không dễ dàng.

Hình 2 17 Tối ưu với snapshot (trước)

Trong hình trên, để ra được con số 123121 thì hệ thống Event sourcing phải đọc từ ban đầu, từ Event với tên PRODUCT ADDED(10).

Có một cách tối ưu, đó chính là chúng ta sẽ xây dựng một bản snapshot lưu trạng thái mới nhất Khi có một Event mới được thêm vào, chỉ cần lấy bản snapshot ra, tính toán kết hợp với Event mới được đưa vào và tạo ra một snapshot mới nhất Như vậy, đây là một cách tối ưu chi phí khi cài đặt Event Sourcing.

Hình 2 18 Tối ưu với snapshot (sau)

Hệ thống sau khi được cài đặt như hình trên sẽ có một bản với snapshot là 123121.Event mới được thêm vào cứ dựa vào snapshot này mà tính toán tiếp.

Lợi ích và bất lợi

Thỉnh thoảng đôi lúc chúng ta muốn theo dõi những gì đã xảy ra trong hệ thống, có thể ví dụ đó là xem lại commit trong Git hoặc Github.

Hình 2 19 Ví dụ về Git minh họa tính năng Audit

Nếu chúng ta gõ lệnh “git log” vào một thư mục được cấu hình Git:

Hình 2 20 Sau khi gõ "Git log" trong Git

 Hệ thống có nhiều luồng đọc hơn là ghi.

Hình 2 21 Tính năng Parallel processing Ở hình trên, có thể thấy là mỗi một service có thể đọc cùng một Event Log (Event Store) Các service1, service2, service3 cùng đọc chung một nguồn và lưu vào Event Log của chính service đó.

Lấy một ví dụ cụ thể hơn với các Recommendation, Analytics, Inventory service cùng đọc một Event Log của một service khác là Order

Hình 2 22 Ví dụ tính năng Parallel processing được người dùng mua nhiều nhất để từ đó đưa ra các đề xuất về sản phẩm để tối ưu trải nghiệm người dùng Đối với Analytics sẽ đọc Event Log của Order và phân tích kinh doanh đưa ra các quyết định về kinh doanh Ví dụ như kinh doanh món này sẽ tốt chỉ vào mùa xuân, hay sản phẩm này được người dùng mua nhiều nên sẽ nhập hàng này về nhiều Còn đối với Inventory service, sau khi đọc Event Log của Order sẽ trừ tồn kho.

Như vậy có thể thầy cùng một nơi lưu trữ Event có thể đọc được từ nhiều service khác nhau, mỗi service có thể hiểu riêng cho mình theo một cách nào đó và thực hiện nghiệp vụ của riêng chính bản thân service đó.

2.3.3 Nhất quán ở một thời điểm nhất định (Eventual consistency)

Một điểm yếu của hệ thống Event sourcing là tính bất đồng bộ Đây là một điểm yếu chung của hầu hết các hệ thống microservice và chúng ta cần phải chấp nhận và giải quyết nó Mô tả như sau:

 Không hẳn là tất cả hệ thống, service khác cùng đọc Event tại một thời điểm của một Event Log.

 Độ trễ giữa những lần đọc.

Lấy ví dụ về 3 service khác nhau cùng đọc một Event Log.

Lý giải cho sự khác nhau này có một lí do chung nhất đó chính là các hệ thống thường phân tán và các service gọi nhau phải thông qua hệ thống mạng khắp mọi nơi, vấn đề này nảy sinh ra nhiều vấn đề bất đồng bộ Lý do thứ hai đó chính là hệ thống luôn sẵn sàng ghi, chính vì vậy nhiều service khi đọc sẽ cho ra nhiều kết quả khác nhau.

Hình 2 24 Về Eventual consistency sau khi không ghi một thời gian

Hệ thống với Event Sourcing chấp nhận và giải quyết bằng cách tại một thời điểm nào đó, khi hệ thống được đọc không còn được ghi vào nữa thì sẽ đồng bộ dữ liệu ở ba service Đây còn gọi là Eventual Consistency hay nhất quán dữ tại một thời điểm.

2.4 Các thành phần quan trọng khi cài đặt Event Sourcing

Trong Event sourcing, Projections (cũng có thể được biết như là View Models hoặc làQuery Model) cung cấp một góc nhìn xem mô hình dữ liệu (data model) dựa trênEvent Thông thường chúng đại diện logic biến đổi từ nguồn mô hình dữ liệu ghi(write model) sang nguồn mô hình dữ liệu đọc (read model) Projections được sử dụng trong cả read model và write model.

Hình 2 25 Tổng quan về projection

Một tình huống phổ biến trong ngữ cảnh nhận Event được tạo từ write model (ví dụ: InvoiceIssued, OrderPlaced, PaymentSubmitted, OrderItemAdded, InvoicePaid, OrderConfirmed) và tính toán nó thành trong read model (ví dụ: một hóa đơn tổng hợp chứa số hóa đơn, mặt hàng chưa thanh toán, ngày hết hạn, …) Loại đối tượng sau khi tính toán có thể được lưu vào một CSDL nào đó cho mục đích truy vấn. Điểm kết thúc của một chuỗi sự kiện này cũng có thể là điểm bắt đầu tổng hợp thành một chuỗi sự kiện khác Ví dụ: Có thể lấy các sự kiện liên quan đến một đơn đặt hàng trước đó, tính tổng giá và tạo một hóa đơn có trạng thái chưa thanh toán và đặt nó trong một stream khác.

Một dạng khác của projection còn được gọi là stream aggregation Đó là quá trình tính toán lại trạng thái hiện tại dựa trên stream Trong suốt quá trình aggregation, các event được duyệt qua từng cái một theo đúng thứ tự nó xuất hiện Mục đích chính của stream aggregation chính là để tái tạo lại trạng thái hiện tại, kiểm tra một cái command đã được thi với nó.

Hình 2 27 Projection trong write model

Là một quá trình xử lí real-time dành cho Event sau khi được lưu vào CSDL.

Subscriptions là một thành rất thiết yếu trong quá trình xây dựng hệ thống với Event- sourced Chúng hỗ trợ một loạt các tác vụ sau:

 Tạo một event mới trong quá trình xử lí.

 Event được lưu trữ trong Event Store.

 Command đã được duyệt qua, và transaction đã hoàn thành.

 Tất cả các read model lấy event từ Event Store và thực hiện một tác vụ nào đó nếu cần thiết.

 Chuyển giao Event đến report model.

 Chuyển Event đến một service, hệ thống khác thông qua message broker.

Subscriptions có thể đăng ký theo dõi tại bất kỳ vị trí nào trong một stream, nhưng thông thường chúng ta muốn vị trí bắt đầu của một stream, điều này cho phép xử lí lịch sử Event Đối với các mục đích tương tác với các service, hệ thống khác, thông thường sẽ đăng ký theo dõi ngay tại thời điểm đó, vì việc chuyển Event từ hệ thống này sang hệ thống kia sẽ tạo ra các kết quả không mong muốn.

Một subscription có thể phục vụ nhiều event handler Thông thường, chúng ta xác định một nhóm các event handler, cái mà được trigger cùng nhau, và nhóm chúng lại trong một subscription Điều này tránh được tình huống như sau: 2 read model cùng lấy thông tin được cập nhật mới nhất nhưng tốc độ lấy là khác nhau và dẫn tới việc kết quả giữa 2 read model không đồng bộ khi cung cấp thông tin cho người dùng.

Ví dụ: Vị trí của xe

Hãy tưởng tượng trong một stream, thông tin của một Event chứa vị trí của xe hiện tại và trạng thái của xe đó như Parked, Moving và Idle Hệ thống sẽ có 2 subscription độc lập phục vụ 2 read model projection – một cái là cho biết vị trí mới nhất của xe, cái còn lại cho biết trạng thái của xe Hai subscription (theo một xác xuất nào đó) đó dễ dàng mất đồng bộ về dữ liệu với nhau, bởi vì Event thông tin về vị trí của xe thường xuyên được cập nhật, trong khi trạng thái của xe thì cập nhật ít hơn khi cả 2 cùng lưu xuống CSDL Chính vì vậy dễ gặp tình trạng là xe thì đang ở chạy nhưng trạng thái của xe là Parked. Để giải quyết vấn đề này chúng ta cần kết hợp 2 projection trong cùng một subscription, chúng có thể làm chậm đi, nhưng trải nghiệm người dùng sẽ tốt hơn và

Một trong những lỗi sai lớn nhất của moị người khi xây dựng một ứng dụng event- sourced đó chính là không thể giải quyết vấn đề realtime subscription Đôi lúc lập trình viên cần phải tương tác với các service, hệ thống bên ngoài sau khi nhận một Event mới Có khá nhiều cách tiếp cận vấn đề này, lỗi mà mọi người thường gặp nhất đó chính là two-phase commit.

Khi tương tác với các ứng dụng ở hạ tầng khác trong cùng một transaction, rủi ro từ các tác vụ này có thể thất bại Ví dụ đoạn code phía bên dưới, đây là một lỗi phổ biến:

Hình 2 28 Minh họa về two phase commit

Các thành phần quan trọng khi cài đặt microservice

2.5.1 Mẫu thiết kế Saga (Saga pattern)

Saga là một pattern cung cấp cách giao tiếp nhất quan dữ liệu giữa các microservice với nhau Saga thực hiện tuần tự các transaction cái mà nó sẽ cập nhật dữ liệu mỗi service và publish một message hoặc event để trigger một transaction tiếp theo Nếu thất bại ở một bước nào đó, saga sẽ thực hiện lại các transaction tính toán lại các transaction đã thực hiện trước đó.

Mô tả vấn đề: Đối với hệ thống monolithic thì các module sẽ tương tác lẫn nhau và dùng chung mộtCSDL.

Hình trên có thể thấy rằng Inventory, Shipping, Payment service cùng sử dụng chung một CSDL Nếu thực hiện một transaction, chúng ta chỉ cần phải tương tác giữa các module này với nhau và cùng gọi chung một CSDL để xử lí

Ví dụ: Khi một người dùng đặt hàng

Khi một người dùng mua một sản phẩm thì hệ thống sẽ xử lí gọi Payment module để tạo hơn đơn, tiếp đến sẽ gọi đến Inventory module để khấu trừ kho Sau khi khấu trừ kho xong sẽ tiếp tục gọi Shipping module để bàn giao đến đơn vị vận chuyển và cuối cùng sẽ chuyển thông tin người mua đến Recommendation module để tạo hệ thống đề xuất cho khách hàng.

Tất cả các hành động trên đều thực hiện trong một transaction.

Hình 2 33 Trong một transaction của Monolithic

Khi ở trong một transaction sẽ thỏa mãn ACID:

 Isolation (tính cô lập): các transaction không tác động lẫn nhau trong quá trình thực thi

 Durability (tính bền vững): dữ liệu được ghi sẽ được lưu trữ và không bị mất đi nếu xảy ra sự cố hệ thống. Đối với kiến trúc microservice thì mỗi một service sở hữu cho mình một CSDL riêng. Làm sao để đảm bảo ACID trong hệ thống microserice  Mẫu thiết kế Saga ra đời để giải quyết vấn đề đó.

Mẫu saga cung cấp cách quản lí transaction bằng cách tuần tự chạy các local transaction Một local transaction là một công việc nguyên khối Mỗi local transaction cập nhật chính CSDL của nó rồi publish một message hoặc một event để trigger một local transaction tiếp theo Nếu có một local transaction nào thất bại, saga sẽ thực thi một chuỗi các hành động đền bù để hệ thống có thể trở lại như lúc ban đầu chưa thực hiện. Ở góc nhìn này chúng ta coi mỗi local transaction là một công việc và tất cả phải hoàn thành hoặc không có cái nào được thực thi Gom tất cả các local transaction ta được

Có hai cách triển khai mẫu saga:

Hình 2 36 Hai cách cài đặt saga trong MSA

Một là Choreography và cái còn lại là Orchestration.

Hình 2 37 Cách cài đặt "Orchestration"

 Sẽ có một service trung tâm đảm nhiệm điều phối tất cả các việc gọi service khác một cách đúng thứ tự.

 Đảm bảo nếu có một thao tác nào thất bại sẽ thực hiện đền bù.

 Các service có thể phản hồi hoặc không phản hồi nếu như service đó quan tâm đến một Event nào đó Ngược lại, không quan tâm thì không làm gì cả

2.5.2 Kiến trúc hướng sự kiện (Event Driven Architecture)

Kiến trúc hướng sự kiện (EDA) sử dụng Event để trigger và giao tiếp giữa những decoupled service và phổ biến trong các ứng dụng hiện đại xây dựng với kiến trúc microservice.

EDA thường bao gồm tối thiểu 3 thành phần chính:

 Producer: Nơi tạo ra những Event bởi một hành động nào đó

 Broker: Một nơi trung gian để chuyển các Event đi

 Comsumer: Nơi tiêu thụ Event

Hình 2 39 Các thành phần trong EDA

Các thành phần trong EDA sử dụng mẫu “Publish/Subscribe” để giao tiếp lẫn nhau.

 Lưu trữ Event (Event persistence) Đảo ngược sự phụ thuộc (Dependency Inversion)

Trong các ứng dụng không sử dụng EDA thì các service1 gọi đến service2 Khi service 1 gọi đến 2, thì 1 phải biết sử tồn tại của 2 Vì vậy nếu 2 chết thì cả hệ thống sẽ chết theo.

Hình 2 40 Sự phụ thuộc giữa các service khi không có EDA Đối với EDA thì sử phụ thuộc này sẽ bị đảo ngược lại Service 1 chỉ cần gửi Event đến Broker và service 1 không cần quan tâm đến bất kỳ điều gì khác nữa Còn đối với service 2, chỉ cần quan tâm đến những Event nào mà service có hứng thú Service 2 có thể phản hồi đến service 1 hoặc nhận được Event nhưng không làm gì cả Đây chính là sự khác biệt.

Hình 2 41 Sự phụ thuộc giữa các service khi có EDA

Bởi vì tính chất đảo ngược sự phụ thuộc trong EDA Chính vì vậy cho phép mỗi service độc lập Service 1 không cần thiết service 2 phải tồn tại, không gây chết hệ thống Khi nó độc lập như vậy, ta có thể viết logic nơi mà service đó thuộc về, dễ dàng tháo lắp.

Trong EDA dễ dàng mở rộng theo chiều ngang Nếu có một service mới nào được viết mới chỉ cần thêm vào, không cần phải sửa logic để có thể chạy được Thêm một service mới chỉ cần subscribe broker.

Hình 2 42 Tính mở rộng trong EDA

Lưu trữ Event (Event persistence) :

Khi giao tiếp giữa các service với nhau bằng cách sử dụng Event, Event có thể được lưu trữ trong broker, và nhưng thông tin trong Event được sử dụng để chuyển đến một

Hình 2 43 Event persistence trong EDA

Không điểm chết (No single point of failure) :

Khi mà Event được lưu trữ tại broker thì đây là một tính năng tuyệt với để hệ thống không có điểm chết, trở nên mạnh mẽ, thông minh hơn.

Hình 2 44 "Single point of failure"

Khi giao tiếp giữa 2 service theo cách thông thường “request và response”, hệ thống

Trong EDA sẽ có một broker, khi Event được gửi đi sẽ chuyển trực tiếp đến Broker này và được lưu trữ lại cho đến khi service tiêu thụ được Event đó mới thôi Điều này cho phép chúng trở nên linh hoạt hơn.

 Sự nhất quán (Eventual Consistency)

Thay vì các service gọi trực tiếp lẫn nhau và chờ cho đến khi nào thành công, thì giờ đây lại có thêm một thành phần được gọi là Broker Để đánh đổi yếu tố dễ mở rộng (Scalability) thì hiệu suất sẽ bị giảm đi Sẽ phải thêm một trung gian, như vậy hệ thống sẽ chậm đi.

Hình 2 46 Minh họa về Eventual Consistency

Sự bất đồng bộ nãy thường diễn ra khi các service cùng tiêu thụ một Event tại các thời điểm khác nhau.

XÂY DỰNG HỆ THỐNG

Giới thiệu chung về bài toán

Bài toán eShopping Cart là một bài toán quan trọng trong lĩnh vực thương mại điện tử, liên quan đến quản lý và xử lý giỏ hàng của khách hàng trên một trang web bán hàng trực tuyến.

Trong mô hình eShopping Cart, khách hàng có thể duyệt qua danh sách sản phẩm trên trang web, lựa chọn các sản phẩm mình muốn mua và thêm vào giỏ hàng Giỏ hàng này giống như một giỏ thực tế, nơi khách hàng có thể thêm, xóa hoặc chỉnh sửa số lượng của từng sản phẩm Sau khi khách hàng đã hoàn tất việc mua hàng, họ có thể tiến hành thanh toán và hoàn tất quá trình đặt hàng. eShopping Cart cung cấp nhiều tính năng hữu ích để tăng trải nghiệm mua sắm của khách hàng, bao gồm:

Thêm và xóa sản phẩm: Khách hàng có thể dễ dàng thêm sản phẩm vào giỏ hàng bằng cách chọn từ danh sách sản phẩm hoặc nhập mã sản phẩm Họ cũng có thể xóa sản phẩm khỏi giỏ hàng nếu muốn.

Chỉnh sửa số lượng: Khách hàng có thể điều chỉnh số lượng của từng sản phẩm trong giỏ hàng Họ có thể tăng hoặc giảm số lượng sản phẩm một cách linh hoạt.

Tính toán tổng giá trị: eShopping Cart tính tổng giá trị của giỏ hàng dựa trên số lượng và giá của từng sản phẩm Điều này giúp khách hàng biết được tổng số tiền họ phải thanh toán trước khi tiến hành thanh toán.

Lưu trữ thông tin: eShopping Cart thường lưu trữ thông tin sản phẩm trong giỏ hàng của khách hàng trong suốt quá trình mua sắm Điều này giúp khách hàng không mất thông tin giỏ hàng khi tạm thời rời khỏi trang web hoặc tắt máy tính.

Kiểm tra tính khả dụng: Trước khi khách hàng thực hiện thanh toán, eShopping Cart thường kiểm tra tính khả dụng của sản phẩm trong giỏ hàng Nếu sản phẩm không còn trong kho hoặc không có đủ số lượng, hệ thống có thể cảnh báo cho khách hàng và yêu

Bài toán eShopping Cart thường được xử lý thông qua các ngôn ngữ lập trình phía Backend như TypeScript trong môi trường NodeJS và các hệ thống quản lý CSDL để lưu trữ thông tin sản phẩm và giỏ hàng của khách hàng.

Qua việc quản lý và xử lý giỏ hàng của khách hàng, eShopping Cart đóng vai trò quan trọng trong quá trình mua sắm trực tuyến, đảm bảo sự thuận tiện và tin cậy cho khách hàng.

Dựa vào kiến thức trong quá trình tìm về Event Sourcing và Microservice, em đã quyết định phát triển bài toán nhỏ eShopping Cart thành một bài toán gồm 2 service: Cart service và Inventory service Trong đó Cart service sẽ đảm bảo các logic về Cart: Tạo phiên giỏ hàng, thêm bớt và điều chỉnh số lượng, xác nhận đặt hàng, còn Inventory service sẽ đảm bảo các logic về quản lí sản phẩm trong kho như: Thêm mới/ xóa sản phẩm, điều chỉnh số lượng, kiểm tra tồn kho, kiểm tra sản phẩm với id hợp lệ, cập nhật thông tin về sản phẩm, khấu trừ sản phẩm khi được cart service yêu cầu Hai service này giao tiếp với nhau thông qua một trung gian được gọi là Message Broker. Mỗi service tự trang bị về các kỹ thuật Event sourcing.

Với Cart service tầm khoảng 5 API và Inventory service tầm khoảng 6 API Được hỗ trợ thông qua công cụ Postman.

3.1.3 Công cụ, công nghệ sử dụng

Ngôn ngữ lập trình sử dụng là Typescript trên môi trường NodeJS Kết hợp với thư viện RestAPI như là ExpressJS Một số các package uuid (để tạo uuid), http-errors(đưa format trả về người dùng chung một dạng duy nhất), dotenv, một số thư viện để

Phân tích

3.1.4.1 Yêu cầu về chức năng

Chức năng Visitor Inventory service

Tạo phiên giỏ hàng mới X

Thêm sản phẩm vào giỏ X

Xóa sản phẩm khỏi giỏ X Điều chỉnh số lượng sản phẩm X

Xác nhận giỏ (khấu trừ sản phẩm trong kho) X X

Kiểm tra sản phẩm tồn tại X X

Bảng 3 1 Chức năng của cart service

Chức năng Visitor Cart service

Xem tất cả các sản phẩm hiện có X

Cập nhật thông tin sản phẩm X

Khấu trừ sản phẩm trong kho X X

Kiểm tra sản phẩm tồn tại X X

\ Bảng 3 2 Chức năng của inventory service

3.1.4.2 Yêu cầu phi chức năng

 Ràng buộc (Revision) chặt chẽ về phiên bản của Entity.

 Yêu cầu trả lại người dùng dưới 1 giây

 Thông báo từ server phải rõ ràng Định dạng trả về của mỗi request là JSON message thông báo trạng thái của request, thông tin về lỗi (nếu có lỗi từ người hoặc lỗi từ server).

 Tất cả các request đối với cart service phải đính kèm Etag, kiểm thử đối với Postman, và trả lại trạng thái mới nhất của Etag sau mỗi request để sử dụng cho các request sau.

Hình 3 1 Sơ đồ use-case cart-service

Hình 3 2 Sơ đồ use-case inventory-service

3.2.3.1 Xem trạng thái giỏ hàng

Tên use-case Xem trạng thái giỏ hàng

Mô tả Người dùng xem trạng thái giỏ hàng của chính mình, xem thử có bao nhiêu sản phẩm, số lượng bao nhiêu.

Sự kiện kích hoạt API “Get all product” được gọi Điều kiện trước Cung cấp ClientId

Cung cấp ShoppingCartId Điều kiện sau Trả về kết quả dưới định dạng JSON bao gồm mã trạng thái http, message thông báo, dữ liệu.

Luồng chính 1 Nhập clientId, shoppingcartId trên url

3 Hệ thống lấy tất cả các sản phẩm có trong giỏ thuộc ClientId, thuộc phiên giỏ ShoppingCartId

4 Trả danh sách sản phẩm Với mỗi sản phẩm bao gồm id và số lượng (quantity)

Luồng thay thế 1a Nhập clientId, shoppingCartId sai Hệ thống trả về kết quả không tìm thấy.

Luồng ngoại lệ 3a MongoDB không thể kết nối.

Tên use-case Tạo phiên giỏ hàng

Mô tả Tạo một phiên giỏ hàng mới

Sự kiện kích hoạt API “Open Shopping Cart” được gọi Điều kiện trước Cung cấp ClientId Điều kiện sau Trả về kết quả dưới định dạng JSON bao gồm mã trạng thái http, message thông báo, dữ liệu gồm id của shopping card được tạo mới.

Luồng chính 1 Nhập clientId trên url

3 Hệ thống tạo một Event “ShoppingCartOpened” lưu vào EventStoreDB

4 Hệ thống tạo dữ liệu về cart lưu trong MongoDB.

5 Trả về trạng thái thành công.

Luồng ngoại lệ 3a EventStoreDB không thể kết nối.

4a MongoDB không thể kết nối.

Bảng 3 4 Đặc tả tạo phiên giỏ hàng

3.2.3.3 Thêm/ điều chỉnh số lượng sản phẩm vào giỏ

Tên use-case Thêm sản phẩm vào giỏ

Mô tả Người dùng chọn sản phẩm mong muốn và thêm vào giỏ, nếu sản phẩm có id đã tồn tại thì cộng dồn.

Sự kiện kích hoạt API “Add Product Item” được gọi Điều kiện trước Cung cấp ClientId, ShoppingCartId, phiên bản Etag Điều kiện sau Trả về kết quả dưới định dạng JSON bao gồm mã trạng thái http, message thông báo thành công.

Luồng chính 1 Nhập clientId, shopping cart id trên url

2 Nhập phiên bản của Etag

3 Nhập id, quantity của sản phẩm trong body.

5 Hệ thống tạo một Event “ProductItemAdded” lưu vào EventStoreDB.

6 Kiểm tra sản phẩm với id có tồn tại hay không?

7 Hệ thống cập nhật dữ liệu về cart trong MongoDB.

3.2.3.4 Xóa/ điều chỉnh số lượng sản phẩm khỏi giỏ

Tên use-case Xóa sản phẩm khỏi giỏ

Mô tả Người dùng chọn sản phẩm mong muốn xóa và xóa, nếu nếu sản phẩm có id đã tồn tại thì trừ bớt đi

Sự kiện kích hoạt API “Add Product Item” được gọi Điều kiện trước Cung cấp ClientId, ShoppingCartId, phiên bản Etag Điều kiện sau Trả về kết quả dưới định dạng JSON bao gồm mã trạng thái http, message thông báo thành công.

Luồng chính 1 Nhập clientId, shopping cart id trên url

2 Nhập phiên bản của Etag

3 Nhập id, quantity của sản phẩm trong body.

5 Hệ thống tạo một Event “ProductItemRemoved” lưu vào EventStoreDB.

6 Hệ thống cập nhật dữ liệu về cart trong MongoDB.

7 Trả về trạng thái thành công.

Luồng thay thế Nhập sai dữ liệu ở bước 1 Trả về kết quả không tìm thấy.

Nhập sai dữ liệu ở bước 2 Trả về kết quả không khớp phiên bản hiện tại.

Nhập sai dữ liệu ở bước 3 Trả về kết quả thông tin ở body không đúng.

Luồng ngoại lệ 5a EventStoreDB không thể kết nối.

7a MongoDB không thể kết nối.

Bảng 3 6 Đặc tả Xóa/ điều chỉnh số lượng sản phẩm khỏi giỏ

Tên use-case Xác nhận giỏ hàng

Mô tả Người dùng trước khi đi tới bước thanh toán thì cần xác nhận giỏ hàng, và giỏ hàng này sẽ không còn được điều chỉnh.

Sự kiện kích hoạt API “Confirm Shopping Cart” được gọi Điều kiện trước Cung cấp ClientId, ShoppingCartId, phiên bản Etag Điều kiện sau Trả về kết quả dưới định dạng JSON bao gồm mã trạng thái http, message thông báo thành công.

Luồng chính 1 Nhập clientId, shopping cart id trên url

2 Nhập phiên bản của Etag

4 Hệ thống tạo một Event

5 Thực hiện khấu trừ số lượng sản phẩm trong Inventory service.

6 Hệ thống cập nhật dữ liệu về cart trong MongoDB.

7 Trả về trạng thái thành công.

Nhập sai dữ liệu ở bước 3 Trả về kết quả thông tin ở body không đúng.

Luồng ngoại lệ 4a EventStoreDB không thể kết nối.

5a Event được bắn đi nhưng không lắng nghe được kết quả trả về.

7a MongoDB không thể kết nối.

Bảng 3 7 Đặc tả Xác nhận giỏ hàng

3.2.3.6 Xem tất cả các sản phẩm hiện có trong kho

Tên use-case Xem tất cả các sản phẩm hiện có trong kho

Mô tả Người dùng xem tất cả sản phẩm hiện có trong kho

Sự kiện kích hoạt API “Get all product” được gọi Điều kiện trước Điều kiện sau Trả về kết quả dưới định dạng JSON bao gồm mã trạng thái http, message thông báo, danh sách các phẩm.

Luồng chính 1 Nhấn gửi một request

2 Hệ thống lấy tất cả các sản phẩm có trong kho

3 Trả về danh sách các sản phẩm.

Luồng ngoại lệ 2a Postgres không thể kết nối.

Bảng 3 8 Đặc tả Xem tất cả các sản phẩm hiện có trong kho

3.2.3.7 Thêm sản phẩm vào kho

Tên use-case Thêm sản phẩm vào kho

Mô tả Người dùng thêm sản phẩm vào kho.

Sự kiện kích hoạt API “Add new product” được gọi Điều kiện trước Cung cấp thông tin về sản phẩm Điều kiện sau Trả về kết quả dưới định dạng JSON bao gồm mã trạng thái http, message thông báo.

Luồng chính 1 Cung cấp thông tin về sản phẩm trong body.

3 Hệ thống tạo một Event “ProductCreated” lưu vào EventStoreDB.

3.2.3.8 Xóa sản phẩm khỏi kho

Tên use-case Xóa sản phẩm khỏi kho

Mô tả Người dùng xóa sản phẩm vào kho.

Sự kiện kích hoạt API “Delete product” được gọi Điều kiện trước Cung cấp id sản phẩm Điều kiện sau Trả về kết quả dưới định dạng JSON bao gồm mã trạng thái http, message thông báo.

Luồng chính 1 Cung cấp thông tin về id sản phẩm trong url.

3 Hệ thống tạo một Event “ProductDeleted” lưu vào EventStoreDB.

4 Hệ thống xóa dữ liệu về sản phẩm trong PostgresDB.

5 Trả về trạng thái thành công.

Luồng thay thế 1a Nhập id không hợp lệ Trả về kết quả không tìm thấy. Luồng ngoại lệ 3a EventStoreDB không thể kết nối.

4a PostgresDB không thể kết nối.

Bảng 3 10 Đặc tả Thêm sản phẩm vào kho

3.2.3.9 Cập nhật số lượng sản phẩm trong kho

Tên use-case Cập nhật số lượng sản phẩm trong kho.

Mô tả Người dùng cập nhật số lượng sản phẩm.

Sự kiện kích hoạt API “Deduct quantity” hoặc “Add quantity” được gọi Điều kiện trước Cung cấp id, số lượng sản phẩm Điều kiện sau Trả về kết quả dưới định dạng JSON bao gồm mã trạng thái http, message thông báo.

Luồng chính 1 Cung cấp thông tin về id sản phẩm trong url.

2 Cung cấp số lượng điều chỉnh

4 Hệ thống tạo một Event “ProductAddQuantity” hoặc “ProductDeductQuantity” lưu vào EventStoreDB.

5 Hệ thống cập nhật dữ liệu về sản phẩm trong PostgresDB.

6 Trả về trạng thái thành công.

Luồng thay thế 1a Nhập id không hợp lệ Trả về kết quả không tìm thấy. Luồng ngoại lệ 4a EventStoreDB không thể kết nối.

5a PostgresDB không thể kết nối.

Bảng 3 11 Đặc tả Cập nhật số lượng sản phẩm trong kho

3.2.3.10 Cập nhật thông tin sản phẩm trong kho

Tên use-case Cập nhật thông tin sản phẩm trong kho. Điều kiện sau Trả về kết quả dưới định dạng JSON bao gồm mã trạng thái http, message thông báo.

Luồng chính 1 Cung cấp thông tin về id sản phẩm trong url.

2 Cung cấp thông tin cần cập nhật.

4 Hệ thống tạo một Event “ProductUpdateInfo” lưu vào EventStoreDB.

5 Hệ thống cập nhật dữ liệu về sản phẩm trong PostgresDB.

6 Trả về trạng thái thành công.

Luồng thay thế 1a Nhập id không hợp lệ Trả về kết quả không tìm thấy. Luồng ngoại lệ 4a EventStoreDB không thể kết nối.

5a PostgresDB không thể kết nối.

Bảng 3 12 Đặc tả Cập nhật thông tin sản phẩm trong kho

Thiết kế

 API gateway: Dùng để chuyển các request của client đến đúng các service, thiết kế theo hướng cài đặt server-side.

 Service discovery: Dùng để lưu trữ các địa chỉ IP của service, được thiết kế theo cách cài đặt là Thirt-party-registration.

 Message broker: Giao tiếp giữa các MS với nhau thông qua pub/sub pattern.

 Cart service: Chứa logic của cart và dữ liệu được lưu trữ ở MongoDB

 Inventory service: Chứa logic inventory và được dữ liệu được lưu trữ ở PostgresDB.

Hình 3 4 Kiến trúc bên trong một service Ở hình trên mô tả kiến trúc bên trong một service gồm 3 thành phần chính:

 API Layer validation of request: Kiểm tra các request đầu vào có hợp lệ hay không? o Command: Đối với mỗi thao tác người dùng thì sẽ có một command tương ứng Đầu tiên sẽ tạo một event tương tứng với command (Event init), tiếp đến là sẽ load hết tất cả các event của stream đó trong EventStore bằng cách lặp qua stream (agregate), đối với mỗi event sẽ có EventHandler chứa logic xử lí event tương ứng Sau khi hợp lệ thì sẽ được append đến EventStore. o Query: Lắng nghe sự thay đổi bên trong EventStoreDB và thực hiện một số thao tác đã được định nghĩa

 Repository Layer (ORM) data logic: Chứa các logic xử lí dữ liệu, đối với inventory thì dùng ORM là sequelize.

Hình 3 5 Một góc nhìn khác về kiến trúc

Hình bên mô tả một góc nhìn khác:

 Domain model: Lõi của ứng dụng nằm đây, chứa tất cả bussiness functionality được đóng gói Đây là nơi business logic được cài đặt.

 Command: Nhận một command từ hệ thống bên ngoài và chuyển nó nên domain model Chịu trách nhiệm validate command, gọi domain và quản lí persistence.

 Một event mới được tạo và được lưu trữ bên trong event store, CSDL này phải đáp ứng real-time subscriber.

 Event store sẽ được chuyển đến các subscriber Subscriber có thể tạo một public event đi ra một hệ thống bên ngoài (bên trái), và một subscriber còn lại chịu trách nhiệm cho việc project event đến các CSDL khác (bên phải) Nơi mà CSDL được dùng cho mục đích query và analytic.

CSDL cho inventory service (PostgresDB):

INVENTORY(id, product_id, quantity, name, price, desc, status, revision, created_at, last_updated)

Tân từ: Quan hệ INVENTORY lưu trữ thông tin của sản phẩm gồm có các thuộc tính: định danh sản phẩm, số lượng, tên, mô tả, giá, tình trạng, phiên bản dữ liệu, thời gian tạo, thời gian chỉnh sửa lần cuối Mỗi sản phẩm phân biệt với nhau bởi id đây là trường được chọn làm khóa chính thay vì product_id nhằm tạo sự linh hoạt khi cập nhật dữ liệu, trường tình trạng cho biết dòng dữ liệu này đang ở trong tình trạng nào như là: có sẵn, hết hàng, ngừng cung cấp bởi nhà cung cấp, đã xóa Trường phiên bản dữ liệu (revision) mô tả số lần sửa đổi dữ liệu.

Tân từ: Quan hệ CHECKPOINT lưu trữ thông tin của điểm xử lí hiện tại trong EventSourcing Trường id là một chuỗi mô tả Checkpoint của subscription Trường position

Tân từ: Tài liệu SHOPPINGCARTDETAILS lưu trữ thông tin giỏ hàng của người dùng bao gồn các thuộc tính: định danh tài liệu document bằng objectId, định danh giỏ hàng, định danh khách hàng, trạng thái của giỏ hàng, các sản phẩm nằm trong giỏ, phiên bản chỉnh sửa tài liệu, ngày tạo phiên giỏ hàng, thời gian xác nhận thanh toán. Mỗi sản phẩm phân biệt với nhau bởi một objectId, trường dữ liệu tình trạng cho biết giỏ hàng đang một trong các tình trạng sau: được mở, đã xác nhận, đã hủy, đã đóng. Trường dữ liệu danh sách sản phẩm (productItems) mô tả danh sách sản phẩm hiện có trong giỏ, mỗi sản phẩm bao gồm id và số lượng Trường phiên bản dữ liệu (revision) mô tả số lần sửa đổi dữ liệu.

Tân từ: Quan hệ CHECKPOINT lưu trữ thông tin của điểm xử lí hiện tại trong Event Sourcing Trường id là một chuỗi mô tả Checkpoint của subscription Trường position mô tả điểm xử lí hiện tại của Checkpoint đó Các checkpoint của các subscription phân biệt với nhau thông qua id.

CSDL lưu trữ Event (EventStoreDB):

Trong stream của cart bao gồm những Event sau:

ShoppingCartOpened(type, data(shoppingCartId, clientId, openedAt))

Tân từ: Event ShoppingCartOpened lưu trữ thông tin Event bao gồm 2 trường dữ liệu là type và data Trường dữ liệu type chính là tên của Event, trường data là một object gồm 3 thuộc tính: shoppingCartId, clientId, openedAt Trong Event khi mở phiên giỏ hàng cần có id của giỏ, id của khách hàng và thời gian mở.

ProductItemAdded(type, data(shoppingCartId, productItem(productId, quantity)))

Tân từ: Event ProductItemAdded lưu trữ thông tin Event bao gồm 2 trường dữ liệu là type và data Trường dữ liệu type chính là tên của Event, trường data là một object gồm 2 thuộc tính: shoppingCartId, productItem Trong Event khi thêm vào giỏ hàng cần có id của giỏ, thông tin sản phẩm bao gồm productId và số lượng (quantity).

ProductItemRemoved(type, data(shoppingCartId, productItem(productId, quantity))) gồm 2 thuộc tính: shoppingCartId, productItem Trong Event khi xóa sản phẩm khỏi giỏ hàng cần có id của giỏ, thông tin sản phẩm bao gồm productId và số lượng cần xóa (quantity).

ShoppingCartConfirmed(type, data(shoppingCartId, confirmedAt))

Tân từ: Event ShoppingCartConfirmed lưu trữ thông tin Event bao gồm 2 trường dữ liệu là type và data Trường dữ liệu type chính là tên của Event, trường data là một object gồm 2 thuộc tính: shoppingCartId, confirmedAt Trong Event khi xác nhận giỏ hàng cần có id của giỏ, thời điểm xác nhận.

Trong stream của inventory gồm các Event sau:

ProductCreated(type, data(productId, quantity, name, price, desc, createdAt))

Tân từ: Event ProductCreated lưu trữ thông tin Event bao gồm 2 trường dữ liệu là type và data Trường dữ liệu type chính là tên của Event, trường data là một object gồm 6 thuộc tính: productId, quantity, name, price, desc, createdAt Các trường bao gồm định danh sản phẩm, số lượng, tên, giá, mô tả, thời gian tạo.

Tân từ: Event ProductDeleted lưu trữ thông tin Event bao gồm 2 trường dữ liệu là type và data Trường dữ liệu type chính là tên của Event, trường data là một object gồm 1 thuộc tính: productId Trong Event khi xóa sản phẩm cần có id sản phẩm.

ProductQuantityAdded(type, data(productId, quantity))

Tân từ: Event ProductQuantityAdded lưu trữ thông tin Event bao gồm 2 trường dữ liệu là type và data Trường dữ liệu type chính là tên của Event, trường data là một object gồm 2 thuộc tính: productId, quantity Trong Event khi thêm số lượng cần có id của

ProductInfoUpdated(type, data(productId, name, price, desc))

Tân từ: Event ProductInfoUpdated lưu trữ thông tin Event bao gồm 2 trường dữ liệu là type và data Trường dữ liệu type chính là tên của Event, trường data là một object gồm 4 thuộc tính: productId, name, price, desc Trong Event khi cập nhật sản phẩm cần có id của sản phâm, các thông tin của sản phẩm.

Tên trường Kiểu dữ liệu Không cho phép null Khóa chính id integer True True product_id uuid True False quantity integer True False name character varying(255) True False price integer True False desc text False False status integer True False revision integer True False created_at timestamp with timezone True False last_updated timestamp with timezone True False

Bảng 3 13 Thiết kế CSDL cho bảng Inventory của inventory serivice

Tên trường Kiểu dữ liệu Không cho phép null Khóa chính id character varying(255) True True position text True False

Bảng 3 14 Thiết kế CSDL cho bảng Checkpoint của inventory serivice

Tên trường Kiểu dữ liệu Không cho phép null

Ngày đăng: 04/09/2023, 20:41

HÌNH ẢNH LIÊN QUAN

Hình 2. 4 Minh họa về chiến thắng điện biên phủ - Tìm hiểu về event sourcing
Hình 2. 4 Minh họa về chiến thắng điện biên phủ (Trang 17)
Hình 2. 8 Lưu trữ thông tin "shopping-cart-opened" Event - Tìm hiểu về event sourcing
Hình 2. 8 Lưu trữ thông tin "shopping-cart-opened" Event (Trang 22)
Hình 2. 13 Đoạn code minh họa lưu trữ trên Ram - Tìm hiểu về event sourcing
Hình 2. 13 Đoạn code minh họa lưu trữ trên Ram (Trang 25)
Hình 2. 18 Tối ưu với snapshot (sau) - Tìm hiểu về event sourcing
Hình 2. 18 Tối ưu với snapshot (sau) (Trang 29)
Hình 2. 21 Tính năng Parallel processing - Tìm hiểu về event sourcing
Hình 2. 21 Tính năng Parallel processing (Trang 31)
Hình 2. 22  Ví dụ tính năng Parallel processing - Tìm hiểu về event sourcing
Hình 2. 22 Ví dụ tính năng Parallel processing (Trang 31)
Hình 2. 24  Về Eventual consistency sau khi không ghi một thời gian - Tìm hiểu về event sourcing
Hình 2. 24 Về Eventual consistency sau khi không ghi một thời gian (Trang 33)
Hình 2. 25  Tổng quan về projection - Tìm hiểu về event sourcing
Hình 2. 25 Tổng quan về projection (Trang 34)
Hình 2. 27  Projection trong write model - Tìm hiểu về event sourcing
Hình 2. 27 Projection trong write model (Trang 35)
Hình 2. 29  Workflow trong subscription - Tìm hiểu về event sourcing
Hình 2. 29 Workflow trong subscription (Trang 38)
Hình 2. 34 MSA - Tìm hiểu về event sourcing
Hình 2. 34 MSA (Trang 43)
Hình 2. 37  Cách cài đặt "Orchestration" - Tìm hiểu về event sourcing
Hình 2. 37 Cách cài đặt "Orchestration" (Trang 45)
Hình 2. 40  Sự phụ thuộc giữa các service khi không có EDA - Tìm hiểu về event sourcing
Hình 2. 40 Sự phụ thuộc giữa các service khi không có EDA (Trang 47)
Hình 2. 41   Sự phụ thuộc giữa các service khi có EDA - Tìm hiểu về event sourcing
Hình 2. 41 Sự phụ thuộc giữa các service khi có EDA (Trang 47)
Hình 2. 42  Tính mở rộng trong EDA - Tìm hiểu về event sourcing
Hình 2. 42 Tính mở rộng trong EDA (Trang 48)
Hình 2. 43 Event persistence trong EDA - Tìm hiểu về event sourcing
Hình 2. 43 Event persistence trong EDA (Trang 49)
Hình 2. 46  Minh họa về Eventual Consistency - Tìm hiểu về event sourcing
Hình 2. 46 Minh họa về Eventual Consistency (Trang 51)
Hình 3. 2  Sơ đồ use-case inventory-service - Tìm hiểu về event sourcing
Hình 3. 2 Sơ đồ use-case inventory-service (Trang 63)
Hình 3. 4  Kiến trúc bên trong một service - Tìm hiểu về event sourcing
Hình 3. 4 Kiến trúc bên trong một service (Trang 69)
Hình 3. 5  Một góc nhìn khác về kiến trúc - Tìm hiểu về event sourcing
Hình 3. 5 Một góc nhìn khác về kiến trúc (Trang 71)
Hình 3. 7  Mô tả dữ liệu về "product-item-added" Event - Tìm hiểu về event sourcing
Hình 3. 7 Mô tả dữ liệu về "product-item-added" Event (Trang 77)
Hình 3. 8  Mô tả dữ liệu về "product-item-removed" Event - Tìm hiểu về event sourcing
Hình 3. 8 Mô tả dữ liệu về "product-item-removed" Event (Trang 77)
Hình 3. 9   Mô tả dữ liệu về "shopping-cart-confirmed" Event - Tìm hiểu về event sourcing
Hình 3. 9 Mô tả dữ liệu về "shopping-cart-confirmed" Event (Trang 78)
Hình 3. 10  Mô tả dữ liệu về "product-created" Event - Tìm hiểu về event sourcing
Hình 3. 10 Mô tả dữ liệu về "product-created" Event (Trang 78)
Hình 3. 11  Mô tả dữ liệu về "product-deleted" Event - Tìm hiểu về event sourcing
Hình 3. 11 Mô tả dữ liệu về "product-deleted" Event (Trang 79)
Hình 3. 17  Console của RabbitMQ - Tìm hiểu về event sourcing
Hình 3. 17 Console của RabbitMQ (Trang 86)
Hình 3. 19  Công cụ tương tác, trực quan pgAdmin4 - Tìm hiểu về event sourcing
Hình 3. 19 Công cụ tương tác, trực quan pgAdmin4 (Trang 87)

TỪ KHÓA LIÊN QUAN

TÀI LIỆU CÙNG NGƯỜI DÙNG

TÀI LIỆU LIÊN QUAN

w