Cqrs là gì

  -  

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

Bạn đang xem: Cqrs là gì

Để xây dựng một hệ thống Micro-services giỏi thì giỏi nhất bọn họ nên bao gồm hiểu biết phần nhiều khái niệm sau: DDD (Domain-driven design) CQRS (Command Query Responsibility Segregation) và Event-Sourcing.


DDD (Domain-drivent design)

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

DDD được xây dựng bao quanh một có mang (concept) call là Bounded Context, tôi lừng chừng dịch ra như vậy nào hoàn toàn có thể gọi đó là ranh giới giữa `modules` hoặc `services`trong khối hệ thống theo nghiệp vụ cơ mà nó đại diện. Có nghĩa là mỗi bounded context thay mặt cho một nhiệm vụ duy nhất cùng không thể rứa thế vào hệ thống, ví như Order fulfilment service giỏi Payment service trong 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 đầu tiên và tối đặc biệt trong một khối hệ thống DDD.



Một concept đặc biệt quan trọng khác của DDD đó đó là Ubiquitous langue, có nghĩa là một trong ngôn ngữ tầm thường được sử dụng trong những bounded contextbởi các thành viên tham gia dự án công trình như Developers, Businesspeople … nhưng mà trong đó tất cả mọi fan đều nắm rõ nó, nhằm tìm ra một tiếng nói phổ biến cho toàn bộ các thành phần tham gia dự án. Việc này nhằm tăng tài năng thấu hiểu nhiệm vụ của hệ thống, và giảm 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 fan trong dự án không chỉ là Business-people mà của cả Developers đều phải sở hữu nghĩa vụ và bổn phận cần hiểu biết và góp phần cho nghiệp vụ (business) trong hệ thống.

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

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

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

Monolith

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



Photo by Zoltan Tasi on UnsplashVậy vắt nào là 1 trong Monolith well-designed? Làm núm nào để chúng ta tránh được Big Ball of Mud? Câu trả lời đó là DDD (domain-driven design), một khối hệ thống Monolith đi theo phía design của DDD sẽ tách biệt ra các thành phần (component) giỏi module ra từng bounded context theo từng nghiệp vụ của nó đại diện. Nói thì dễ nhưng để triển khai được vấn đề đó người thiết kế khối hệ thống phải là người thông thạo về business của hệ thống không thua thả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ý bởi nào đó ta bắt buộc phân tách bóc hệ thống Monolith ra nhiều services không giống nhau (micro-services), chúng ta chỉ cần bóc tách các bounded context ra các thành phần riêng biệt biệt.

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

Microservices

Tới hiện nay Microservices không thể là khái niệm gì mới mẻ nữa, những concept như là service boundaries, asynchronous message xuất xắc application database, v.V… vẫn là hầu như 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 ưu điểm để tiến hành một khối hệ thống theo Microservices như là “độc lập về phân phát triển, triển khai và mở rộng (independent development/deployment/scale) v.V… nhưng theo tôi thì ưu điểm nhất của Microservices đó cân xứng với cách làm việc và tiếp xúc “giữa người cùng với người”. Về thực chất con bạn chỉ có thể làm việc và giao tiếp với nhau tốt nhất có thể với một team dưới 10 người, do thật quá nặng nề khi thao tác trên một trong những phần mềm có quá nhiều kỹ sư. Vì chưng thế chúng ta cần buộc phải làm là thành lập mỗi nhóm tự do trên các phần khác biệt của hệ thống, chính là tính Agility trong Agile. Vày vậy chưa hẳn ngẫu nhiên một Agile team hay như một 1-1 vị nhỏ tuổi nhất trong quân đội (tiểu đội) cũng chỉ nên có bên dưới 10 người.

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

Tuy nhiên như vẫn nói trên Micro-services là một khối hệ thống Distributed System, nó luôn đi kèm theo với những phức tạp trong việc vận hành, triển khai 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 tài liệu (data) trường đoản cú services, qua bí quyết communication cùng với nhau cho dù ít tuyệt nhiều. Các service thì tất cả nhiều cách để giao tiếp cùng nhau nhưng thường thì đó là loại request-response thực hiện API qua HTTP hoặc RPC, hoặc giữ hộ message theo kiểu send-and-forget theo quy mô Pub/Sub. Cũng từ này mà nẩy sinh ra các vấn đề khác ví như “data consistency” trong phong cách thiết kế Microservices.

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

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

Có thể thấy DDD nó phù hợp và quan trọng đặc biệt trong Micro-services đến nhường nào, vày vậy hãy đừng nói với tôi rằng chúng ta đang thao tác làm việc với Microservies mà lưỡng lự gì DDD nhé :D.

Event-Driven Architecture

Như đã nói ở trên rằng những service luôn luôn luôn có nhu cầu giao tiếp với những service khác, cách phù hợp nhất cùng với việc giao tiếp này chính là gửi nhấn message giữa các services theo một biện pháp bất đồng bộ (asynchronously). Phong cách thiết kế đó thường được hotline là Event-Drivent Architecture (EDA), trong EDA ta quan niệm ra tía 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 đấy đã sẩy ra chỗ nào đó. Đặc điểm của event là nó không bao giờ thay đổi (immutable).Command: Nó thay mặt cho một hành động mà địa điểm gửi (publisher) ao ước nơi dấn (consumer) thực hiện một chiếc gì đó, với kết quả của hành vi sẽ được gửi lại mang lại 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ó thay mặt đại diện cho một yêu cầu dữ liệu trả về từ nơi gửi (publisher) cho tới một xuất xắc nhiều nơi nhận (consumer), dữ liệu sẽ tiến hành lấy cùng trả về cho publisher.

Xem thêm: Quả Cầu May Mắn Cf Mien Phi, Ưu Đãi Khi Mua Quả Cầu May Mắn

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



Một lấy ví dụ về EDA trong thực tế là trong một khối hệ thống về eCommerce bao gồm một service là Order Fulfilment, service này luôn yêu cầu deals (Order) cần được giao dịch thanh toán (payment) trước khi nó thực hiện cách hành động khác. Từ bây giờ Order Fulfilment service sẽ gửi một asynchronous command message cho tới Payment service, lúc đó Payment service sẽ tiến hành việc giao dịch và trả về một event message chứa kết quả thành công giỏi thất bại. Order Fulfilment service vẫn consumer hiệu quả và liên tục những process tiếp sau (cancel order/shipping order).

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

Eventual Consistency

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



Eventual consistency is an inevitable concept in large-scale distributed systems lượt thích … ThanosBởi vì một số trong những quyết định trong business logic luôn luôn bắt buộc đư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à tác dụng các ra quyết định đó cũng nên được update tương ứng với các thành phần liên quan. Cũng giống như trong DDD các Aggregate luôn luôn phải đồng bộ và không bao giờ thay đổi (consistent và invariants), các entity cùng value object trong một Aggregate phải luôn consistent cùng nhau khi nghiệp vụ cần lôi ra hay vậy đổi.

Command Query Responsibility Segregation (CQRS)

CQRS thực ra là một concept rất dễ dàng là tách bóc phần command cùng query (đọc&ghi) ra thành hai thành phần (component) hiếm hoi mục đích để buổi tối ưu việc đọc hoặc ghi vào hệ thống.


Điểm mạnh dạn của phong cách xây dựng này là command chỉ tác động ảnh hưởng tới một Aggregate trong lúc đó query rất có thể đọc và lấy một lượng to dữ liệu từ không ít nguồn. Tức là ta hoàn toàn có thể hạn chế tác động (effect) của việc ghi dữ liệu và về tối ưu hóa (optimize) truy nã vấn (query) cho phần đọc. Với việc bóc biệt (segregation) đọc&ghi (read&write) hệ thống rất có thể dễ dàng sử dụng những data storage khác biệt cho câu hỏi tối ưu tốc độ (performant) mang đến từng loại. Mà thường thì thì câu hỏi read sẽ tốn performant hơn tác vụ write, vày vậy việc tách bóc bạch này cũng khiến cho ta thuận lợi optimized xuất xắc scaling cho chỗ read side.

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

Tuy nhiên CQRS tương tự 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 kiến trúc EDA, mà đa phần các khối hệ thống còn lại phù hợp với dạng CRUD hơn, cùng nó nên triển khai theo cách đó. Đặc biệt là CQRS phần nhiều chỉ tương xứng với 1 phần cụ thể trong hệ thống (BoundContext vào DDD) hơn là trên toàn bộ hệ thống.

CQRS sẽ làm cho hệ thống đang trở phải rất phức tạp, vì chưng vậy bọn họ phải rất cẩn thận khi sử dụng CQRS, vì chưng nó cũng giống như Mircoservice là một khối hệ thống rất nặng nề để sử dụng tốt. Trường hợp không thiết kế và sử lý tốt chúng ta sẽ cần trả giá chỉ đắt ngay cả khi ta bao gồm một team có năng lực về technology tốt.

Event sourcing

Ý tưởng của sự kiện sourcing đã có từ rất lâu và cũng không mớ lạ và độc đáo gì, vào nội bộ hầu hết các database đều sử dụng kiến trúc event sourcing, ví dụ chế độ Binlog trong MySQL hay phân tích và đo lường Log vào Oracle.

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


Khi tâm trạng của entity bị vắt đổi, một message dạng event sẽ gởi đi mục đích để lưu lại lịch sử chuyển đổi của entity. Ta có thể persisted sự đổi khác ngay mau lẹ khi sự kiện tới, hoặc snapshot thời hạn nếu entity tất cả số lượng event lớn mà lại ta ước ao optimize. Các hệ thống như tài thiết yếu (finance), bank (banking) hay bảo đảm (insurance) event Sourced liên tiếp được sử dụng, mục tiêu là để tàng trữ lại toàn bộ các đổi khác trong hệ thống để rất có thể xử lý sau đây nếu cần.

Điểm mạnh mẽ của nó là ta có thể tái hiện nay (reconstructed) tâm lý 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) tất cả các sự kiện phát sinh tới thời điểm đó. Điều này có hữu ích trong vấn đề tái hiện nay bug hoặc rollback lại trạng thái của entity nếu có lỗi xảy ra. Tuy vậy việc replaying all này phải tiến hành với sự cẩn thận, bởi rất có thể khi phân phát lại những command event ảnh hưởng tới các service khác, ví dụ sự kiện OrderPlaced được phát đi lại(emit) thì rất có thể event OrderFulfilled sẽ được thực hiện nhiều hơn thế một lần.

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

Location Transparency

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

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

Xem thêm: Tổng Hợp Đáp Án Đuổi Hình Bắt Chữ Mới Nhất, Đáp Án Game Đuổi Hình Bắt Chữ Mới Nhất (2710 Câu)

Kết luận: các 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ả các bài toán. Nhưng nó chỉ tương xứng cho vài hệ thống đặc thù bao gồm domain hay business phức tạp như các khối hệ thống banking, finance, insurance hay eCommerce. Với nó bao gồm điểm tầm thường là đều sử dụng DDD như một cửa hàng kiến trúc cũng như lý luận vào hệ thống.