12. Request trong hệ thống Microservices
• Service chạy trên nhiều máy
chủ, ở nhiều port khác nhau
• Các service có thể bật, tắt,
bổ sung bất cứ lúc nào
→ Làm sao để biết service ở
đâu để gọi?
12
13. Service Discovery - Eureka
• Mỗi 1 service được định danh bằng
serviceId
• Service sử dụng Eureka Client để tương
tác với Eureka Server:
• Register: đăng ký mới (serviceId, host,
port)
• Renew: sử dụng heartbeats định kỳ đăng
ký lại để biết service còn hoạt động
• Get Registry: trả về danh sách host:port
của các service theo serviceId
13
14. Request vào hệ
thống Microservices
• Kết nối vào hệ thống trở nên
phức tạp do phải biết
serviceId, phải kết nối đến
Service Discovery
• Nginx không biết được sự thay
đổi của các service để gọi &
cân tải
→ Làm sao để đơn giản hóa việc
gọi vào các microservices?
14
15. API Gateway - Zuul
• Địa chỉ truy xuất duy nhất để gọi vào các microservices
• Zuul là edge service -> không dùng để các microservices gọi lẫn nhau
• Zuul sử dụng Ribbon để gọi tới các service
• Eureka Client
• Client Load Balancer
• Caching
• ZuulFilter: tiền xử lý request trước khi gọi sang các service
15
16. API Gateway & Service Discovery
16
Get Registry
order
10.0.0.1:8080
10.0.0.2:8081
10.0.0.3:8082
18. Centralized Configuration
18
Vấn đề:
- Cấu hình phân tán, khó
kiểm soát
- Các service có 1 số cấu
hình chung, thay đổi là
phải đổi hàng loạt
- Reload config khi đang
chạy
20. Spring Cloud Config
• Thông tin file cấu hình được lưu trong git hoặc file vật lý
• Tên file: {serviceId}.yml
• Nhiều môi trường: dev, test, stage, live...
• Kế thừa từ application.yml: mọi service đều lấy cấu hình
chung
• File bootstrap.yml: cấu hình serviceId, config server, môi
trường
• Reload Config: HTTP GET [service-host:port]/refresh
• Spring Cloud Bus – auto reload
20
22. Đối tượng yêu cầu truy cập
• 1st Party: Backend, quản trị hệ thống...: toàn quyền truy xuất mọi
website
• 3rd Party: ứng dụng của các nhà phát triển cung cấp thêm tính năng
cho chủ cửa hàng: chủ cửa hàng cấp quyền truy xuất từng tài nguyên
• Mobile app: đăng nhập để lấy token truy xuất, quyền theo tài khoản
đăng nhập
→Cần 1 phương thức xác thực & kiểm tra quyền linh hoạt -> OAuth2 +
Spring Security
22
23. 23
Ghi chú:
• 3rd Apps: xác thực OAuth qua
Access Token
• Sapo Mobile App: Client Credential
• Backend: Client Credential, Session
Credential (Share session giữa
Backend và OAuth Server).
• 3rd App: có quyền trên mọi cửa
hàng , Sapo Mobile App +
Backend: Có quyền trên cửa hàng
được cấu hình
25. 1 Dockerfile cho mọi service
FROM frolvlad/alpine-oraclejdk8:slim
ADD lib lib
ADD order.jar app.jar
RUN sh -c 'touch /app.jar'
ENTRYPOINT ["java","-Xmx128m","-Xms128m","-
Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
25
26. CI/CD với Jenkins & Docker
• Sử dụng Spotify docker-maven-plugin:
• Tách lớp thư viện ra thư mục riêng & cache được layer này, giảm kích thước
image (~75MB)
• Giảm network traffic & thời gian deploy (~200-700KB dữ liệu mỗi lần update)
• Tự động gán tag Docker image:
{git_commit_short_code}-{branch} -> 4b4a71ef-dev
26
27. Kết hợp Netflix OSS với Docker Swarm
• Zuul làm API Gateway
• Eureka làm Service Discovery
• Ribbon Client để gọi giữa các microservices
• Docker Swarm:
• Quản lý các microservices
• Deploy, scale, update các microservices
27
28. 28
1. Dev push code lên Gitlab
2. Gitlab webhook
gọi sang Jenkins
3. Jenkins pull code từ Gitlab:
- mã nguồn
- Dockerfile
- Jenkinsfile
4. Biên dịch & build Docker
image, tự động gắn tag image
5. Push image lên
Private Docker Registry
6. Bắn webhook sang Jenkins
server khác, thực hiện lệnh
docker service update
30. Yêu cầu với sản phẩm SAPO
• Đáp ứng nhiều nghiệp vụ
• Nghiệp vụ phức tạp
• Maintainable code
• Tính đúng đắn dữ liệu
• Performance
→ lựa chọn Domain Driven Design (DDD) & xử lý bất đồng bộ qua
Message Queue
30
31. Tại sao chọn DDD?
• Kiểm soát tốt nghiệp vụ trong code
• Code có thể maintain được
• Dễ dàng sửa chữa khi có lỗi hoặc nghiệp vụ thay đổi
• Đảm bảo tính đúng đắn dữ liệu do toàn bộ Aggregate được lưu trong
1 transaction
31
32. Một số khái niệm
• Entity: đối tượng được định danh
• Aggregate: một nhóm các entity có quan hệ với nhau phản ánh
nghiệp vụ của domain
• Aggregate Root: là entity đại diện cho Aggregate
• Sub Entity: các entity còn lại trong Aggregate
• Repository: lưu trữ aggregate và truy xuất dữ liệu
• Domain Event: các event xảy ra trong Aggregate Root
32
34. Identity trong DDD
• Entity cần được định danh luôn khi khởi tạo
• Kết quả của nghiệp vụ được lưu trữ qua 1 transaction (Repository
save nguyên Aggregate Root)
• Có nhiều nghiệp vụ map các entity & sub entity, cần biết Id của nhau.
Ví dụ: Order tạo Fulfillment -> event fulfillment_created, data
của event cần có FulfillmentId
→ SQL Server support cơ chế generate Id
SELECT NEXT VALUE FOR SeqOrderId
EXEC sp_sequence_get_range
34
35. Xử lý xung đột khi update dữ liệu
• Cùng 1 thời điểm có nhiều người dùng cập nhật 1 entity.
• Ví dụ: cùng thời điểm 1 nhân viên xác nhận đơn hàng, 1 nhân viên
khác hủy đơn hàng. Cần đảm bảo ai cập nhật trước thành công,
người cập nhật sau thất bại.
→ Optimistic Lock cho Aggregate Root
Đánh version cho bảng Order, mọi thao tác update lên Order hoặc bất
cứ Sub Entity nào trong Order Aggregate cũng sẽ thay đổi order version
35
36. Tối ưu update cho Repository
• 1 Aggregate chỉ được lưu bằng 1 hàm duy nhất
• Order Domain có 8 Sub Entity liên quan -> update cho ít nhất 9 bảng
→ Cơ chế xác định sự thay đổi ở entity và sub entity, chỉ update entity
và những sub entity nào thay đổi.
Bất cứ thay đổi nào ở sub entity -> thay đổi ở entity
this.modify = true;
this.modifiedOn = Util.getUTC();
36
40. Tại sao dùng Kafka?
• Distributed Streaming Platform
• Hỗ trợ Pub/Sub
• High performance
• Đảm bảo consumer xử lý message đúng thứ tự
mà producer gửi trên 1 partition
• Đảm bảo ko mất message, tất cả các message
trong queue đều đc xử lý
• Exactly one message process
40
41. Exactly one message process
• Mỗi message chỉ được xử lý 1 lần ứng với 1 nghiệp vụ xác định
• Có 2 cách:
• Kafka hỗ trợ - lưu offset & data đẩy vào kafka trong cùng 1 transaction
• Tự implement
• SAPO tự implement do dữ liệu nghiệp vụ lưu trong DB
• Sử dụng transaction cho việc lưu offset đồng thời với việc lưu dữ liệu
nghiệp vụ
41
43. Giải pháp: Kafka Connect
43
Aggregate
save
Kafka
ConnectDB
Kafka
Transaction
• Lưu Aggregate + message vào
DB trong cùng transaction
• Kafka connect đẩy msg từ db
vào kafka
→ performance ko tốt bằng đẩy
thằng vào kafka nhưng đảm bảo
chính xác
44. Ví dụ phân hệ bán hàng
• 2 màn hình bán hàng
• Bán hàng online
• Đồng bộ từ kênh bán hàng
• Nhân viên chọn hàng cho Khách (gọi điện, chat)
• Cần phải giao hàng cho khách
• Bán hàng tại quầy (POS)
• Khách mang hàng ra thanh toán
• Nhận hàng luôn tại quầy
44
48. Quy trình POS – 1 thao tác
48
fulfillment_received
payment_added
ETL Job,
Webhook Job,
Notification Job,
Stock Job,
Debt Job
Tạo đơn
Duyệt
Đóng gói
Xuất kho
Thanh toán
Kafka
created
finalized
fulfillment_added
49. Lợi ích sử dụng DDD & Message Queue
• 2 quy trình khác nhau nhưng cùng chung 1 Order Domain xử lý
• Linh hoạt trong việc thay đổi quy trình hoặc tạo ra quy trình mới
49
50. Hướng cải tiến hệ thống
• Đẩy thẳng dữ liệu vào Kafka không phải lưu vào DB
• Tăng Performance phần Order
50