Event sourcing là gì

  -  

Micro-services những năm về trước và tới tận bây chừ nó vẫn là 1 hot-trend chưa có dấu hiện mát hơn , nhà nhà tín đồ người đều nói về nó, và gần như là micro-services sẽ thành default architecture trong mọi dự án. Ai ai cũng biết những ưu thế của nó, dẫu vậy micro-services thực chất nó là ‘distributed system’ và tất nhiên đã là distributed system thì nó rất khó khăn và phức tạp. Trường hợp trong quá trình kiến thiết không cảnh giác thì tất cả bọn họ sẽ dễ dãi rơi vào dòng gọi là ‘micro-service madness’ (cơn điên/ác mộng với tên Micro-services).

Bạn đang xem: Event sourcing là gì

Để kiến tạo một khối hệ thống Micro-services tốt thì tốt nhất họ nên gồm có hiểu biết các khái niệm sau: DDD (Domain-driven design) CQRS (Command Query Responsibility Segregation) và Event-Sourcing.


DDD (Domain-drivent design)

Nếu các bạn đang thao tác một khối hệ thống có nhiệm vụ (business) phệ và tinh vi và đặc biệt là nếu bạn có nhu cầu hệ thống của chính mình sẵn sàng (ready) cho micro-service vào tương lai, thì Domain-drivent design chính là phao cứu giúp sinh của chúng ta. Thực tiễn thì DDD nó đã nơi đâu đó trong giới phần mềm khoảng rộng 15 năm nay rồi, dẫu vậy nó chỉ “nổi tiếng" với được “chú ý” đôi lúc micro-services trở nên “nở rộ".

DDD được xây dựng bao phủ một có mang (concept) điện thoại tư vấn là Bounded Context, tôi lưỡng lự dịch ra như vậy nào có thể gọi đó là ranh giới giữa `modules` hoặc `services`trong hệ thống theo nghiệp vụ mà nó đại diện. Tức là mỗi bounded context đại diện cho một nhiệm vụ duy nhất với không thể ráng thế trong hệ thống, ví như Order fulfilment service tuyệt Payment service vào một khối hệ thống về tài thiết yếu (finance). Việc xác minh đúng Context là điều trước tiên và tối quan trọng trong một khối hệ thống DDD.



Một concept đặc biệt quan trọng khác của DDD đó chính là Ubiquitous langue, có nghĩa là một trong những ngôn ngữ chung được sử dụng trong những bounded contextbởi những thành viên tham gia dự án công trình như Developers, Businesspeople … nhưng mà trong đó tất cả mọi tín đồ đều nắm rõ nó, để tìm ra một tiếng nói phổ biến cho tất cả các thành phần tham gia dự án. Bài toán này nhằm mục tiêu tăng năng lực thấu hiểu nhiệm vụ của hệ thống, và sút thiểu những rủi ro về giao tiếp (communicate) dẫn tới những hiểu lầm ko đáng có (misunderstanding). Trong DDD tất cả mọi bạn trong dự án không chỉ là Business-people mà của cả Developers đều phải sở hữu nghĩa vụ cùng bổn phận yêu cầu hiểu biết và góp sức cho nghiệp vụ (business) trong hệ thống.

Aggregate cũng là 1 khái niệm đặc trưng ở tầng nghệ thuật (technical level) giúp cho Developer rất có thể ánh xạ (mapping) và mô hình hóa (object oriented) các business trong khối hệ thống vào một Object duy nhất, bắng giải pháp tập hợp những entity có tương quan tới nhau trong một Bound Context, từng Bound Context hoàn toàn có thể có một hoặc những Aggregate tùy trường phái. Đặc điểm nhưng mà một Aggregate phải bảo đảm đó là tính đồng nhất (consistency)và bất biến (invariants) vào giao dịch, tức là tất cả các entity vào nó nên được đi cùng cả nhà trong một transaction và bảo đảm an toàn tính nhất cửa hàng (consitency) trong mỗi nuốm đổi. Điều này đặc trưng quan trọng vào các khối hệ thống distributed system.

Tuy nhiên chúng ta chỉ hưởng thụ mới mô hình DDD cùng với những khối hệ thống có nghiệp vụ phức tạp, mà đa phần khoảng 95% các dự án tương xứng với CRUD hơn là cùng với DDD.

DDD là một khái niệm tuyệt ho cùng phức tạp, vài mẫu không thể nói hết được, có thể một nội dung bài viết khác tôi vẫn nói thêm bỏ ra tiết, về cơ bản DDD là 1 cách tiếp cận cùng mô phỏng khối hệ thống phần mềm dưới giống với biện pháp nghiệp vụ vận hành bên trên. Tức là mọi vật dụng của nó đề xuất đều có chân thành và ý nghĩa về mặt nhiệm vụ hơn là với phương diện kỹ thuật.

Monolith

Monolith là 1 trong từ cổ duy nhất khối đá khổng lồ, trong phần mềm nó ám chỉ một khối hệ thống phần mềm bao gồm nhiều thành phần không giống nhau được kết hợp thành một chương trình duy tốt nhất được xúc tiến (deploy) bên trên một gốc rễ duy nhất. Xúc tiến một vận dụng kiểu Monolith từ bỏ lâu đã trở thành một tiêu chuẩn chỉnh (standard) trong giới phần mềm. Một hệ thống kiểu Monolith giả dụ được module hóa với thiết kế giỏi (well-designed) thì câu hỏi vận hành, duy trì (maintain) hay upgrade vẫn vô cùng tốt, không hệt như các Micro-services “fan-boy” hay lôi ra để chê bai và dìm mặt hàng Monolith. Tuy vậy thì vào “thực chiến” đa số bọn họ thường không gia hạn được thiết kế xuất sắc khi dự án công trình lớn dần, dẫn tới những vấn đề về câu hỏi maintain, mà lại trong trường vừa lòng xấu độc nhất vô nhị hệ thống họ sẽ biến chuyển một trái bóng bùn (Big Ball of Mud).



Photo by Zoltan Tasi on UnsplashVậy nắm nào là 1 trong những Monolith well-designed? Làm cầm nào để họ tránh được Big Ball of Mud? Câu trả lời chính là DDD (domain-driven design), một hệ thống Monolith đi theo hướng design của DDD sẽ bóc biệt ra những thành phần (component) tuyệt module ra từng bounded context theo từng nghiệp vụ của nó đại diện. Nói thì dễ dàng nhưng để gia công được vấn đề này người thiết kế hệ thống phải là người thông liền về business của hệ thống không thua kém kém gì những buiness-people. Điều này cũng sẽ rất tiện lợi cho vấn đề nếu tất cả một lý vị nào đó ta bắt buộc phân tách hệ thống Monolith ra các services khác biệt (micro-services), họ chỉ cần tách bóc các bounded context ra những thành phần riêng biệt biệt.

Tuy nhiên tất cả một vụ việc khi chúng ta tách bóc Monolith thành các Micro-Services đó là việc tiếp xúc (communication) giữa các services. Ở khối hệ thống Monolith nó chỉ đối chọi gian là những object calls, tuy nhiên trong Micro-Serivies thì câu hỏi này phải đi qua net-work bằng phương pháp sử dụng các kỹ thuật như API Call, RPC hay sự kiện Bus thông qua một khái niệm điện thoại tư vấn là location transparency mà bọn họ sẽ quay trở về và bàn thêm sau.

Microservices

Tới bây chừ Microservices không thể là có mang gì mớ lạ và độc đáo nữa, các concept như là service boundaries, asynchronous message tuyệt application database, v.V… vẫn là đầy đủ concept danh tiếng và được sử dụng trong tương đối nhiều năm qua.



Nguồn ảnh: https://microservices.io/patterns/microservices.htmlRất những các điểm mạnh để thực hiện một hệ thống theo Microservices như thể “độc lập về phân phát triển, tiến hành và không ngừng mở rộng (independent development/deployment/scale) v.V… nhưng theo tôi thì ưu thế nhất của Microservices đó phù hợp với cách thao tác và giao tiếp “giữa người cùng với người”. Về bản chất con fan chỉ hoàn toàn có thể làm bài toán và tiếp xúc với nhau rất tốt với một team dưới 10 người, vị thật quá cạnh tranh khi thao tác trên 1 phần mềm có quá nhiều kỹ sư. Vì chưng thế chúng ta cần nên làm là thành lập mỗi nhóm hòa bình trên các phần khác biệt của hệ thống, sẽ là tính Agility vào Agile. Vị vậy không phải ngẫu nhiên một Agile team hoặc như một đối kháng vị bé dại nhất vào quân team (tiểu đội) cũng nên làm có dưới 10 người.

Với một hệ thống Micro-services được thiết kế tốt thì những team phụ trách từng services đã implement, deploy với run những ứng dụng của bản thân một cách tự do và ít ảnh hưởng trọn tới những team khác. Và tất yếu nó cực tốt và phù hợp với những vấn đề về không ngừng mở rộng (scalability) sau này.

Tuy nhiên như sẽ nói bên trên Micro-services là một khối hệ thống Distributed System, nó luôn kèm theo với những phức tạp trong vấn đề vận hành, xúc tiến và về phía nghệ thuật (technical) lẫn nghiệp vu (business) bởi vì mỗi service không thể nào thực sự độc lập, nó luôn luôn cần dữ liệu (data) từ bỏ services, qua biện pháp communication cùng với nhau mặc dù ít hay nhiều. Các service thì có nhiều phương pháp để giao tiếp với nhau nhưng thông thường đó là thứ hạng request-response thực hiện API qua HTTP hoặc RPC, hoặc giữ hộ message theo kiểu send-and-forget theo mô hình Pub/Sub. Cũng từ đó mà nẩy sinh ra những vấn đề khác như “data consistency” trong bản vẽ xây dựng Microservices.

Do đó việc xác định chuẩn xác các bounded contexts hay service boundaries với cách các services tiếp xúc với nhau ngay từ trên đầu là một bài toán tối quan liêu trọng. Cũng chính vì việc refactoring hay di chuyển (moving) các công dụng (functionality) vào Micro-services trở ngại hơn rất nhiều lần so với trong Monolith.

Các kỹ sư làm việc lâu năm cùng với Distributed system thường xuyên nói rằng: “Nếu chúng ta không thể xây cất một khối hệ thống Monolith well-designed (với DDD) thì nên quên đi việc xây dựng phong cách xây dựng Microservices.”

Có thể thấy DDD nó phù hợp và quan trọng trong Micro-services đến nhường nào, bởi vậy hãy đừng nói cùng với tôi rằng bạn đang thao tác với Microservies mà do dự gì DDD nhé :D.

Event-Driven Architecture

Như sẽ nói ở trên rằng các service luôn luôn luôn có nhu cầu giao tiếp với những service khác, cách tương xứng nhất cùng với việc tiếp xúc này chính là gửi nhận message giữa các services theo một cách bất đồng nhất (asynchronously). Phong cách xây dựng đó thường được gọi là Event-Drivent Architecture (EDA), vào EDA ta quan niệm ra bố loại message:

Event: Nó đại diện thay mặt cho một thông điệp thông báo rằng vẫn có nào đó đã sẩy ra nơi đâu đó. Đặc điểm của event là nó bất biến (immutable).Command: Nó thay mặt đại diện cho một hành động mà vị trí gửi (publisher) mong nơi nhấn (consumer) thực hiện một cái gì đó, và kết quả của hành vi sẽ được gởi lại đến sender. Đặc điểm của command là nó luôn luôn có tối thiểu một địa điểm nhận (consumer)Query: Nó đại diện thay mặt cho một yêu cầu dữ liệu trả về từ nơi gửi (publisher) cho tới một tuyệt nhiều khu vực nhận (consumer), dữ liệu sẽ tiến hành lấy và trả về cho publisher.

Xem thêm: Irr Là Gì? Công Thức Tính Irr Và Ý Nghĩa Của Chỉ Số Irr Là Gì

Trong EDA ta sẽ áp dụng message kiểu event nếu advertiser gửi đi (emit) message mà lại không ân cần tới gồm consumer nào lắng nghe (listening), và tất cả nếu không có consumer làm sao lắng nghe thì quảng cáo trên internet vẫn đang thực hiện hành vi của nó. Message giao diện Command được sử dụng nếu advertiser mong đợi một điều nào đó sẽ sẩy ra ở 1 service khác một phương pháp bất đồng hóa (asynchronous), trước lúc nó fulfilment nghiệp vụ (business task) của publisher đó, bằng phương pháp chờ đợi hiệu quả hành đụng từ consumer trả về . Họ sẽ thực hiện message giao diện Query nếu muốn lấy thông tin xuất phát từ 1 hoặc nhiều service khác. Dữ liệu cũng trở thành được trả về từ bỏ consumer tới quảng cáo online theo một cách sự không tương đồng bộ.



Một ví dụ như về EDA trong trong thực tiễn là trong một hệ thống về eCommerce tất cả một service là Order Fulfilment, service này luôn luôn yêu cầu đơn hàng (Order) buộc phải được giao dịch (payment) trước lúc nó triển khai cách hành động khác. Lúc này Order Fulfilment service sẽ gửi một asynchronous command message tới Payment service, lúc đó Payment service sẽ tiến hành việc giao dịch và trả về một sự kiện message chứa tác dụng thành công xuất xắc thất bại. Order Fulfilment service sẽ consumer hiệu quả và liên tục những process tiếp sau (cancel order/shipping order).

Trong EDA mỗi event nó đang không phản chiếu ở tầng kỹ thuật (technical level) cơ mà nó phải ánh xạ với có chân thành và ý nghĩa với một hành động của nghiệp vụ (business level) nhất thiết trong hệ thống. Lấy ví dụ thay bởi vì sử dụng event CustomerChanged nhằm gửi thông điệp rằng người tiêu dùng đang nuốm đổi địa chỉ cửa hàng mà chúng ta nên sử dụng sự kiện CustomerMoved, nó đã có ý nghĩa (meaningful) với business hơn. Do đó việc modelling sự kiện cũng buộc phải tập thông thường vào hành động (behavioural) của nghiệp vụ nhiều hơn thế là cấu tạo (structure) của mã sản phẩm theo hơi hướng của Aggregate vào DDD. Điều này sẽ khiến cho ứng dụng dễ dàng nắm bắt hơn rằng nó đang làm gì ở góc nhìn về business, thông qua đó ta thấy rằng concept của DDD lại một lần nữa phù hợp ở đây.

Eventual Consistency

Trong mọi hệ thống trong thực tiễn thì sự kiện bắt buộc phải thỏa mãn nhu cầu việc đồng nhất và đồng bộ (Eventual Consistency). Ví như việc chuyển khoản giữa hai thông tin tài khoản của hai ngân hàng thì hai command sự kiện bắt yêu cầu được thực hiện một cách đồng hóa và tuyệt nhất quán, ko thể tài khoản A bị trừ tiền và thông tin tài khoản B vẫn không sở hữu và nhận được tiền được. Trong đó mọi event được dồng bộ và đồng hóa giữa một hoặc nhiều service không giống nhau trong hệ thống, vấn đề đó cũng kéo theo sự tinh vi không đáng gồm trong hệ thống, tuy phức tạp nhưng nó là điều hiển nhiên và tất yêu tránh khỏi (inevitable)trong distributed system.



Eventual consistency is an inevitable concept in large-scale distributed systems like … ThanosBởi vì một vài quyết định vào business logic luôn luôn đề xuất đưa ra dựa trên các dữ liệu đồng nhất nghiêm ngặt (data consistency) và đáng tin cậy, và công dụng các ra quyết định đó cũng buộc phải được cập nhật tương ứng với những thành phần liên quan. Cũng giống như trong DDD những Aggregate luôn luôn luôn phải nhất quán và không bao giờ thay đổi (consistent & invariants), những entity cùng value object vào một Aggregate phải luôn consistent cùng nhau khi nhiệm vụ cần lôi ra hay vắt đổi.

Command Query Responsibility Segregation (CQRS)

CQRS thực tế là một concept rất dễ dàng là tách phần command cùng query (đọc&ghi) ra thành nhị thành phần (component) riêng lẻ mục đích để buổi tối ưu câu hỏi đọc hoặc ghi trong hệ thống.


Điểm mạnh bạo của phong cách xây dựng này là command chỉ ảnh hưởng tới một Aggregate trong khi đó query hoàn toàn có thể đọc với lấy một lượng bự dữ liệu từ rất nhiều nguồn. Có nghĩa là ta hoàn toàn có thể hạn chế ảnh hưởng (effect) của vấn đề ghi dữ liệu và tối ưu hóa (optimize) truy tìm vấn (query) bỏ phần đọc. Với việc tách bóc biệt (segregation) đọc&ghi (read&write) hệ thống có thể dễ dàng áp dụng những data storage khác biệt cho vấn đề tối ưu vận tốc (performant) đến từng loại. Mà thường thì thì bài toán read vẫn tốn performant rộng tác vụ write, vì chưng vậy việc tách bạch này cũng khiến cho ta tiện lợi optimized giỏi scaling cho phần read side.

Tuy nhiên việc bóc biệt này dẫn tới vấn đề ta buộc phải luôn đồng nhất dữ liệu từ write side với read side. Với việc đồng điệu kiểu bất đồng bộ (asynchronously) sẽ khiến cho dữ liệu read side gần như là không thể phản ảnh và đồng hóa tức thời (immediately) từ tài liệu của write side. Việc phải tạo nên đọc&ghi đề xuất synchronous với nhau, hay khối hệ thống phải đảm bảo eventual consistency cũng làm cho khối hệ thống phức tạp hơn rất nhiều lần.

Tuy nhiên CQRS cũng như DDD chúng ta chỉ tận hưởng với nó bên trên một vài khối hệ thống có nghiệp vụ phức tạp đặc thù dựa trên phong cách xây dựng EDA, mà đa số các hệ thống còn lại phù hợp với dạng CRUD hơn, với nó nên triển khai theo bí quyết đó. Đặc biệt là CQRS phần lớn chỉ tương xứng với một trong những phần cụ thể trong khối hệ thống (BoundContext vào DDD) hơn là trên toàn bộ hệ thống.

CQRS sẽ khiến cho hệ thống đã trở đề nghị rất phức tạp, vì vậy chúng ta phải rất cẩn trọng khi áp dụng CQRS, vày nó cũng như Mircoservice là một khối hệ thống rất khó để áp dụng tốt. Ví như không xây đắp và sử lý tốt chúng ta sẽ đề xuất trả giá đắt ngay cả khi ta bao gồm một team có năng lượng về technology tốt.

Event sourcing

Ý tưởng của event sourcing đang có từ lâu và cũng không mới lạ gì, trong nội bộ đa số các database đều thực hiện kiến trúc sự kiện sourcing, ví dụ hiệ tượng Binlog vào MySQL hay audit Log vào Oracle.

Concept của event sourcing là lưu trữ (persisted) toàn bộ lịch sử chuyển đổi của business entity cùng được sắp đến sếp theo trình tự thời gian của sự biến hóa (time-ordered sequence).


Khi tâm trạng của entity bị cố đổi, một message dạng event sẽ gửi đi mục đích để gìn giữ lịch sử biến hóa của entity. Ta rất có thể persisted sự đổi khác ngay mau lẹ khi sự kiện tới, hoặc snapshot chu trình nếu entity tất cả số lượng event lớn nhưng mà ta mong muốn optimize. Các hệ thống như tài chủ yếu (finance), ngân hàng (banking) hay bảo hiểm (insurance) sự kiện Sourced thường xuyên được sử dụng, mục tiêu là để lưu trữ lại toàn bộ các thay đổi trong khối hệ thống để rất có thể xử lý trong tương lai nếu cần.

Điểm mạnh mẽ của nó là ta hoàn toàn có thể tái hiện tại (reconstructed) tinh thần của entity tại một thời điểm bất kỳ, bằng phương pháp phát lại (replaying all) toàn bộ các sự kiện phát sinh tới thời điểm đó. Điều này còn có hữu ích trong việc tái hiện bug hoặc rollback lại trạng thái của entity nếu tất cả lỗi xảy ra. Tuy nhiên việc replaying all này phải triển khai với sự cẩn thận, vị rất rất có thể khi phân phát lại các command event ảnh hưởng tới những service khác, ví dụ sự kiện OrderPlaced được phát đi lại(emit) thì rất rất có thể event OrderFulfilled sẽ tiến hành thực hiện nhiều hơn thế nữa một lần.

Event sourcing thường được sử dụng như một phần trong CQRS để đồng nhất sự thay đổi của Command cùng với Query. Mặc dù không phải toàn bộ hệ thống đều phải sở hữu event sourced, mà nó phụ thuộc vào vào business của từng bounded contexthoặc theo từng nhiệm vụ của Aggregate. Các event sourcing không nên publish ra bên ngoài bounded context của nó để tránh đều sự dựa vào không quan trọng giữa các bounded context.

Location Transparency

Một concept rất đặc biệt quan trọng khác trong việc xậy dựng một Monolith sẵn sàng cho Microservice là Location Transparency, nó sẽ giúp đỡ việc các Context xác định được địa điểm Context khác nhưng nó cần thúc đẩy (interacts) tới. Câu hỏi này làm tinh giảm sự dựa vào (dependency) giữa các bounded context trong một dự án công trình Monolith, lúc mà phần lớn component hồ hết được deploy chung trên một đơn vị chức năng (unit). Location Transparency mang lại lợi ích cho việc có thể thay đổi Monolith sang trọng Microservice khi mà mọi service đều được deploy lên các môi trường riêng biệt, cơ mà không phải thay đổi ngẫu nhiên dòng code nào. Bao gồm nhiều phương pháp để cài để Location Transparency như áp dụng messaging cùng với những tài liệu kiểu asynchronous, hoặc HTTPS/RPC với tài liệu trao đổi kiểu synchronous.

Ví dụ vào một dự Monolith viết bằng Java là những bounded context sẽ đàm phán asynchronus với nhau qua sự kiện Bus hoặc thiết đặt Interface bên trên bounded context với Implement của nó sẽ nằm ở vị trí Locaiont Transparency nếu cần đàm phán kiểu synchronous.

Xem thêm: Review Bank Key Là Gì ? Mã Bankcode Của Tất Cả Ngân Hàng Tại Việt Nam

Kết luận: những kiến trúc như Microservice, CQRS hay event Sourcing không phải là một trong viên đạn tệ bạc (silver bullet) để giải quyết tất cả những bài toán. Nhưng mà nó chỉ tương xứng cho vài hệ thống đặc thù có domain tuyệt business phức hợp như các hệ thống banking, finance, insurance giỏi eCommerce. Cùng nó bao gồm điểm chung là đều sử dụng DDD như một đại lý kiến trúc tương tự như lý luận vào hệ thống.