Skip to main content

Command Palette

Search for a command to run...

Syllabus software engineering (6)

Updated
45 min readView as Markdown

Giai đoạn 12 - Distributed Systems (Ngày 645–721)

Tổng hợp Concurrency (Giai đoạn 5), Networking (Giai đoạn 6), Saga/Outbox (Giai đoạn 8), Replication (Giai đoạn 11) ở quy mô lớn hơn - nhiều máy, không đáng tin cậy, không đồng bộ thời gian.

Nhóm 1: Giới thiệu (Ngày 645–646)

Ngày 645: Giới thiệu Distributed Systems

  • Mục tiêu: Thấy rõ đây là điểm hội tụ của nhiều giai đoạn đã học.

  • Lý thuyết: Distributed System = nhiều máy tính giao tiếp qua network để hoàn thành 1 nhiệm vụ chung, xuất hiện lại toàn bộ vấn đề đã gặp: race condition (Giai đoạn 5) ở quy mô network, latency (Giai đoạn 6), consistency (Giai đoạn 8/11) - nhưng giờ không thể giả định message luôn tới, luôn đúng thứ tự.

  • Thực hành: Liệt kê 3 giả định "an toàn" khi lập trình đơn máy (function call luôn thành công, memory luôn đọc đúng giá trị mới nhất) không còn đúng trong distributed system.

Ngày 646: Fallacies of Distributed Computing

  • Mục tiêu: Có checklist các ngộ nhận kinh điển để tránh mắc phải.

  • Lý thuyết: 8 ngộ nhận nổi tiếng (L. Peter Deutsch): network đáng tin cậy, latency bằng 0, bandwidth vô hạn, network an toàn, topology không đổi, chỉ có 1 administrator, chi phí vận chuyển bằng 0, network đồng nhất.

  • Thực hành: Với 3-service project (Giai đoạn 8), chỉ ra 1 chỗ code đang ngầm giả định 1 trong 8 ngộ nhận này.

Nhóm 2: Communication (Ngày 647–652)

Ngày 647: Ôn lại RPC vs REST trong bối cảnh Distributed System

  • Mục tiêu: Nhìn lại kiến thức đã học (Giai đoạn 9-10) dưới góc độ hệ phân tán.

  • Lý thuyết: Ở quy mô nhiều service, lựa chọn giao thức giao tiếp ảnh hưởng trực tiếp tới độ trễ tổng thể và khả năng chịu lỗi của toàn hệ thống.

  • Thực hành: Vẽ lại sơ đồ 3-service project, đánh dấu giao thức đang dùng cho mỗi cặp giao tiếp (REST/gRPC), đánh giá có hợp lý không.

Ngày 648: Service Discovery

  • Mục tiêu: Hiểu vấn đề: làm sao 1 service biết địa chỉ IP/port của service khác khi chúng có thể chạy trên nhiều máy và thay đổi liên tục.

  • Lý thuyết: Service Discovery - registry trung tâm (VD: Consul, etcd, Eureka) nơi service đăng ký địa chỉ của mình, các service khác tra cứu registry thay vì hardcode địa chỉ.

  • Thực hành: Vẽ sơ đồ: Order Service khởi động → đăng ký vào Service Registry → Payment Service tra cứu Registry để tìm địa chỉ Order Service.

Ngày 649: Load Balancing

  • Mục tiêu: Hiểu cách phân phối traffic khi có nhiều instance của cùng 1 service.

  • Lý thuyết: Round Robin (xoay vòng đơn giản), Least Connections (ưu tiên instance ít tải nhất), thuật toán nào phù hợp workload nào.

  • Thực hành: Lập bảng so sánh Round Robin vs Least Connections theo tiêu chí: độ phức tạp, hiệu quả với request có thời gian xử lý không đều nhau.

Ngày 650: Consistent Hashing

  • Mục tiêu: Học kỹ thuật quan trọng cho việc phân phối dữ liệu/tải ổn định khi số node thay đổi.

  • Lý thuyết: Consistent Hashing giảm thiểu số key cần di chuyển lại khi thêm/bớt node (so với hash đơn giản hash(key) % n, nơi gần như toàn bộ key phải di chuyển khi n đổi).

  • Thực hành: Vẽ sơ đồ vòng tròn hash (hash ring), minh hoạ khi thêm 1 node mới chỉ ảnh hưởng tới 1 phần nhỏ key thay vì toàn bộ.

Ngày 651: API Gateway

  • Mục tiêu: Liên hệ lại Envoy đã học ở Giai đoạn 10.

  • Lý thuyết: API Gateway là điểm vào duy nhất cho client bên ngoài, đảm nhận routing, auth, rate limiting tập trung - tránh client phải biết địa chỉ của từng service nội bộ.

  • Thực hành: Vẽ sơ đồ: client bên ngoài → API Gateway (Envoy) → route tới đúng service nội bộ, xác định trách nhiệm nào (auth, rate limit) nên đặt ở Gateway thay vì từng service.

Ngày 652: Lab - Thiết kế Service Discovery + Load Balancing

  • Mục tiêu: Áp dụng vào 3-service project.

  • Lý thuyết: Ôn lại toàn bộ Ngày 648-651.

  • Thực hành: Thiết kế đầy đủ: mỗi service đăng ký vào registry giả định khi khởi động, Saga Orchestrator (Giai đoạn 8) tra cứu registry thay vì hardcode địa chỉ Payment/Inventory Service.

Nhóm 3: Messaging (Ngày 653–666)

Ngày 653: Message Queue - Giới thiệu

  • Mục tiêu: Có bức tranh tổng quan trước khi học 2 công cụ cụ thể.

  • Lý thuyết: Point-to-point (1 message chỉ 1 consumer xử lý) vs Pub/Sub (1 message nhiều subscriber cùng nhận) - liên hệ lại Observer pattern (Giai đoạn 3) ở quy mô phân tán.

  • Thực hành: Xác định trong 3-service project, event nào nên là point-to-point (VD: ChargePayment command), event nào nên là pub/sub (VD: OrderCreated mà nhiều service quan tâm).

Ngày 654: Kafka - Kiến trúc tổng quan

  • Mục tiêu: Hiểu 3 khái niệm cốt lõi của Kafka.

  • Lý thuyết: Broker (server lưu trữ message), Topic (kênh phân loại message theo chủ đề), Partition (topic được chia nhỏ để scale, mỗi partition là 1 log tuần tự bất biến - liên hệ WAL đã học Giai đoạn 11).

  • Thực hành: Vẽ sơ đồ 1 topic order-events chia thành 3 partition, giải thích vì sao partition giúp Kafka scale ngang.

Ngày 655: Kafka - Producer & Partitioning Strategy

  • Mục tiêu: Hiểu cách Producer quyết định message vào partition nào.

  • Lý thuyết: Partitioning theo key (cùng key luôn vào cùng partition, đảm bảo thứ tự cho message cùng key) hoặc round-robin (không có key).

  • Thực hành: Thiết kế partitioning strategy cho topic order-events: dùng orderId làm key để đảm bảo mọi event của 1 order luôn theo đúng thứ tự.

Ngày 656: Kafka - Consumer & Consumer Group

  • Mục tiêu: Hiểu cách nhiều consumer chia nhau xử lý message.

  • Lý thuyết: Consumer Group - nhiều consumer trong cùng group chia nhau các partition (mỗi partition chỉ 1 consumer trong group xử lý tại 1 thời điểm), cho phép scale xử lý ngang.

  • Thực hành: Vẽ sơ đồ: topic 3 partition, Consumer Group 3 consumer - mỗi consumer nhận đúng 1 partition; thử tăng lên 5 consumer, giải thích 2 consumer sẽ idle.

Ngày 657: Kafka - Offset Management

  • Mục tiêu: Hiểu cách Kafka theo dõi tiến độ đọc và các mức đảm bảo delivery.

  • Lý thuyết: Offset đánh dấu vị trí đã đọc trong partition; at-most-once (commit offset trước khi xử lý - có thể mất message nếu crash), at-least-once (commit sau khi xử lý - có thể xử lý trùng), exactly-once (phức tạp nhất, cần thêm cơ chế transactional).

  • Thực hành: Lập bảng so sánh 3 mức đảm bảo, liên hệ lại Idempotency (Giai đoạn 9) như 1 cách bù đắp cho at-least-once (xử lý trùng không sao vì đã idempotent).

Ngày 658: Kafka - Replication

  • Mục tiêu: Liên hệ lại Replication đã học Giai đoạn 11.

  • Lý thuyết: Mỗi partition có nhiều replica trên các broker khác nhau, 1 replica là leader (nhận write) các replica còn lại là follower - chính là mô hình Leader-Follower đã học, áp dụng cho từng partition.

  • Thực hành: Vẽ sơ đồ 1 partition với replication factor 3, chỉ ra leader và 2 follower.

Ngày 659: Lab - Setup Kafka, viết Producer/Consumer

  • Mục tiêu: Thực hành trực tiếp.

  • Lý thuyết: Ôn lại toàn bộ khái niệm tuần này.

  • Thực hành: Chạy Kafka (qua Docker), viết Producer publish OrderCreated event, Consumer Group subscribe và xử lý.

Ngày 660: RabbitMQ - Kiến trúc tổng quan

  • Mục tiêu: Học công cụ messaging thứ 2, triết lý khác Kafka.

  • Lý thuyết: Exchange (nhận message từ producer, quyết định route đi đâu), Queue (nơi message chờ được consumer lấy), Binding (quy tắc nối Exchange với Queue).

  • Thực hành: Vẽ sơ đồ Exchange → Binding → Queue cho 1 ví dụ đơn giản.

Ngày 661: RabbitMQ - Exchange Types

  • Mục tiêu: Hiểu 4 kiểu routing khác nhau.

  • Lý thuyết: Direct (route theo routing key chính xác), Topic (route theo pattern, VD: order.*), Fanout (broadcast tới mọi queue đã bind), Headers (route theo header thay vì key).

  • Thực hành: Thiết kế Exchange phù hợp cho use case: gửi OrderCreated cho cả Payment Service và Notification Service cùng lúc (gợi ý: Fanout).

Ngày 662: RabbitMQ - Acknowledgment & Dead Letter Queue

  • Mục tiêu: Hiểu cơ chế đảm bảo message không bị mất và xử lý message lỗi.

  • Lý thuyết: Consumer phải ACK sau khi xử lý xong (nếu không ACK, message được redeliver); Dead Letter Queue nhận message bị reject/hết hạn/quá số lần retry, tránh vòng lặp vô hạn.

  • Thực hành: Thiết kế Dead Letter Queue cho message xử lý thất bại quá 3 lần.

Ngày 663: So sánh Kafka vs RabbitMQ

  • Mục tiêu: Có tiêu chí chọn lựa rõ ràng.

  • Lý thuyết: Kafka (log-based, giữ message lâu dài, phù hợp event streaming/replay lịch sử, throughput cực cao) vs RabbitMQ (queue-based, routing linh hoạt hơn, phù hợp task queue truyền thống).

  • Thực hành: Lập bảng so sánh, xác định công cụ phù hợp cho từng nhu cầu trong 3-service project (event streaming cho analytics vs task queue cho xử lý đơn hàng).

Ngày 664: Lab - Setup RabbitMQ

  • Mục tiêu: Thực hành trực tiếp công cụ thứ 2.

  • Lý thuyết: Ôn lại Exchange/Queue/Binding.

  • Thực hành: Chạy RabbitMQ (qua Docker), viết Publisher/Consumer đơn giản với Direct Exchange.

Ngày 665: Lab - Tích hợp Message Broker thật vào Outbox Pattern

  • Mục tiêu: Hoàn thiện Outbox Pattern (Giai đoạn 8) với broker thật thay vì giả lập.

  • Lý thuyết: Ôn lại Message Relay (Ngày 406) - giờ publish thật ra Kafka/RabbitMQ thay vì in log giả lập.

  • Thực hành: Sửa Message Relay của 3-service project để publish event thật ra Kafka (hoặc RabbitMQ), verify event tới đúng consumer.

Ngày 666: Review Messaging

  • Mục tiêu: Tổng hợp nhóm Messaging.

  • Lý thuyết: Tổng hợp: Point-to-point/Pub-Sub, Kafka (log-based), RabbitMQ (queue-based), delivery guarantee.

  • Thực hành: Viết tổng kết: với kiến trúc Saga (Giai đoạn 8) đã thiết kế, message broker nào phù hợp hơn và tại sao.

Nhóm 4: Consistency (Ngày 667–676)

Ngày 667: CAP Theorem

  • Mục tiêu: Học định lý nền tảng nhất của distributed system.

  • Lý thuyết: CAP - Consistency (mọi node thấy cùng dữ liệu), Availability (mọi request đều nhận response), Partition Tolerance (hệ thống vẫn hoạt động khi mất kết nối giữa các node) - không thể có cả 3 cùng lúc khi có Partition xảy ra.

  • Thực hành: Đọc định nghĩa gốc của CAP Theorem, tóm tắt lại bằng lời của mình.

Ngày 668: CAP - Ví dụ thực tế

  • Mục tiêu: Hiểu CAP không phải chỉ là lý thuyết trừu tượng.

  • Lý thuyết: Khi network partition xảy ra giữa 2 node, hệ thống phải chọn: từ chối request (ưu tiên Consistency, CP) hoặc phục vụ request với dữ liệu có thể cũ (ưu tiên Availability, AP).

  • Thực hành: Phân loại 3 hệ thống quen thuộc (PostgreSQL single-node, Cassandra, MongoDB với write concern mặc định) vào CP hoặc AP, giải thích lựa chọn.

Ngày 669: PACELC

  • Mục tiêu: Học phần mở rộng của CAP, thực dụng hơn cho thiết kế thực tế.

  • Lý thuyết: PACELC - nếu có Partition (P) thì chọn giữa Availability (A) và Consistency (C); Else (E, không có partition) thì chọn giữa Latency (L) và Consistency (C) - CAP chỉ nói về lúc có sự cố, PACELC nói cả lúc bình thường.

  • Thực hành: Phân loại lại 3 hệ thống ở Ngày 668 theo PACELC đầy đủ (VD: PA/EL, PC/EC).

Ngày 670: Strong Consistency

  • Mục tiêu: Hiểu mức consistency mạnh nhất.

  • Lý thuyết: Strong Consistency (Linearizability) - mọi read sau 1 write luôn thấy giá trị mới nhất, như thể hệ thống chỉ có 1 bản sao dữ liệu duy nhất - chi phí cao (thường cần đồng bộ hoá giữa các node cho mỗi thao tác).

  • Thực hành: Vẽ sơ đồ minh hoạ Strong Consistency: mọi node luôn trả về cùng giá trị bất kể đọc từ đâu.

Ngày 671: Eventual Consistency

  • Mục tiêu: Liên hệ lại CQRS (Giai đoạn 8) và Replication Lag (Giai đoạn 11).

  • Lý thuyết: Eventual Consistency - nếu không có write mới, cuối cùng mọi replica sẽ hội tụ về cùng giá trị, nhưng tại 1 thời điểm cụ thể có thể đọc được giá trị khác nhau ở các node khác nhau.

  • Thực hành: Liên hệ lại Read Model của CQRS (Giai đoạn 8) - giải thích rõ nó là 1 ví dụ thực tế của Eventual Consistency.

Ngày 672: Causal Consistency

  • Mục tiêu: Học mức trung gian giữa Strong và Eventual.

  • Lý thuyết: Causal Consistency đảm bảo các thao tác có quan hệ nhân-quả (causally related) được thấy đúng thứ tự ở mọi node, còn thao tác không liên quan thì không đảm bảo thứ tự.

  • Thực hành: Vẽ ví dụ: comment "trả lời" 1 bài post phải luôn xuất hiện sau bài post đó ở mọi node xem - đây chính là yêu cầu Causal Consistency.

Ngày 673: Read-your-writes & Monotonic Reads

  • Mục tiêu: Học 2 đảm bảo thực dụng thường được yêu cầu trong sản phẩm thực tế.

  • Lý thuyết: Read-your-writes (user luôn thấy chính thay đổi họ vừa thực hiện, dù hệ thống chỉ Eventual Consistency tổng thể), Monotonic Reads (đã đọc được giá trị mới thì không bao giờ đọc lại giá trị cũ hơn ở lần sau).

  • Thực hành: Với vấn đề Replication Lag đã nêu Ngày 623 (Giai đoạn 11), thiết kế giải pháp đảm bảo Read-your-writes (VD: đọc từ Leader cho request ngay sau write của chính user đó).

Ngày 674: Lab - Phân loại Consistency Model

  • Mục tiêu: Áp dụng lý thuyết vào 3-service project thật.

  • Lý thuyết: Ôn lại toàn bộ các mô hình đã học.

  • Thực hành: Với mỗi luồng dữ liệu trong 3-service project (Order status, Payment balance, Inventory stock), xác định mức consistency cần thiết và mức đang thực sự có.

Ngày 675: Vector Clock

  • Mục tiêu: Học kỹ thuật xác định thứ tự nhân-quả giữa các sự kiện phân tán khi không có đồng hồ chung.

  • Lý thuyết: Vector Clock - mỗi node giữ 1 vector đếm sự kiện của tất cả node, so sánh 2 vector clock cho biết 2 sự kiện có quan hệ nhân-quả hay độc lập (concurrent).

  • Thực hành: Mô phỏng thủ công vector clock cho 3 node với vài sự kiện, xác định cặp sự kiện nào là "happens-before" (liên hệ lại Ngày 255) và cặp nào là "concurrent".

Ngày 676: Review Consistency

  • Mục tiêu: Tổng hợp nhóm Consistency.

  • Lý thuyết: Tổng hợp: CAP → PACELC → các mô hình Consistency → Vector Clock.

  • Thực hành: Viết bài tổng kết liên hệ ngược: CQRS/Saga (Giai đoạn 8) chính là các pattern kỹ thuật để sống chung với Eventual Consistency một cách có kiểm soát.

Nhóm 5: Consensus (Ngày 677–688)

Ngày 677: Consensus Problem

  • Mục tiêu: Hiểu bài toán nền tảng: làm sao nhiều node đồng thuận về 1 giá trị dù có node lỗi/chậm.

  • Lý thuyết: Consensus cần: Agreement (mọi node quyết định cùng giá trị), Validity (giá trị quyết định phải từng được đề xuất bởi 1 node nào đó), Termination (cuối cùng phải đưa ra quyết định).

  • Thực hành: Giải thích vì sao Leader Election (đã gặp ở Ngày 624, Giai đoạn 11) thực chất là 1 bài toán Consensus.

Ngày 678: Raft - Giới thiệu

  • Mục tiêu: Học thuật toán consensus dễ hiểu nhất, được thiết kế có chủ đích để dễ dạy/implement hơn Paxos.

  • Lý thuyết: Raft chia vấn đề thành 3 phần độc lập: Leader Election, Log Replication, Safety.

  • Thực hành: Đọc paper gốc "In Search of an Understandable Consensus Algorithm" phần abstract, tóm tắt mục tiêu thiết kế của Raft.

Ngày 679: Raft - Leader Election

  • Mục tiêu: Hiểu cách các node tự bầu ra 1 Leader.

  • Lý thuyết: Mỗi node có 3 trạng thái (Follower/Candidate/Leader), term (nhiệm kỳ) tăng dần, node chuyển thành Candidate khi hết timeout không nghe thấy Leader, xin vote từ các node khác.

  • Thực hành: Vẽ sơ đồ chuyển trạng thái Follower → Candidate → Leader (hoặc quay lại Follower nếu thua cuộc bầu cử).

Ngày 680: Raft - Log Replication

  • Mục tiêu: Hiểu cách Leader đồng bộ dữ liệu tới Follower sau khi đã được bầu.

  • Lý thuyết: Leader nhận write từ client, ghi vào log của mình, gửi tới Follower - chỉ coi là "committed" khi đa số (majority) node đã ghi log thành công.

  • Thực hành: Vẽ sơ đồ tuần tự: client gửi write → Leader ghi log → gửi AppendEntries tới Follower → đa số ACK → Leader commit → thông báo client.

Ngày 681: Raft - Safety

  • Mục tiêu: Hiểu các ràng buộc đảm bảo tính đúng đắn của thuật toán.

  • Lý thuyết: Election Safety (chỉ 1 leader mỗi term), Leader Append-Only (leader không bao giờ overwrite log của mình), Log Matching (nếu 2 log có cùng entry ở cùng index thì mọi entry trước đó cũng giống nhau).

  • Thực hành: Đọc và tóm tắt 5 tính chất Safety trong paper Raft, giải thích ngắn gọn ý nghĩa của mỗi tính chất.

Ngày 682: Raft - Membership Change

  • Mục tiêu: Hiểu cách Raft xử lý khi cần thêm/bớt node trong cluster.

  • Lý thuyết: Thay đổi cấu hình cluster (thêm/bớt node) cần xử lý cẩn thận để tránh có 2 leader cùng lúc (split-brain) trong giai đoạn chuyển tiếp - Raft dùng joint consensus (cấu hình chuyển tiếp).

  • Thực hành: Vẽ sơ đồ minh hoạ vấn đề nếu thay đổi cấu hình không cẩn thận (2 leader cùng lúc), và cách joint consensus tránh được.

Ngày 683: Lab - Implement Raft Leader Election

  • Mục tiêu: Thực hành hoá phần đầu của thuật toán.

  • Lý thuyết: Ôn lại Ngày 679.

  • Thực hành: Cài đặt phần Leader Election của Raft (đơn giản hoá): 3 node giả lập trên cùng máy (3 process/thread), dùng RPC giả lập, verify luôn bầu ra đúng 1 leader.

Ngày 684: Lab - Implement Raft Log Replication

  • Mục tiêu: Hoàn thiện phần thứ 2.

  • Lý thuyết: Ôn lại Ngày 680.

  • Thực hành: Thêm AppendEntries RPC vào implementation Ngày 683, verify log được đồng bộ đúng tới các Follower khi Leader nhận write.

Ngày 685: Paxos - Giới thiệu ngắn gọn

  • Mục tiêu: Biết thuật toán consensus "kinh điển" khác để so sánh.

  • Lý thuyết: Paxos giải quyết cùng bài toán nhưng khó hiểu/implement hơn Raft (không có khái niệm Leader rõ ràng như Raft) - nhiều hệ thống production cũ dùng Paxos (Chubby, Zookeeper's ZAB là biến thể).

  • Thực hành: Lập bảng so sánh Raft vs Paxos theo tiêu chí: độ dễ hiểu, có Leader rõ ràng hay không, mức độ phổ biến trong hệ thống mới.

Ngày 686: Consensus trong thực tế - etcd, ZooKeeper

  • Mục tiêu: Thấy Consensus được đóng gói sẵn để dùng, không cần tự implement trong production.

  • Lý thuyết: etcd (dùng Raft, nền tảng của Kubernetes), ZooKeeper (dùng ZAB, nền tảng của nhiều hệ thống Hadoop ecosystem) - cả 2 cung cấp sẵn: distributed key-value store, leader election, distributed lock.

  • Thực hành: Đọc tài liệu etcd, liệt kê 3 use case chính nó thường được dùng cho (configuration, service discovery, leader election).

Ngày 687: Lab - Dùng etcd cho Service Discovery/Leader Election

  • Mục tiêu: Áp dụng công cụ thật vào 3-service project, thay thế phần tự implement.

  • Lý thuyết: Ôn lại Service Discovery đã thiết kế Ngày 652 - giờ dùng etcd thật thay vì giả lập.

  • Thực hành: Chạy etcd, đăng ký service vào etcd khi khởi động, dùng etcd để thực hiện leader election cho Saga Orchestrator (đảm bảo chỉ 1 instance Orchestrator hoạt động tại 1 thời điểm nếu chạy nhiều instance).

Ngày 688: Review Consensus

  • Mục tiêu: Tổng hợp nhóm Consensus.

  • Lý thuyết: Tổng hợp: Consensus Problem → Raft (Leader Election, Log Replication, Safety) → Paxos → công cụ thực tế (etcd/ZooKeeper).

  • Thực hành: Viết tổng kết: giải thích vì sao "chỉ cần 1 leader duy nhất tại 1 thời điểm" (đã giả định ở nhiều pattern trước đó như Saga Orchestrator) thực ra là 1 bài toán khó cần Consensus để đảm bảo đúng.

Nhóm 6: Resilience Patterns (Ngày 689–696)

Ngày 689: Retry Pattern

  • Mục tiêu: Học pattern cơ bản nhất để đối phó với lỗi tạm thời.

  • Lý thuyết: Exponential Backoff (tăng dần thời gian chờ giữa các lần retry) kết hợp Jitter (thêm ngẫu nhiên nhỏ để tránh nhiều client retry cùng lúc gây "thundering herd").

  • Thực hành: Viết hàm retry với exponential backoff + jitter cho 1 lời gọi HTTP giả lập hay lỗi tạm thời.

Ngày 690: Circuit Breaker

  • Mục tiêu: Học pattern ngăn hệ thống tiếp tục gọi 1 service đang lỗi liên tục.

  • Lý thuyết: 3 trạng thái - Closed (bình thường, cho request đi qua), Open (service đang lỗi, chặn request ngay lập tức không gọi thật), Half-Open (thử cho 1 số request đi qua để kiểm tra service đã phục hồi chưa).

  • Thực hành: Vẽ sơ đồ chuyển trạng thái Circuit Breaker: Closed → Open (khi tỷ lệ lỗi vượt ngưỡng) → Half-Open (sau timeout) → Closed (nếu request thử nghiệm thành công) hoặc quay lại Open (nếu vẫn lỗi).

Ngày 691: Bulkhead Pattern

  • Mục tiêu: Học cách cô lập lỗi để tránh cascading failure (lỗi lan truyền).

  • Lý thuyết: Bulkhead (lấy cảm hứng từ khoang tàu thuỷ) - chia resource (connection pool, thread pool) thành các khoang riêng biệt cho từng dependency, để 1 dependency chậm/lỗi không làm cạn kiệt resource dùng cho dependency khác.

  • Thực hành: Vẽ sơ đồ minh hoạ: không có Bulkhead, 1 thread pool chung bị Payment Service chậm chiếm hết, làm cả Inventory Service cũng không xử lý được - có Bulkhead, mỗi dependency có thread pool riêng.

Ngày 692: Idempotency trong Retry

  • Mục tiêu: Liên hệ lại Idempotency đã học ở Giai đoạn 9, giờ thấy rõ vì sao nó bắt buộc phải có khi kết hợp Retry.

  • Lý thuyết: Nếu request không idempotent, Retry Pattern (Ngày 689) có thể gây tác dụng phụ nghiêm trọng (VD: charge tiền 2 lần) - Idempotency Key là điều kiện tiên quyết để Retry an toàn.

  • Thực hành: Xem lại thiết kế ChargePayment với idempotency key (Giai đoạn 9), xác nhận nó an toàn khi kết hợp với Retry Pattern.

Ngày 693: Timeout

  • Mục tiêu: Học cách thiết kế timeout hợp lý, tránh cả 2 thái cực.

  • Lý thuyết: Timeout quá ngắn gây lỗi giả (request đang xử lý bình thường nhưng bị coi là fail); timeout quá dài gây tích luỹ resource chờ đợi (liên hệ lại vấn đề Bulkhead giải quyết) - nên set dựa trên percentile latency thực tế (VD: p99) thay vì đoán.

  • Thực hành: Với 3-service project, đề xuất giá trị timeout hợp lý cho lời gọi ChargePayment, giải thích cách bạn sẽ đo để xác định con số này trong thực tế.

Ngày 694: Lab - Implement Circuit Breaker

  • Mục tiêu: Thực hành pattern quan trọng nhất trong nhóm.

  • Lý thuyết: Ôn lại 3 trạng thái Ngày 690.

  • Thực hành: Cài đặt CircuitBreaker class bọc quanh lời gọi Payment Service trong Saga Orchestrator, test cả 3 trạng thái bằng cách giả lập Payment Service lỗi liên tục rồi phục hồi.

Ngày 695: Lab - Implement Retry + Bulkhead

  • Mục tiêu: Hoàn thiện bộ resilience pattern cho 3-service project.

  • Lý thuyết: Ôn lại Retry (Ngày 689) và Bulkhead (Ngày 691).

  • Thực hành: Thêm Retry với backoff cho lời gọi giữa các service, tách connection pool riêng cho từng dependency (Bulkhead).

Ngày 696: Review Resilience Patterns

  • Mục tiêu: Tổng hợp nhóm Resilience Patterns.

  • Lý thuyết: Tổng hợp: Retry + Circuit Breaker + Bulkhead + Idempotency + Timeout - các pattern này luôn nên dùng kết hợp, không dùng đơn lẻ.

  • Thực hành: Viết "Resilience Checklist" cho mọi lời gọi giữa service trong tương lai (VD: có timeout chưa? có retry với backoff chưa? có idempotent chưa? có circuit breaker chưa?).

Nhóm 7: Project - Distributed Job System (Ngày 697–721)

Ngày 697: Thiết kế kiến trúc Distributed Job System

  • Mục tiêu: Tổng hợp toàn bộ Giai đoạn 12 vào 1 project lớn.

  • Lý thuyết: Ôn lại Concurrent Task Scheduler đã xây ở Giai đoạn 5 (Ngày 258-266) - giờ mở rộng thành hệ thống phân tán nhiều node thay vì chỉ đa luồng trên 1 máy.

  • Thực hành: Vẽ sơ đồ kiến trúc tổng thể: Job Queue (message broker), nhiều Worker Node, 1 Scheduler (có failover), Job State Store.

Ngày 698: Xác định yêu cầu

  • Mục tiêu: Làm rõ scope trước khi thiết kế chi tiết.

  • Lý thuyết: Yêu cầu chức năng: submit job, phân phối job cho worker, tracking trạng thái, retry khi thất bại, chịu được worker/scheduler chết.

  • Thực hành: Viết đặc tả yêu cầu đầy đủ (functional + non-functional: throughput mong muốn, độ trễ chấp nhận được).

Ngày 699: Thiết kế Job Queue phân tán

  • Mục tiêu: Chọn và thiết kế cơ chế truyền job.

  • Lý thuyết: Ôn lại Kafka vs RabbitMQ (Ngày 663) - Job Queue phù hợp với mô hình queue-based (RabbitMQ) hơn vì cần point-to-point, mỗi job chỉ 1 worker xử lý.

  • Thực hành: Thiết kế schema message cho 1 job (job ID, loại job, payload, priority), chọn Exchange type phù hợp trên RabbitMQ.

Ngày 700: Thiết kế Worker Node

  • Mục tiêu: Xác định cách worker tham gia vào hệ thống.

  • Lý thuyết: Worker cần đăng ký vào Worker Registry khi khởi động, gửi heartbeat định kỳ để hệ thống biết nó còn sống.

  • Thực hành: Thiết kế schema Worker Registry (worker ID, trạng thái, last heartbeat), dùng etcd (đã học Ngày 686-687) để lưu.

Ngày 701: Thiết kế Leader Election cho Scheduler

  • Mục tiêu: Đảm bảo chỉ 1 Scheduler hoạt động tại 1 thời điểm dù chạy nhiều instance để chịu lỗi.

  • Lý thuyết: Ôn lại Raft/etcd Leader Election (Ngày 679, 687) - Scheduler dùng etcd để bầu leader, chỉ leader mới thực sự phân phối job.

  • Thực hành: Thiết kế cơ chế: nhiều instance Scheduler cùng chạy, dùng etcd lock để chỉ 1 instance active tại 1 thời điểm, các instance khác ở chế độ standby.

Ngày 702: Thiết kế Job Assignment

  • Mục tiêu: Xác định thuật toán phân phối job cho worker.

  • Lý thuyết: Ôn lại Load Balancing (Ngày 649) - áp dụng Least Connections (ưu tiên worker đang xử lý ít job nhất) cho việc phân phối job.

  • Thực hành: Thiết kế thuật toán assignment: Scheduler theo dõi số job đang chạy của mỗi worker (qua Worker Registry), ưu tiên gán job mới cho worker ít tải nhất.

Ngày 703: Thiết kế Fault Tolerance

  • Mục tiêu: Xác định cách hệ thống phản ứng khi worker chết giữa chừng.

  • Lý thuyết: Nếu worker ngừng heartbeat quá 1 khoảng thời gian, Scheduler coi worker đã chết, job đang chạy trên worker đó cần được reassign cho worker khác.

  • Thực hành: Thiết kế timeout cho heartbeat, quy trình reassign job khi phát hiện worker chết, xử lý trường hợp job đã hoàn thành nhưng worker chết trước khi báo cáo kết quả (liên hệ Idempotency).

Ngày 704: Thiết kế Consistency Model cho Job State

  • Mục tiêu: Xác định mức consistency cần thiết cho trạng thái job.

  • Lý thuyết: Ôn lại các mô hình Consistency (Ngày 670-673) - trạng thái job (Pending/Running/Completed/Failed) cần Strong Consistency để tránh 2 worker cùng nhận 1 job, nhưng thông tin thống kê tổng quan có thể Eventual Consistency.

  • Thực hành: Phân loại từng loại dữ liệu trong hệ thống theo mức consistency cần thiết, tương tự lab đã làm Ngày 674.

Ngày 705: Implement Job Queue

  • Mục tiêu: Bắt đầu code.

  • Lý thuyết: Ôn lại thiết kế Ngày 699.

  • Thực hành: Cài đặt Producer publish job lên RabbitMQ theo schema đã thiết kế.

Ngày 706: Implement Worker - Consumer

  • Mục tiêu: Worker nhận và xử lý job.

  • Lý thuyết: Ôn lại Consumer Acknowledgment (Ngày 662).

  • Thực hành: Cài đặt Worker consume job từ Queue, xử lý (giả lập công việc), ACK sau khi hoàn thành.

Ngày 707: Implement Worker Registry + Heartbeat

  • Mục tiêu: Hoàn thiện cơ chế theo dõi worker.

  • Lý thuyết: Ôn lại thiết kế Ngày 700.

  • Thực hành: Cài đặt Worker đăng ký vào etcd khi khởi động, gửi heartbeat định kỳ (VD: mỗi 5 giây).

Ngày 708: Implement Leader Election cho Scheduler

  • Mục tiêu: Đảm bảo tính đúng đắn khi chạy nhiều Scheduler instance.

  • Lý thuyết: Ôn lại thiết kế Ngày 701.

  • Thực hành: Cài đặt Scheduler dùng etcd distributed lock để bầu leader, verify chỉ 1 instance active khi chạy 3 instance cùng lúc.

Ngày 709: Implement Job Assignment Logic

  • Mục tiêu: Scheduler thực sự phân phối job thông minh.

  • Lý thuyết: Ôn lại thuật toán Ngày 702.

  • Thực hành: Cài đặt logic Scheduler (leader) đọc Worker Registry, chọn worker ít tải nhất, gán job.

Ngày 710: Implement Job State Tracking

  • Mục tiêu: Theo dõi trạng thái toàn bộ job trong hệ thống.

  • Lý thuyết: Ôn lại State pattern (Giai đoạn 3) áp dụng cho trạng thái job.

  • Thực hành: Cài đặt Job State Store (VD: dùng database từ Giai đoạn 11), cập nhật trạng thái Pending → Running → Completed/Failed theo đúng luồng.

Ngày 711: Implement Retry cho Job thất bại

  • Mục tiêu: Áp dụng Resilience Pattern đã học.

  • Lý thuyết: Ôn lại Exponential Backoff (Ngày 689).

  • Thực hành: Thêm cơ chế retry cho job thất bại, giới hạn số lần retry, backoff tăng dần giữa các lần.

Ngày 712: Implement Circuit Breaker cho External Call

  • Mục tiêu: Bảo vệ hệ thống khỏi dependency ngoài bị lỗi.

  • Lý thuyết: Ôn lại Circuit Breaker (Ngày 690).

  • Thực hành: Nếu job có gọi ra external service (giả lập), bọc lời gọi đó bằng Circuit Breaker.

Ngày 713: Implement Idempotency cho Job Execution

  • Mục tiêu: Đảm bảo an toàn khi job bị xử lý trùng (do Retry hoặc do reassign khi worker "chết nhầm").

  • Lý thuyết: Ôn lại Idempotency Key (Giai đoạn 9, Ngày 692).

  • Thực hành: Thêm idempotency key cho mỗi job, đảm bảo xử lý trùng job cùng key không gây tác dụng phụ kép.

Ngày 714: Implement Timeout cho Job chạy quá lâu

  • Mục tiêu: Tránh job "treo" vô thời hạn.

  • Lý thuyết: Ôn lại nguyên tắc thiết kế Timeout (Ngày 693).

  • Thực hành: Thêm timeout cho mỗi job, nếu vượt quá thời gian cho phép, coi như thất bại và trigger retry/reassign.

Ngày 715: Implement Dead Letter Queue

  • Mục tiêu: Xử lý job liên tục thất bại mà không làm nghẽn hệ thống.

  • Lý thuyết: Ôn lại Dead Letter Queue (Ngày 662).

  • Thực hành: Sau N lần retry thất bại, chuyển job vào Dead Letter Queue để xem xét thủ công thay vì retry vô hạn.

Ngày 716: Test - Worker chết giữa chừng

  • Mục tiêu: Verify Fault Tolerance hoạt động đúng.

  • Lý thuyết: Ôn lại thiết kế Ngày 703.

  • Thực hành: Viết test/kịch bản: kill 1 worker process khi đang xử lý job, verify Scheduler phát hiện (qua mất heartbeat) và reassign job cho worker khác.

Ngày 717: Test - Scheduler chết giữa chừng

  • Mục tiêu: Verify Leader Election/Failover hoạt động đúng.

  • Lý thuyết: Ôn lại thiết kế Ngày 701, 708.

  • Thực hành: Kill Scheduler instance đang là leader, verify 1 trong các instance standby tự động trở thành leader mới và tiếp tục phân phối job.

Ngày 718: Test - Message Broker mất kết nối tạm thời

  • Mục tiêu: Verify hệ thống chịu được lỗi hạ tầng, không chỉ lỗi ở tầng application.

  • Lý thuyết: Ôn lại Retry Pattern áp dụng cho kết nối tới hạ tầng (không chỉ giữa các service).

  • Thực hành: Giả lập RabbitMQ ngừng hoạt động tạm thời, verify Producer/Consumer tự động reconnect khi broker phục hồi, không mất job.

Ngày 719: Benchmark Throughput

  • Mục tiêu: Đánh giá hiệu năng hệ thống hoàn chỉnh.

  • Lý thuyết: Ôn lại benchmark methodology đã áp dụng nhiều lần.

  • Thực hành: Đo throughput (job/giây) với số lượng worker khác nhau (1, 3, 5 worker), vẽ biểu đồ khả năng scale ngang.

Ngày 720: Review Kiến trúc Tổng thể

  • Mục tiêu: Đánh giá lại toàn bộ hệ thống đã xây.

  • Lý thuyết: Ôn lại toàn bộ pattern đã dùng: Service Discovery, Consistent Hashing (nếu có dùng cho sharding worker), Message Queue, Consensus (etcd), Resilience Patterns.

  • Thực hành: Viết review: hệ thống có single point of failure nào còn sót lại không, mức consistency ở mỗi thành phần có đúng như thiết kế Ngày 704 không.

Ngày 721: Retrospective Giai đoạn 12

  • Mục tiêu: Tổng kết toàn bộ Giai đoạn Distributed Systems.

  • Lý thuyết: Nhìn lại hành trình: Communication → Messaging → Consistency → Consensus → Resilience Patterns → Distributed Job System - đây là những kiến thức khó nhất và cũng thực dụng nhất cho vai trò Platform/Framework Engineer.

  • Thực hành: Viết báo cáo retrospective toàn diện, liên hệ ngược Distributed Job System với Concurrent Task Scheduler (Giai đoạn 5) - chỉ ra rõ ràng những vấn đề mới xuất hiện khi chuyển từ đa luồng (1 máy) sang đa node (nhiều máy, network không đáng tin cậy).


Giai đoạn 13 - DevOps/Infra & Observability (Ngày 722–763)

Giai đoạn mới bổ sung. Đây chính là mảng bạn đã ngầm giả định cần thiết khi đưa ra ví dụ "Dockerfile Best Practice" - kiến thức bắt buộc để đưa mọi thứ đã xây từ đầu roadmap lên production thật.

Nhóm 1: Giới thiệu (Ngày 722–723)

Ngày 722: Giới thiệu DevOps & Infra

  • Mục tiêu: Hiểu vì sao Architect/Framework Engineer cần biết cả mảng vận hành, không chỉ thiết kế code.

  • Lý thuyết: Kiến trúc tốt trên giấy nhưng không deploy/vận hành được thì vô giá trị - 3-service project (Giai đoạn 8/12) hiện vẫn chỉ chạy local, cần đưa lên môi trường thật.

  • Thực hành: Liệt kê những gì đang thiếu để 3-service project chạy được ở production thật (container hoá, orchestration, CI/CD, monitoring).

Ngày 723: 12-Factor App

  • Mục tiêu: Học bộ nguyên tắc kinh điển cho ứng dụng cloud-native.

  • Lý thuyết: 12 nguyên tắc (codebase, dependencies tường minh, config qua env - liên hệ lại Secrets Management Giai đoạn 9, stateless process, port binding, disposability...) định hình cách thiết kế app dễ deploy/scale trên hạ tầng hiện đại.

  • Thực hành: Đối chiếu 3-service project với 12-Factor, đánh dấu nguyên tắc nào đã tuân thủ, nguyên tắc nào chưa (VD: config có đang hardcode không).

Nhóm 2: Docker (Ngày 724–731)

Ngày 724: Container là gì

  • Mục tiêu: Hiểu container khác Virtual Machine như thế nào ở tầng OS.

  • Lý thuyết: Container dùng chung kernel với host, cô lập bằng Linux namespace (process, network, filesystem) và giới hạn tài nguyên bằng cgroup - liên hệ lại Process/Thread và Virtual Memory đã học Giai đoạn 0.

  • Thực hành: Lập bảng so sánh Container vs VM theo tiêu chí: thời gian khởi động, overhead tài nguyên, mức độ cô lập.

Ngày 725: Docker Image - Layer & Union File System

  • Mục tiêu: Hiểu cách Docker lưu trữ image hiệu quả.

  • Lý thuyết: Mỗi lệnh trong Dockerfile tạo 1 layer, các layer xếp chồng qua Union File System - layer giống nhau giữa nhiều image được chia sẻ, tiết kiệm dung lượng.

  • Thực hành: Build 2 image từ 2 Dockerfile gần giống nhau, dùng docker history xem layer nào được tái sử dụng.

Ngày 726: Dockerfile cơ bản

  • Mục tiêu: Thành thạo cú pháp Dockerfile.

  • Lý thuyết: FROM (base image), RUN (chạy lệnh lúc build), COPY (chép file), CMD/ENTRYPOINT (lệnh chạy lúc container start).

  • Thực hành: Viết Dockerfile đầu tiên cho Order Service (Java/Spring Boot từ Giai đoạn 10), build và chạy thử.

Ngày 727: Dockerfile Best Practice

  • Mục tiêu: Viết Dockerfile nhỏ gọn, build nhanh.

  • Lý thuyết: Order layer theo tần suất thay đổi (COPY dependency manifest trước, code sau - tận dụng cache), .dockerignore loại bỏ file không cần thiết khỏi build context.

  • Thực hành: Tối ưu lại Dockerfile Ngày 726, đo dung lượng image và thời gian build trước/sau khi áp dụng best practice.

Ngày 728: Multi-stage Build

  • Mục tiêu: Giảm kích thước image production xuống mức tối thiểu.

  • Lý thuyết: Multi-stage build dùng 1 stage để build (có đầy đủ compiler/toolchain nặng), stage cuối chỉ copy artifact cần thiết sang base image nhẹ - image production không chứa công cụ build thừa.

  • Thực hành: Viết multi-stage Dockerfile cho Payment Service (C++ từ Giai đoạn 10, cần compile), so sánh dung lượng image trước/sau.

Ngày 729: Docker Compose

  • Mục tiêu: Chạy nhiều container phối hợp trên máy dev.

  • Lý thuyết: docker-compose.yml định nghĩa nhiều service, network, volume - 1 lệnh khởi động toàn bộ stack thay vì chạy từng container thủ công.

  • Thực hành: Viết docker-compose.yml chạy cùng lúc Order Service, Payment Service, PostgreSQL, RabbitMQ.

Ngày 730: Lab - Dockerize 3-Service Project

  • Mục tiêu: Container hoá toàn bộ project chính đã xây từ Giai đoạn 8-12.

  • Lý thuyết: Ôn lại toàn bộ tuần này.

  • Thực hành: Viết Dockerfile tối ưu cho cả 3 service (Order/Payment/Inventory) + Docker Compose chạy toàn bộ hệ thống (bao gồm database, message broker, etcd) chỉ bằng docker-compose up.

Ngày 731: Review Docker

  • Mục tiêu: Củng cố nhóm Docker.

  • Lý thuyết: Tổng hợp: Container vs VM, Image/Layer, Dockerfile Best Practice, Multi-stage build, Compose.

  • Thực hành: Viết checklist Dockerfile review (VD: có multi-stage chưa, có .dockerignore chưa, có chạy bằng non-root user chưa).

Nhóm 3: Kubernetes (Ngày 732–743)

Ngày 732: Kubernetes - Giới thiệu

  • Mục tiêu: Hiểu vấn đề orchestration mà Kubernetes giải quyết.

  • Lý thuyết: Chạy 1 container thủ công thì dễ, nhưng chạy hàng chục container, tự phục hồi khi container chết, scale theo tải, cập nhật không downtime - cần 1 hệ thống orchestration.

  • Thực hành: Liệt kê 3 vấn đề vận hành 3-service project gặp phải nếu chỉ chạy bằng Docker Compose ở production thật (không tự phục hồi, không scale tự động, không rolling update).

Ngày 733: Pod

  • Mục tiêu: Hiểu đơn vị deploy cơ bản nhất của Kubernetes.

  • Lý thuyết: Pod là nhóm 1 hoặc nhiều container luôn được lên lịch cùng nhau, chia sẻ network namespace - thường 1 Pod = 1 container ứng dụng (đôi khi thêm sidecar, liên hệ Envoy Giai đoạn 10).

  • Thực hành: Viết Pod manifest YAML đơn giản cho Order Service, apply vào cluster local (minikube/kind), verify Pod chạy bằng kubectl get pods.

Ngày 734: Deployment

  • Mục tiêu: Học cách quản lý nhiều replica và cập nhật version.

  • Lý thuyết: Deployment quản lý ReplicaSet (đảm bảo đủ N Pod chạy), hỗ trợ Rolling Update (cập nhật dần từng Pod, không downtime).

  • Thực hành: Viết Deployment cho Order Service với 3 replica, thử update image version, quan sát Rolling Update diễn ra qua kubectl rollout status.

Ngày 735: Service - Networking giữa Pod

  • Mục tiêu: Liên hệ lại Service Discovery đã học Giai đoạn 12.

  • Lý thuyết: Kubernetes Service cung cấp 1 địa chỉ ổn định (DNS name) trỏ tới nhóm Pod luôn thay đổi (do restart/scale) - chính là Service Discovery được Kubernetes làm sẵn.

  • Thực hành: Viết Service cho Order Service, verify Payment Service có thể gọi Order Service qua DNS name nội bộ (order-service.default.svc.cluster.local) thay vì IP cụ thể.

Ngày 736: ConfigMap & Secret

  • Mục tiêu: Liên hệ lại Secrets Management đã học Giai đoạn 9.

  • Lý thuyết: ConfigMap lưu config không nhạy cảm, Secret lưu dữ liệu nhạy cảm (base64-encoded, không phải mã hoá thật - cần thêm công cụ như Vault cho bảo mật cao hơn) - cả 2 đều inject vào Pod qua env var hoặc mounted file.

  • Thực hành: Chuyển các biến môi trường đã thiết lập ở Giai đoạn 9 (Ngày 447) sang ConfigMap/Secret của Kubernetes.

Ngày 737: Ingress

  • Mục tiêu: Liên hệ lại API Gateway/Envoy đã học Giai đoạn 10-12.

  • Lý thuyết: Ingress định nghĩa cách traffic từ bên ngoài cluster được route vào đúng Service nội bộ - thường được implement bởi Ingress Controller (có thể chính là Envoy).

  • Thực hành: Viết Ingress route /orders tới Order Service, /payments tới Payment Service.

Ngày 738: Horizontal Pod Autoscaler

  • Mục tiêu: Học cách Kubernetes tự động scale theo tải.

  • Lý thuyết: HPA theo dõi metric (CPU, memory, hoặc custom metric) và tự động tăng/giảm số replica trong ngưỡng cho phép.

  • Thực hành: Cấu hình HPA cho Order Service scale từ 2-10 replica dựa trên CPU usage, giả lập tải cao và quan sát số replica tăng lên.

Ngày 739: Liveness & Readiness Probe

  • Mục tiêu: Học cách Kubernetes biết Pod có "khoẻ" không.

  • Lý thuyết: Liveness Probe (Pod có đang sống không, nếu fail thì restart Pod), Readiness Probe (Pod đã sẵn sàng nhận traffic chưa, nếu fail thì tạm loại khỏi Service) - liên hệ lại health check endpoint (Spring Boot Actuator, Giai đoạn 10).

  • Thực hành: Thêm Liveness/Readiness Probe cho Order Service trỏ tới endpoint /actuator/health đã có sẵn.

Ngày 740: StatefulSet

  • Mục tiêu: Học cách chạy ứng dụng cần persistent identity (khác Deployment vốn coi mọi Pod như nhau).

  • Lý thuyết: StatefulSet cho mỗi Pod 1 identity ổn định (tên, storage riêng) - cần thiết cho database/KV Store (liên hệ Mini KV Store Giai đoạn 11) khi chạy trên Kubernetes.

  • Thực hành: Vẽ sơ đồ giải thích vì sao PostgreSQL nên chạy bằng StatefulSet thay vì Deployment thông thường.

Ngày 741: Lab - Viết K8s Manifest cho 3-Service Project

  • Mục tiêu: Áp dụng toàn bộ tuần này vào project chính.

  • Lý thuyết: Ôn lại toàn bộ: Deployment, Service, ConfigMap/Secret, Ingress, Probe.

  • Thực hành: Viết đầy đủ manifest YAML cho cả 3 service + database + message broker.

Ngày 742: Lab - Deploy lên Cluster

  • Mục tiêu: Thực sự chạy được trên Kubernetes, không chỉ viết YAML.

  • Lý thuyết: Ôn lại kubectl apply, cách debug khi Pod không chạy (kubectl describe pod, kubectl logs).

  • Thực hành: Apply toàn bộ manifest lên cluster local (minikube/kind), verify toàn bộ 3-service project hoạt động đúng qua Ingress.

Ngày 743: Review Kubernetes

  • Mục tiêu: Củng cố nhóm Kubernetes.

  • Lý thuyết: Tổng hợp toàn bộ: Pod → Deployment → Service → ConfigMap/Secret → Ingress → HPA → Probe → StatefulSet.

  • Thực hành: Viết sơ đồ tổng thể kiến trúc Kubernetes cho 3-service project, chỉ rõ từng thành phần đóng vai trò gì.

Nhóm 4: CI/CD (Ngày 744–749)

Ngày 744: CI/CD - Giới thiệu

  • Mục tiêu: Phân biệt 2 khái niệm hay bị gộp chung.

  • Lý thuyết: Continuous Integration (tự động build + test mỗi khi có code mới), Continuous Deployment/Delivery (tự động deploy code đã qua CI lên môi trường tiếp theo).

  • Thực hành: Vẽ sơ đồ pipeline tổng quan: code push → CI (build, test) → CD (deploy tới staging/production).

Ngày 745: CI Pipeline

  • Mục tiêu: Hiểu các bước chuẩn của 1 CI pipeline.

  • Lý thuyết: Checkout code → build → chạy unit test (Giai đoạn 4) → chạy lint/static analysis → build Docker image.

  • Thực hành: Liệt kê đầy đủ các bước CI cần cho Order Service, tham chiếu lại Testing Strategy Playbook đã viết ở Giai đoạn 4.

Ngày 746: CD Pipeline - Deployment Strategy

  • Mục tiêu: Học các chiến lược deploy giảm thiểu rủi ro.

  • Lý thuyết: Rolling Update (đã gặp ở Kubernetes Deployment), Blue-Green (chạy song song 2 môi trường, chuyển traffic tức thì), Canary (chuyển dần % traffic sang version mới, theo dõi lỗi trước khi chuyển hết).

  • Thực hành: Lập bảng so sánh 3 chiến lược theo tiêu chí: tốc độ rollback, chi phí hạ tầng, độ phức tạp.

Ngày 747: GitHub Actions/GitLab CI

  • Mục tiêu: Làm quen công cụ CI/CD phổ biến thực tế.

  • Lý thuyết: Pipeline định nghĩa dạng YAML, chạy trên runner, trigger theo event (push, pull request).

  • Thực hành: Đọc cú pháp cơ bản GitHub Actions workflow file, xác định các thành phần chính (jobs, steps, triggers).

Ngày 748: Lab - Viết CI/CD Pipeline

  • Mục tiêu: Áp dụng thực tế vào 3-service project.

  • Lý thuyết: Ôn lại toàn bộ Ngày 744-747.

  • Thực hành: Viết GitHub Actions workflow: build + test tự động khi push code, build Docker image, (giả lập) deploy lên Kubernetes cluster khi merge vào nhánh main.

Ngày 749: Review CI/CD

  • Mục tiêu: Củng cố nhóm CI/CD.

  • Lý thuyết: Tổng hợp: CI (build/test tự động) → CD (deploy tự động) → Deployment Strategy giảm rủi ro.

  • Thực hành: Viết checklist: 1 pipeline CI/CD tốt cần đảm bảo những gì (test chạy trước khi build image, có thể rollback nhanh, không deploy khi test fail).

Nhóm 5: Infrastructure as Code (Ngày 750–755)

Ngày 750: Infrastructure as Code - Giới thiệu

  • Mục tiêu: Hiểu vấn đề IaC giải quyết.

  • Lý thuyết: Thay vì tạo hạ tầng (server, network, database) thủ công qua UI/console (dễ sai sót, không lặp lại được), định nghĩa hạ tầng bằng code - version control được, review được, tái tạo được.

  • Thực hành: Liệt kê hạ tầng cần thiết để chạy 3-service project ở production (Kubernetes cluster, database, message broker, network) - đây sẽ là scope cho IaC.

Ngày 751: Terraform - Khái niệm cơ bản

  • Mục tiêu: Làm quen công cụ IaC phổ biến nhất.

  • Lý thuyết: Provider (kết nối tới cloud provider cụ thể - AWS/GCP/Azure), Resource (1 thành phần hạ tầng cụ thể), State (Terraform lưu trạng thái hạ tầng hiện tại để biết cần thay đổi gì).

  • Thực hành: Đọc cú pháp HCL (HashiCorp Configuration Language) cơ bản, viết 1 resource đơn giản (VD: 1 file local để test không cần cloud thật).

Ngày 752: Terraform - Plan & Apply Workflow

  • Mục tiêu: Hiểu quy trình an toàn khi thay đổi hạ tầng.

  • Lý thuyết: terraform plan (xem trước thay đổi sẽ áp dụng, không thực thi), terraform apply (thực thi thay đổi) - tách biệt 2 bước giúp review trước khi thay đổi hạ tầng thật.

  • Thực hành: Chạy terraform plan cho 1 thay đổi nhỏ, đọc output để hiểu cách Terraform biểu diễn thay đổi (thêm/sửa/xoá).

Ngày 753: Terraform Module

  • Mục tiêu: Học cách tái sử dụng cấu hình hạ tầng.

  • Lý thuyết: Module đóng gói 1 nhóm resource thành đơn vị tái sử dụng (tương tự Function/Class trong lập trình) - dùng lại cho nhiều môi trường (dev/staging/production).

  • Thực hành: Thiết kế 1 module giả định kubernetes-cluster nhận tham số (số node, loại instance), có thể gọi lại cho nhiều môi trường khác nhau.

Ngày 754: Lab - Provision Hạ tầng cho 3-Service Project

  • Mục tiêu: Áp dụng thực tế (có thể dùng cloud free tier hoặc local provider để không tốn phí).

  • Lý thuyết: Ôn lại toàn bộ Ngày 750-753.

  • Thực hành: Viết Terraform config định nghĩa hạ tầng cần thiết cho 3-service project (network, cluster placeholder), chạy plan/apply để verify.

Ngày 755: Review IaC

  • Mục tiêu: Củng cố nhóm IaC.

  • Lý thuyết: Tổng hợp: vì sao IaC quan trọng (reproducibility, version control, review được), Terraform (Provider/Resource/State/Module).

  • Thực hành: Viết nhận xét: IaC giải quyết vấn đề gì mà Kubernetes manifest (Ngày 732-743) chưa giải quyết được (gợi ý: Kubernetes quản lý ứng dụng bên trong cluster, Terraform quản lý chính cluster đó và hạ tầng xung quanh).

Nhóm 6: Observability (Ngày 756–761)

Ngày 756: Observability - 3 Trụ cột

  • Mục tiêu: Có bức tranh tổng thể trước khi học từng loại.

  • Lý thuyết: Logs (sự kiện rời rạc, chi tiết), Metrics (số liệu tổng hợp theo thời gian, nhẹ, dễ query xu hướng), Traces (theo dõi 1 request xuyên qua nhiều service - liên hệ trực tiếp Distributed Systems Giai đoạn 12).

  • Thực hành: Với 1 lỗi giả định ("Order bị stuck ở trạng thái Pending"), xác định bạn sẽ cần loại observability nào để debug (có thể cần cả 3).

Ngày 757: Structured Logging

  • Mục tiêu: Học cách log hiệu quả cho hệ thống phân tán.

  • Lý thuyết: Structured Logging (log dạng JSON có field rõ ràng thay vì text tự do) - dễ dàng query/filter/aggregate, đặc biệt quan trọng khi log từ nhiều service cần gộp lại xem cùng nhau.

  • Thực hành: Sửa log hiện tại của 3-service project sang structured logging (JSON), đảm bảo mỗi log entry có service_name, trace_id (chuẩn bị cho Ngày 759), level, message.

Ngày 758: Metrics - Prometheus

  • Mục tiêu: Làm quen công cụ metrics phổ biến nhất trong hệ sinh thái cloud-native.

  • Lý thuyết: Counter (chỉ tăng, VD: tổng số request), Gauge (lên xuống tự do, VD: số connection hiện tại), Histogram (phân bố giá trị, VD: latency percentile) - Prometheus scrape metric định kỳ từ endpoint /metrics của mỗi service.

  • Thực hành: Expose endpoint /metrics cho Order Service (liên hệ Spring Boot Actuator, Giai đoạn 10), cấu hình Prometheus scrape metric đó.

Ngày 759: Distributed Tracing - OpenTelemetry

  • Mục tiêu: Liên hệ trực tiếp RPC/gRPC (Giai đoạn 9-10) và Service Communication (Giai đoạn 12).

  • Lý thuyết: Mỗi request được gán 1 trace_id xuyên suốt toàn bộ hành trình qua nhiều service (mỗi bước là 1 span) - OpenTelemetry là chuẩn phổ biến để instrument code tự động sinh trace.

  • Thực hành: Tích hợp OpenTelemetry SDK vào 3-service project, verify 1 request đi qua Order → Payment → Inventory tạo ra 1 trace hoàn chỉnh với đầy đủ span.

Ngày 760: SLI/SLO/Error Budget

  • Mục tiêu: Học cách định lượng "đủ tốt" cho 1 service, không chỉ theo dõi số liệu suông.

  • Lý thuyết: SLI (Service Level Indicator - số liệu đo được, VD: latency p99), SLO (Service Level Objective - mục tiêu cho SLI, VD: p99 < 200ms trong 99.9% thời gian), Error Budget (khoảng "được phép lỗi" trước khi vi phạm SLO, dùng để cân bằng giữa tốc độ release và độ ổn định).

  • Thực hành: Định nghĩa SLI/SLO cho Order Service (VD: availability, latency), tính Error Budget cho 1 tháng dựa trên SLO đã chọn.

Ngày 761: Lab - Tích hợp Observability đầy đủ

  • Mục tiêu: Hoàn thiện cả 3 trụ cột cho 3-service project.

  • Lý thuyết: Ôn lại toàn bộ tuần này.

  • Thực hành: Đảm bảo cả 3 service có: structured logging tập trung (VD: gửi về Elasticsearch/Loki), metrics qua Prometheus, tracing qua OpenTelemetry - kết nối trace_id giữa log và trace để có thể nhảy từ 1 dòng log lỗi sang toàn bộ trace liên quan.

Nhóm 7: Review (Ngày 762–763)

Ngày 762: Lab - Dashboard Giám sát Tổng thể

  • Mục tiêu: Có 1 cái nhìn tổng quan trực quan cho toàn hệ thống.

  • Lý thuyết: Grafana - công cụ visualize phổ biến nhất cho Prometheus metrics, kết hợp với log/trace viewer.

  • Thực hành: Xây 1 dashboard Grafana hiển thị: request rate, error rate, latency p50/p99 cho cả 3 service, cộng thêm trạng thái Circuit Breaker (Giai đoạn 12) nếu có expose metric.

Ngày 763: Retrospective Giai đoạn 13

  • Mục tiêu: Tổng kết toàn bộ Giai đoạn DevOps/Infra & Observability.

  • Lý thuyết: Nhìn lại hành trình: Docker → Kubernetes → CI/CD → IaC → Observability - đây chính là mảnh ghép cuối cùng để đưa mọi project đã xây từ đầu roadmap (Mini Web Framework, Payment Platform, 3-service project, Distributed Job System) lên production thật, vận hành được, quan sát được.

  • Thực hành: Viết báo cáo retrospective: liệt kê toàn bộ pipeline từ code tới production đã xây dựng được, xác định phần nào còn thiếu để thực sự sẵn sàng cho production (VD: alerting khi vi phạm SLO, disaster recovery plan).


Knowledge

Part 1 of 50