This commit is contained in:
Leonard-ThindPad-P50
2026-09-08 10:26:21 +07:00
commit c81f249920
169 changed files with 38726 additions and 0 deletions

View File

@@ -0,0 +1,205 @@
---
section: "03"
title: Thiết kế kiến trúc
status: approved
version: 1
reviewer_notes: ""
---
# 3. Thiết kế kiến trúc (System Architecture Design)
## 3.1 Mô hình kiến trúc
### Lựa chọn: Kiến trúc hướng dịch vụ theo bounded-context (Coarse-grained Service-Oriented / "modular microservices"), kết hợp Event-Driven cho các luồng bất đồng bộ
Hệ thống được chia thành khoảng 10 service nghiệp vụ độc lập (mỗi service sở hữu dữ liệu riêng — database-per-service), giao tiếp đồng bộ qua REST cho các thao tác request/response và bất đồng bộ qua message broker (Kafka/Amazon MSK, hoặc SQS/SNS cho các luồng đơn giản hơn) cho các quy trình chuỗi nhiều bước (đặt hàng → thanh toán → trừ tồn kho → tính hoa hồng → payout → thông báo).
Đây **không phải** microservices chi tiết theo từng entity (tránh over-engineering), mà là mô hình "modular monolith được service hoá theo domain lớn" — mỗi service tương ứng một bounded context nghiệp vụ rõ ràng, đủ nhỏ để một nhóm 3-6 kỹ sư sở hữu, đủ lớn để tránh chi phí vận hành/network overhead của hàng chục nano-service.
### Danh sách service và đối chiếu với FR/NFR
| Service | Trách nhiệm chính | FR phục vụ | NFR/ràng buộc liên quan |
|---|---|---|---|
| **Identity & Access Service** | Đăng ký/đăng nhập email-password, OAuth Google/Facebook, MFA cho Admin/Seller, phát hành JWT/session | FR-01, FR-02, FR-27 | NFR-04 (bảo mật), tách riêng để cô lập rủi ro credential/PII |
| **Catalog & Inventory Service** | Quản lý Product/SKU/Category, tồn kho do seller cập nhật, wishlist, quản trị catalog toàn sàn (admin ẩn/gỡ sản phẩm vi phạm) | FR-04 (dữ liệu gốc), FR-10, FR-18, FR-24 | NFR-01, NFR-06 (đa ngôn ngữ nội dung sản phẩm), NFR-07 |
| **Search subsystem** (thành phần đọc, không phải service độc lập có team riêng) | Chỉ mục tìm kiếm/filter sản phẩm (OpenSearch), đồng bộ qua event từ Catalog | FR-04 (tìm kiếm) | NFR-01 (<2s), NFR-02 (cache/CDN, chịu tải đỉnh flash sale) |
| **Cart & Order Service** | Giỏ hàng đa seller, checkout, tách đơn theo seller, vòng đời đơn hàng, tiếp nhận yêu cầu đổi trả/khiếu nại, xem đơn theo seller | FR-05, FR-06, FR-08, FR-09, FR-19 | NFR-01 (checkout <3s), NFR-02 (queue hấp thụ đột biến đặt hàng flash sale) |
| **Payment Service** | Tích hợp VNPay/Momo, xử lý luồng COD, đối soát giao dịch, không lưu dữ liệu thẻ | FR-07 | NFR-04, NFR-05 (giảm phạm vi PCI-DSS bằng cách cô lập service này và không lưu card data) |
| **Seller Management Service** | Onboarding & KYC (upload/duyệt giấy tờ), quản trị seller (khoá/duyệt), dashboard báo cáo doanh thu | FR-17, FR-20, FR-23 | NFR-04 (PII giấy tờ KYC lưu S3 mã hoá riêng biệt), NFR-05 |
| **Commission & Payout Service** | Cấu hình bảng hoa hồng theo ngành hàng, tính hoa hồng, lịch payout hàng tuần, kỳ giữ tiền (hold), tạo lệnh chuyển khoản ngân hàng | FR-21, FR-22 | NFR-05 (tuân thủ tài chính), tách riêng khỏi Seller Management vì đây là luồng tài chính nhạy cảm cần audit trail riêng |
| **Promotion & Loyalty Service** | Cấu hình mã giảm giá/khuyến mãi, tích/đổi điểm thưởng, xếp hạng thành viên | FR-13, FR-14 | NFR-07 |
| **Review Service** | Đánh giá/nhận xét sản phẩm sau khi mua | FR-11 | NFR-01 |
| **Notification Service** | Gửi email/SMS xác nhận đơn hàng, cập nhật trạng thái giao hàng, là consumer của các domain event | FR-12 | NFR-02 (qua queue, không chặn luồng chính), NFR-06 (nội dung đa ngôn ngữ) |
| **Shipping & Fulfillment Service** | Điều phối đóng gói/tồn kho vận hành, tích hợp GHN/GHTK, cập nhật trạng thái giao hàng, hỗ trợ Ops/Warehouse | FR-26 | NFR-01, NFR-08 |
| **Dispute/CSR handling** | Xử lý tranh chấp — triển khai như module trong Cart & Order Service với quyền truy cập mở rộng cho CSR/Admin (không tách service riêng vì khối lượng nghiệp vụ chưa đủ lớn để cần đội riêng) | FR-25 | NFR-04 (kiểm soát quyền truy cập CSR ở mức đọc + ghi có giới hạn) |
Ghi chú: FR-15 (đa ngôn ngữ) và FR-16 (đa tiền tệ hiển thị) không phải là service riêng mà là **năng lực xuyên suốt (cross-cutting)** được triển khai qua i18n framework ở tầng frontend/BFF và trường ngôn ngữ/tỷ giá lưu ở Catalog & Pricing config — phục vụ NFR-06.
### Đối chiếu quyết định kiến trúc với NFR/ràng buộc
- **NFR-02 (scale-out, cache, CDN, MQ ngay từ đầu) + quy mô "large"** → đây là lý do chính không chọn Monolith đơn khối: cần scale độc lập Catalog/Search (đọc nhiều) và Cart/Checkout (ghi nhiều, đột biến flash sale) mà không kéo theo toàn bộ hệ thống. Message broker (Kafka/MSK) tách rời các bước xử lý sau khi đặt hàng thành công (tính hoa hồng, payout, notification, loyalty) để không làm chậm phản hồi checkout.
- **NFR-01 (checkout <3s, catalog/search <2s ngay cả tải đỉnh)** → Search tách thành subsystem riêng dùng OpenSearch + cache Redis, không query trực tiếp DB giao dịch; Cart & Order Service dùng cache cho giỏ hàng (Redis) và queue để đệm đơn hàng khi tải đỉnh thay vì xử lý đồng bộ toàn bộ chuỗi nghiệp vụ.
- **NFR-05/PCI-DSS scope giảm** → Payment Service là biên cô lập duy nhất giao tiếp với VNPay/Momo; không service nào khác lưu trữ thông tin thẻ; giảm phạm vi kiểm toán PCI-DSS xuống 1 service thay vì toàn hệ thống.
- **NFR-04 (PII, giấy tờ KYC)** → Seller Management Service lưu file KYC trong S3 bucket riêng có mã hoá + access policy giới hạn (chỉ Seller Management Service và Admin), tách khỏi Identity Service để giảm bề mặt tấn công.
- **FR-06 checkout tách đơn theo seller + FR-21/22 commission/payout** → tách Commission & Payout thành service riêng để có audit trail tài chính độc lập, tránh commission logic bị lẫn với logic vận hành seller (onboarding/KYC) vốn thay đổi thường xuyên hơn.
- **NFR-07 (maintainability, module hoá theo nhóm)** → ranh giới service theo domain cho phép các đội catalog/order/seller/payment phát triển và release độc lập, khớp với ghi chú NFR-07 trong mục 2.
- **NFR-08 (vận hành, escalation 24/7 cho sự cố nghiêm trọng)** → các service giao dịch cốt lõi (Cart & Order, Payment, Identity) được ưu tiên chạy multi-AZ với auto-scaling và health check chặt hơn các service ít quan trọng hơn (Review, Promotion).
### Trade-off và phương án bị loại
| Phương án | Lý do cân nhắc | Lý do loại/không chọn hoàn toàn |
|---|---|---|
| **Monolith truyền thống (1 codebase, 1 DB)** | Đơn giản triển khai, phù hợp đội nhỏ, chi phí vận hành thấp | Loại — không đáp ứng NFR-02 (yêu cầu scale-out ngang từ đầu) và không cho phép scale độc lập Catalog/Search khỏi Checkout khi tải đỉnh flash sale; rủi ro một lỗi nhỏ ở module ít quan trọng (VD Review) có thể ảnh hưởng uptime toàn hệ thống (mâu thuẫn NFR-03 99.9%) |
| **Microservices chi tiết (chia theo từng entity, 20-30+ service)** | Scale/độc lập tối đa theo lý thuyết | Loại — độ phức tạp vận hành (distributed tracing, service mesh, quản lý hàng chục pipeline CI/CD) vượt quá nhu cầu thực tế của MVP; ngân sách/timeline chưa xác định (giả định #7, mục 5 brief) → rủi ro chậm tiến độ; chọn mức "coarse-grained" cân bằng hơn |
| **Modular Monolith (module hoá trong 1 process, chưa tách service)** | Giữ đơn giản vận hành, vẫn module hoá code theo domain | Cân nhắc làm bước đệm hợp lý cho giai đoạn đầu, nhưng không chọn làm kiến trúc mục tiêu vì NFR-02 yêu cầu rõ scale-out ngang và MQ ngay từ đầu — nếu chọn modular monolith sẽ cần re-architect sớm khi traffic tăng, tốn kém hơn là tách service hợp lý từ đầu cho các domain đã biết rõ tải cao (Catalog/Search, Checkout) |
| **Event-Driven thuần tuý (toàn bộ giao tiếp qua event, không REST)** | Độ tách rời (decoupling) cao nhất | Loại một phần — các luồng cần phản hồi tức thời cho người dùng (đăng nhập, xem catalog, checkout, thanh toán) phù hợp hơn với REST đồng bộ; event chỉ dùng cho luồng nghiệp vụ chuỗi phía sau (post-order processing) để tránh độ trễ cảm nhận (perceived latency) không cần thiết |
## 3.2 Sơ đồ thành phần & triển khai (Component & Deployment Diagram)
```mermaid
flowchart TB
subgraph Clients
WebCustomer["Web Storefront (Customer/Guest)\nResponsive SPA"]
SellerPortal["Seller Portal"]
AdminPortal["Admin/Ops/CSR Backoffice"]
end
CDN["CloudFront CDN\n(static assets, ảnh sản phẩm)"]
WAF["AWS WAF"]
ALB["Application Load Balancer"]
APIGW["API Gateway / BFF layer\n(routing, auth check, rate limit)"]
subgraph CoreServices["Core Services (ECS Fargate / EKS, auto-scaling)"]
IDSvc["Identity & Access Service"]
CatalogSvc["Catalog & Inventory Service"]
SearchSvc["Search subsystem\n(OpenSearch)"]
CartOrderSvc["Cart & Order Service\n(+ Dispute handling)"]
PaymentSvc["Payment Service"]
SellerSvc["Seller Management Service\n(KYC/onboarding)"]
CommissionSvc["Commission & Payout Service"]
PromoLoyaltySvc["Promotion & Loyalty Service"]
ReviewSvc["Review Service"]
NotifySvc["Notification Service"]
ShippingSvc["Shipping & Fulfillment Service"]
end
Redis[("ElastiCache Redis\ncache, session, giỏ hàng")]
RDS[("RDS PostgreSQL Multi-AZ\ndatabase-per-service")]
S3[("S3\nảnh sản phẩm, KYC docs, invoice")]
MQ["Message Broker\n(Amazon MSK/Kafka hoặc SQS/SNS)"]
subgraph External["Dịch vụ bên ngoài"]
VNPay["VNPay"]
Momo["Momo"]
GHN["GHN"]
GHTK["GHTK"]
EmailSMS["Email/SMS Provider\n(SES/SNS hoặc SendGrid/Twilio)"]
Bank["Ngân hàng\n(chuyển khoản payout)"]
OAuth["Google/Facebook OAuth"]
end
WebCustomer --> CDN
WebCustomer --> WAF
SellerPortal --> WAF
AdminPortal --> WAF
WAF --> ALB --> APIGW
APIGW --> IDSvc
APIGW --> CatalogSvc
APIGW --> SearchSvc
APIGW --> CartOrderSvc
APIGW --> PaymentSvc
APIGW --> SellerSvc
APIGW --> CommissionSvc
APIGW --> PromoLoyaltySvc
APIGW --> ReviewSvc
APIGW --> ShippingSvc
IDSvc --> RDS
IDSvc --> OAuth
CatalogSvc --> RDS
CatalogSvc --> S3
CatalogSvc -.event.-> MQ
MQ -.sync index.-> SearchSvc
SearchSvc --> Redis
CartOrderSvc --> RDS
CartOrderSvc --> Redis
CartOrderSvc -.event.-> MQ
PaymentSvc --> RDS
PaymentSvc --> VNPay
PaymentSvc --> Momo
PaymentSvc -.event.-> MQ
SellerSvc --> RDS
SellerSvc --> S3
MQ -.consume.-> CommissionSvc
CommissionSvc --> RDS
CommissionSvc --> Bank
MQ -.consume.-> PromoLoyaltySvc
PromoLoyaltySvc --> RDS
ReviewSvc --> RDS
MQ -.consume.-> NotifySvc
NotifySvc --> EmailSMS
ShippingSvc --> RDS
ShippingSvc --> GHN
ShippingSvc --> GHTK
MQ -.consume.-> ShippingSvc
```
Ghi chú kiến trúc triển khai:
- Mỗi service chạy container hoá trên ECS Fargate (hoặc EKS nếu cần kiểm soát sâu hơn), auto-scaling group riêng theo tải thực tế của từng domain (Catalog/Search và Cart/Order được cấp cấu hình auto-scale nhanh hơn cho mùa flash sale).
- Database theo mô hình "database-per-service" trên RDS PostgreSQL Multi-AZ; không service nào truy cập trực tiếp DB của service khác — chỉ qua API hoặc event.
- Redis (ElastiCache) dùng chung cho cache catalog/search, lưu session, và giỏ hàng (giỏ hàng cần độ trễ thấp, có thể chấp nhận mất dữ liệu tạm thời thấp).
- Message broker là xương sống cho các luồng bất đồng bộ: OrderPlaced, PaymentConfirmed, OrderDelivered (khởi động đếm hold), CommissionCalculated, PayoutScheduled, InventoryReserved, ReviewEligible, LoyaltyPointsEarned, NotificationRequested.
- API Gateway/BFF đảm nhiệm xác thực token (JWT), rate limiting, và có thể tách thành 3 BFF nhỏ (Customer BFF, Seller BFF, Admin BFF) để tối ưu payload riêng cho từng loại client — chi tiết endpoint sẽ do `api-designer` đặc tả ở mục 4.
- Thiết kế chi tiết bảo mật (mã hoá at-rest/in-transit, KMS, WAF rule cụ thể) thuộc mục 8; ở đây chỉ thể hiện vị trí kiến trúc của các control đó (WAF, S3 mã hoá, cô lập Payment Service).
## 3.3 Môi trường triển khai (Environments)
| Môi trường | Kích cỡ hạ tầng | Dữ liệu | Feature flag | Quyền truy cập |
|---|---|---|---|---|
| **Dev** | 1 instance/service, cấu hình nhỏ nhất (VD Fargate 0.25-0.5 vCPU), RDS single-AZ, không cần OpenSearch cluster nhiều node | Dữ liệu giả lập (seed/synthetic), không chứa PII/KYC thật | Tất cả feature flag mặc định bật để dev/test tính năng mới | Đội kỹ sư phát triển; không giới hạn IP |
| **Staging** | Cấu hình gần giống Production nhưng scale nhỏ hơn (1-2 instance/service), RDS Multi-AZ nhỏ, OpenSearch cluster nhỏ | Dữ liệu đã ẩn danh hoá (anonymized) từ Production hoặc dữ liệu giả lập quy mô lớn hơn Dev để test hiệu năng; **không** đưa PII/KYC thật vào Staging (tuân thủ NĐ13/2023) | Feature flag phản ánh trạng thái sắp release (dùng để UAT/regression trước khi lên Production) | Đội QA, Product Owner, stakeholder UAT; giới hạn qua VPN/IP allowlist |
| **Production** | Auto-scaling theo tải thực tế, RDS Multi-AZ + read replica cho các bảng đọc nhiều (Catalog), OpenSearch cluster đa node, CDN toàn cầu qua CloudFront | Dữ liệu thật (PII khách hàng/seller, giao dịch thanh toán, KYC) — mã hoá at-rest, phân quyền truy cập nghiêm ngặt | Feature flag kiểm soát rollout dần (canary/phần trăm người dùng) cho tính năng rủi ro cao (VD thay đổi luồng thanh toán/commission) | Chỉ đội vận hành (Ops) và Admin được cấp quyền truy cập hạ tầng qua IAM role có audit log; không truy cập DB Production trực tiếp trừ trường hợp khẩn cấp có phê duyệt |
Ghi chú: cả 3 môi trường đều nằm trên AWS theo giả định #7/#10 (mục 1.4 — 01-tong-quan.md). Production yêu cầu hỗ trợ vận hành giờ hành chính kèm escalation 24/7 cho sự cố nghiêm trọng (NFR-08) — chi tiết on-call/runbook thuộc mục 9 (Kế hoạch vận hành & Kiểm thử).
## 3.4 Tích hợp bên thứ ba
| Dịch vụ | Giao thức | Timeout/Retry | Fallback khi lỗi | Trách nhiệm |
|---|---|---|---|---|
| **VNPay** | REST/HTTPS (redirect + callback/IPN xác nhận giao dịch) | Timeout gọi API: 10s; retry callback xử lý idempotent tối đa 3 lần với backoff (do VNPay có thể gọi lại IPN) | Nếu callback không nhận được sau ngưỡng thời gian, đơn hàng chuyển trạng thái "chờ xác nhận thanh toán" và có job đối soát định kỳ (reconciliation) gọi API tra cứu giao dịch; khách hàng được thông báo trạng thái tạm thời | Payment Service |
| **Momo** | REST/HTTPS (tương tự VNPay: redirect + IPN) | Timeout 10s; retry callback idempotent tối đa 3 lần | Tương tự VNPay — job đối soát định kỳ tra cứu trạng thái giao dịch qua API Momo | Payment Service |
| **COD (thu tiền mặt khi giao)** | Không phải tích hợp API bên ngoài — là luồng nghiệp vụ nội bộ, xác nhận thu tiền do đơn vị vận chuyển/Ops cập nhật thủ công hoặc qua webhook GHN/GHTK | Không áp dụng timeout API; SLA xác nhận thu tiền phụ thuộc đơn vị vận chuyển | Nếu đơn vị vận chuyển không cập nhật trạng thái thu tiền đúng hạn, CSR có quy trình đối soát thủ công định kỳ | Cart & Order Service (trạng thái đơn) + Shipping & Fulfillment Service |
| **GHN** | REST/HTTPS (tạo vận đơn, tra cứu trạng thái, webhook cập nhật) | Timeout 8s; retry tạo vận đơn tối đa 3 lần với backoff; webhook xử lý idempotent | Nếu GHN không phản hồi, hệ thống chuyển sang thử tạo vận đơn qua GHTK (nếu seller/khu vực hỗ trợ) hoặc đưa vào hàng đợi retry thủ công cho Ops xử lý | Shipping & Fulfillment Service |
| **GHTK** | REST/HTTPS (tương tự GHN) | Timeout 8s; retry tối đa 3 lần | Tương tự GHN — fallback chéo hoặc hàng đợi retry thủ công | Shipping & Fulfillment Service |
| **Email/SMS Provider** (đề xuất: AWS SES cho email + AWS SNS/hoặc nhà cung cấp nội địa cho SMS — *nhà cung cấp cụ thể chưa chốt, xem giả định*) | REST/HTTPS hoặc SDK, gửi bất đồng bộ qua queue | Timeout 5s; retry tối đa 5 lần với exponential backoff (do đây là thông báo không chặn luồng chính) | Nếu gửi thất bại sau tất cả lần retry, ghi log lỗi và đưa vào dead-letter queue để CSR/Ops xử lý thủ công (gọi lại/gửi lại); không chặn hoặc rollback đơn hàng | Notification Service |
| **Chuyển khoản ngân hàng (payout)** | Batch file (theo chuẩn ngân hàng, VD NAPAS) hoặc API ngân hàng đối tác — *chưa chốt ngân hàng cụ thể, xem giả định* | Không áp dụng timeout theo nghĩa API tức thời; SLA xử lý batch theo chu kỳ hàng tuần; retry submit file nếu bị từ chối do lỗi định dạng | Nếu batch payout bị từ chối/thất bại, Commission & Payout Service giữ trạng thái "payout thất bại", cảnh báo Admin, và seller được thông báo chậm trễ; không tự động thử lại chuyển tiền để tránh double-payout — cần xác nhận thủ công | Commission & Payout Service + Admin (giám sát) |
| **Google/Facebook OAuth** | OAuth 2.0 / OpenID Connect (redirect flow) | Timeout xác thực 10s | Nếu OAuth provider lỗi, Customer vẫn có thể đăng nhập bằng email/password (không phụ thuộc hoàn toàn vào OAuth) | Identity & Access Service |
## 3.5 Tóm tắt truy vết
Bảng dưới bổ sung cho Ma trận truy vết ở mục 2.4 (cột "Mục thiết kế liên quan" — phần kiến trúc):
| Requirement ID | Service/thành phần chịu trách nhiệm chính |
|---|---|
| FR-01, FR-02, FR-27 | Identity & Access Service |
| FR-03 | Identity & Access Service (hồ sơ) + Catalog & Inventory Service (địa chỉ giao hàng liên kết Order) |
| FR-04, FR-10, FR-18, FR-24 | Catalog & Inventory Service + Search subsystem |
| FR-05, FR-06, FR-08, FR-09, FR-19, FR-25 | Cart & Order Service |
| FR-07 | Payment Service |
| FR-11 | Review Service |
| FR-12 | Notification Service |
| FR-13, FR-14 | Promotion & Loyalty Service |
| FR-15, FR-16 | Cross-cutting i18n/currency (BFF/frontend + Catalog config) |
| FR-17, FR-20, FR-23 | Seller Management Service |
| FR-21, FR-22 | Commission & Payout Service |
| FR-26 | Shipping & Fulfillment Service |
`api-designer` sẽ dùng bảng này làm cơ sở để nhóm endpoint theo service; `data-modeler` dùng ranh giới service ở mục 3.1 làm cơ sở database-per-service khi thiết kế ERD (mục 5).