domain driven design và event driven architecture

Post on 23-Jan-2018

1.109 Views

Category:

Software

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

Domain Driven Design và Event Driven

Architecture

trong xây dựng Enterprise Software

Lê Minh Nghĩa

Solution Architect from Tiki

22/10/2016

Giới thiệu về bản thân

• Lê Minh Nghĩa

• Solution Architect – tiki.vn

• Email: nghia.fit@gmail.com

• Facebook: /nghialeminh

Các nội dung chính

1. Các yêu cầu đặt ra

2. Ứng dụng Domain Driven Design

3. Event - driven Architecture

4. Một số Case Studies

5. Kết luận

3

1. Các yêu cầu đặt ra

• Khả năng mở rộng về mặt nghiệp vụ.

• Khả năng mở rộng về mặt hiệu năng

4

1.1. Khả năng mở rộng về nghiệp vụ

• Nghiệp vụ luôn luôn thay đổi. Thiết kế là để đáp ứng nhu cầu thay đổi.

• Có model dữ liệu phải nhất quán và rõ ràng

• Logic nghiệp vụ phải tập trung

• Cấu trúc thống nhất

• Mọi thành phần đều có thể thay thế.

• Tiếp cận: Domain Driven Design

5

1.2. Mở rộng về mặt hiệu năng

• Không dùng chung một mô hình xử lý

• Đảm bảo khả năng tích hợp và mở rộng

• Đảm bảo tính ổn định trong môi trường phân tán.

• Tiếp cận: Event driven Architecture

6

1.3. Mô hình kiến trúc

7

DatabaseMessage Queue Caching

2. Ứng dụng Domain Driven Design

• Khó khăn khi phát triển

• Thiết kế Aggregate

• Infrastructure Layer

• Mức độ tái sử dụng

8

2.1. Khó khăn khi phát triển

• Không có model dữ liệu nhất quán.

• Trùng lặp mã nguồn lớn

• Khó kiểm soát khi nghiêp vụ bùng nổ

• Không có cấu trúc API thống nhất

• Khó đảm bảo tính nhất quán

9

2.2. Aggregrate

Là một nhóm các đối tượng dữ liệu được đối xử như một thể thống nhất

trong hệ thống

VD: order và order line phải coi như là hai thành phần nhất quán của

đối tượng aggregate order, định danh trong hệ thống là order id.

10

2.2. Aggregrate

11

2.2. Aggregrate

- Đảm bảo cách nhìn thống nhất trong toàn bộ hệ thống

- Khi nói đến một aggregate phải nói tới một đối tượng dữ liệu toàn vẹn,

đầy đủ.

- Không tồn tại các nghiệp vụ riêng biệt với từng thành phần của một

aggregate

- Tất cả logic từ data access tới service đều phải xoay quanh các

aggregate

12

2.2. Aggregate

• Chọn lựa phạm vi aggregate vừa đủ.

• Phạm vi aggregate quá lớn sẽ dẫn tới performance không tốt.

• Phạm vị aggregate quá bé sẽ dẫn tới logic bị phân mảnh và khó quản

lý.

• Đảm bảo các thành phần của một aggregate luôn nhất quán

13

2.2. Aggregate

Sử dụng pattern về data access thống nhất:– Repository Pattern

– ORM

Cấu trúc resources API tương ứng với các Aggregate

14

2.2. Aggregate

Don’t Repeat Yourself:

• Không nhầm lẫn Aggregate và các DTO

• Không design API dựa theo nhu cầu hiển thị

• Không xây dựng data access theo từng chức năng.

15

2.3. Infrastructure Layer

DatabaseMessage Queue Caching

16

2.3. Infrastructure Layer

• Đảm nhiệm vai trò làm việc với các thành phân bên dưới như DB,

Message Queue, File…

• Phần lớn logic của hệ thống là logic nghiệp vụ

• Không để logic của phần infrastructure làm giảm tốc độ phát triển

của nghiệp vụ

17

2.3. Infrastructure Layer

• Phải có khả năng tái sử dụng cao

• Phai nhất quán trong toàn bộ cấu trúc hệ thống

• Pattern:

- Repository Pattern

- Observer Pattern

- ORM Pattern

18

2.4. Mức độ tái sử dụng

Applications – Web App, API, Server Application…

Application Service

Domain Service

Domain Model

Infrastructures

19

Mức độ sử dụng

2.4. Mức độ tái sử dụng

• Các layer càng cao thì càng được sử dụng nhiều.

• Các layer càng bên dưới thì càng phải tái sử dụng cao

• Tránh thiết kế để độ phức tạp là ngang nhau giữa tất cả các layer.

• Tốc độ phát triển ngày một nhanh, vì tích lũy được các logic trước đó.

• Phải luôn kiểm soát, refactor mã nguồn.

• Phải ám ảnh triết lý: Don’t Repeat Yourself!

20

3. Event – Driven Architecture.

• Yêu cầu mở rộng về mặt hệ thống

• Event Drivent Archtecture trong Distributed System

• Message Bus/Event Bus

• Event Sourcing

• Tích hợp hệ thống

• Đảm bảo thứ tự message

21

3.1. Yêu cầu mở rộng hệ thống

• Không chia được thì không scale được

• Scale độc lập nhiều thành phần

• Giải quyết tính ổn định trong tích hợp hệ thống

22

3.2. EDA trong Distributed System

Request Driven Architecture

23

3.2. EDA trong Distributed System

Request Driven Architecture:

• Phức tạp khi tích hợp hệ thống

• Rất khó để quản lý tính nhất quán của dữ liệu

• Khó để mở rộng độc lập các thành phần của hệ thống

24

3.2. EDA trong Distributed System

25

Event Driven Architecture

3.2. EDA trong Distributed System

Event Driven Architecture

- Lose couping toàn bộ hệ thống

- Dễ dàng tích hợp

- Quản lý luồng message

26

3.3. Message Bus

• Đóng vai trò truyền gửi message trong hệ thống

• Đảm bảo quá trình truyền gửi ổn định

• Có khả năng điều hướng message

• Dễ dàng tích hợp với các thành phần trong hệ thống.

• Là đối tượng về mặt logic của các hạ tầng message queue

27

3.3. Message Bus

Logistic

SystemOperation

Data

WarehouseTracking Optimize

Message Bus

3.3. Message Bus

Có thể trừu tượng hóa thành hai loại:

- Event Bus : truyền gửi các event đã xảy ra

- Command Bus: truyền gửi bất đồng bộ các lệnh thay đổi dữ liệu trong

hệ thống.

29

3.4 Event Sourcing

30

3.4 Event Sourcing

• Lưu trữ thay đổi của đối tượng

• Tách các phần ghi và đọc trong hê thống

31

3.4 Event Sourcing và thực tế áp dụng

• Việc xây dựng cấu trúc lưu trữ Event Store cho tất cả là phức tạp

• Kiểm soát tính đồng thời trong các thao tác cập nhật khó khăn

• Phân tích read side thành nhiều thành phần tùy theo yêu cầu về tính

nhất quán và đồng thời với write side.

• Nên dùng Event Store để lưu log hơn là main database.

32

3.4 Event Sourcing và thực tế áp dụng

Ví dụ: Cập nhật trạng thái đơn hàng:

- Nếu cần lấy ngay trạng thái thành công hay thất bại để hiển thị sử

dụng chung một mô hình lưu trữ cho hai việc

- Nếu sau khi cập nhật tác động tới dữ liệu ở khâu vận hành khác

read side là cấu trúc lưu trữ phục vụ khâu vận hành

33

3.5. Đảm bảo thứ tự của message

• Đảm bảo thứ tự message có vai trò quyết định với tính ổn định của

toàn hệ thống

VD: để tracking trạng thái hàng hóa, khi vận hành có hai event:

- e1: nhập kho

- e2: xuất kho

Các event gửi trong môi trường phân tán, thứ tự e1, và e2 có thể bị đảo

lộn.

Khi số lượng event càng lớn, thì tỉ lệ lỗi càng cao, ảnh hưởng độ ổn định

hệ thống.

34

3.5. Đảm bảo thứ tự message

• Đảm bảo thứ tự ghi dữ liệu

• Đảm bảo thứ tự gửi event

• Đảm bảo thứ tứ nhận event

35

3.5.1. Đảm bảo thứ tự ghi

• Các event được append vào một log. Ví dụ: insert vào một table.

• Các lệnh insert thường không lock nhau, do đó các lệnh insert có thể thực thi đồng thời.

VD:

- Thời điểm T1: lấy order và xử lý

Process 1: Get Order – version = 1

DoSomething()

version = version + 1 2 event E2

Process 2: Get Order – version = 1

DoSomething()

version = version + 1 2 event E2

- Thời điểm T2: lưu kết quả xử lý: lưu các event lại.

Do các lệnh insert không lock nhau, nên lưu trữ sẽ là: E1 – E2 – E2

Wrong!

36

3.5.1. Đảm bảo thứ tự ghi

Solution 1: lock theo key range, sử dụng transaction mode lock serializable

Ví dụ: lock theo key là id order

Solution 2: sử dụng hai resources:

R1: snapshot của object

R2: event log

Lock lệnh update trên R1 và append vào R2

Solution 3: nếu lưu event trên table, thì sử dụng bộ cặp primary key của event:

Aggregate Id – Version

Các event cùng version sẽ bị đụng độ khi insert.

37

3.5.2. Đảm bảo thứ tự gửi

Các message có thể bị gửi sai thứ tự, dù thời điểm xử lý diễn ra đúng thứ

tự.

VD:

- Thời điểm T1:

DoSomething();

Send Event 1;

- Thời điểm T2:

DoSomething();

Send Event 2;

Event 1 send đi lỗi, Event 2 lại send thành công Wrong!

38

3.5.2. Đảm bảo thứ tự gửi

Solution:

- Không áp dụng đồng thời ghi DB và gửi event vì không có transaction.

- Phải gửi log các event trước khi gửi đi

- Gộp nhóm các event theo id của aggregate phát event. Lưu trữ event với

cặp key: aggregateId – version

- Load các event cần gửi theo aggregate id, và gửi tuần tự theo version

- Dừng gửi ngay khi gặp event lỗi

- Xử lý sự cố Load lại theo aggregateId và gửi tiếp theo thứ tự version

- Sử dụng hai bảng:

• Bảng Event để store event

• Bảng Undispatched Event để lưu tạm các event chờ gửi, sẽ xóa sau khi gửi xong.

39

3.5.2. Đảm bảo thứ tự gửi

ID Version

ABC 3

XYZ 2

40

ID Version Payload

ABC 1 ….

ABC 2 ….

ABC 3 ….

XYZ 1 ….

XYZ 2 ….

Order

Event

ID Version Payload

ABC 1 ….

ABC 2 ….

ABC 3 ….

XYZ 1 ….

XYZ 2 ….

Undispatched Event

3.5.3. Đảm bảo thứ tự nhận message

Các message khi được dequeue song song có thể sẽ bị mất thứ tự khi

xử lý:

• T1: message 1 dequeue và P1 process

• T2: message 2 dequeue và P2 process

Vì P1 xử lý lâu hơn P2 nên P2 commit trước Wrong!

41

3.5.3. Đảm bảo thứ tự nhận message

• Gom nhóm các message theo một định danh: ví dụ aggregate id

• Các message của một nhóm chỉ được nhận bởi một thread tại một

thời điểm

• Tận dụng các tính năng Partition của Kafka hoặc Session của Windows

Service Bus để đảm bảo thứ tự message khi routing

42

3.6. Tích hợp hệ thống.

• Message Bus giúp đơn giản quá trình tích hợp message

• Các thành phần tích hợp dựa trên nền tảng message bus

43

Context A Context B

Message Bus

3.6. Tích hợp hệ thống.

• Giữa các context không nên biết tới thành phần sẽ consumer

message của nó

• Logic luồng message khác với logic thực thi tại từng thành phần

• Các context khác nhau yêu cầu các định dạng message khác nhau

44

3.6.1. Process Manager

• Dùng để giải quyết vấn đề điều phối giữa các luồng message

• Đóng vai trò là thành phần trung tâm trong việc tổ chức logic của

luồng message

• Không xử lý logic nghiệp vụ, chỉ làm logic điều phối luồng.

• Phát huy vai trò lớn khi các logic luồng phức tạp.

45

3.6.2. Process Manager

46

Context A Context B

Message Bus

Process

Manager

3.6.3. Translator Pattern

• Đóng vai trò chuyển đổi message thành các định dạng phù hợp với

consumer

• Tách logic phát message khỏi logic transform message

47

Context A Context B

Message Bus

Translator B

4. Case Studies

• Một số yêu cầu cơ bản của bàn tài toán giao vận.

• Xác định các đối tượng dữ liệu cơ bản

• Xây dựng cấu trúc đầu tiên

• Apply Event Sourcing

• Event Handler/Command Handler

• Mô hình hệ thống

48

4.1. Các yêu cầu cơ bản.

• Quản lý các đối tượng hàng hóa: đơn hàng, gói hàng, carton…

• Quản lý luồng nghiệp vụ đơn hàng: gom hàng, nhặt hàng, xuất

nhập…

• Theo dõi trạng thái đơn hàng

• Báo cáo và phân tích

49

4.2. Các đối tượng cơ bản

50

SO

Items

Package

Items

Carton

Items

4.3. Xây dựng cấu trúc đầu tiên

51

ApplicationIn

fras

tru

ctu

res Application Service

Domain Service

Domain Model

4.3.1. Domain Models

52

public partial class SO : EventSourced, IStateContext

public partial class Package : EventSourced, IStateContext

public partial class Carton : EventSourced, IStateContext

4.2.2. Infrastructure

53

public interface IRepository<Context> where Context : DbContext

{

void Save<T>( T aggregate ) where T : class;

T Find<T>( object id ) where T : class;

IQueryable<T> Get<T>( Expression<Func<T, bool>> predicate ) where T :

class;

}

4.2.3. Domain Services

54

public class PackageService : IPackageService

{

private readonly Func<IRepository<DbContext>>

repositoryFactory;

public Package CreatePackage(CreatePack param)

{

Package package =

createActivity.MakePackage(param);

repository.Save<Package>(package);

repository.SaveChanges();

return package;

}

}

4.3. Apply Event Sourcing

• Quản lý các đối tượng trạng thái các đối tượng hàng hóa để theo dõi

• Xây dựng model cho việc lưu trữ event

• Thay đổi tầng lưu trữ để đảm bảo không thay đổi tầng logic

55

4.3.1. Xây dựng model cho event

56

Event Sourced

- ListPendingEvent (VersionEvent)

- Version: integer

- RaiseEvent(Event)

SO CartonPackage

VersionEvent

- SourceId: Guid

- Version: integer

StateChan

ed Event

4.3.1. Xây dựng model cho event

57

4.3.1. Xây dựng model cho event

58

4.3.3. Thay đổi Infrastructure

• Lưu trữ thay đổi thì gửi event đi

• Chỉ thay đổi tầng Repository

59

4.3.3. Thay đổi Infrastructure

60

4.3.3. Domain Service giữ nguyên

• Chi cấu hình Dependency Injection lại Repository, giữ nguyên logic

61

4.3.4. Event Handler/Command Handler

62

Event Bus

Message Receiver

Message Dispatcher Command Dispatcher

Infrastructures

Domain Service

Comand Handler Event Handler

4.3.4. Event Handler/Command Handler

63

4.5. Mô hình hệ thống

64

Command/Event Bus

Carton

Processing

Tracking

System

SO

Processing

Data

Warehoouse

Package

Processing

Routing

Optimize

5. Kết luận

1. DDD giúp có một cấu trúc tách bạch, rõ ràng

2. Phải thiết kế để mọi thành phần đều có thể thay

thế và mở rộng

3. Event Drivent Architecture phù hợp để scaling mở

rộng hệ thống.

4. Sử dụng một model thống nhất

5. Xây dựng tách bách infrastructure với business layer

65

Xin chân thành cám ơn!

top related