Nội dung bài viết
Hi các bạn 👋. Mình là Hùng Anh.
Trong quá trình làm việc, hẳn có lúc bạn từng đọc các bản vẽ C4 model trong tài liệu SAD (Software Architecture Document) của các anh Solution Architect. Nhưng bạn đã thực sự hiểu từng loại diagram ở đó mang ý nghĩa gì, và được dùng trong tình huống nào chưa? Nếu ngay bây giờ được giao vẽ sơ đồ kiến trúc cho 1 hệ thống, liệu bạn có làm được không?
Bài này mình và bạn sẽ cùng tìm hiểu C4 model — chuẩn vẽ kiến trúc phổ biến nhất hiện nay — để lần tới gặp những bản vẽ đó, bạn không chỉ đọc hiểu mà còn tự vẽ được.
Bắt đầu thôi.
1. Vấn Đề Của Những Diagram Không Theo Chuẩn
Hình dưới đây có lẽ bạn đã gặp nhiều lần:

Có 3 vấn đề dễ nhận ra:
- Lẫn lộn tầng trừu tượng. "Users" là con người, "OrderServiceImpl" là 1 class Java, "K8s cluster" là hạ tầng — 3 thứ ở 3 tầng trừu tượng khác nhau lại đứng cạnh nhau trong cùng 1 hình.
- Ký hiệu tự chế. Mũi tên từ "API" sang "Auth" nghĩa là gọi sang, phụ thuộc, hay deploy lên? Box hình mây và box hình trụ khác nhau ở điểm nào? Không có chú thích, mỗi người đọc sẽ tự diễn giải 1 kiểu.
- 1 hình phục vụ mọi đối tượng. CTO muốn nhìn tổng quan, dev mới cần chi tiết, SRE quan tâm hạ tầng. Gộp tất cả vào 1 hình thì cuối cùng không nhóm nào dùng được.
2. C4 Model
C4 model do Simon Brown tạo ra, dựa trên 1 ý tưởng rất quen thuộc: các mức zoom của bản đồ. Cùng 1 vùng đất, Google Maps lúc cho bạn nhìn cả đất nước, lúc là 1 thành phố, lúc lại là từng con phố — zoom đến đâu, hiện chi tiết đến đó.
C4 áp dụng đúng cách tiếp cận này cho phần mềm, với 4 mức zoom: Context, Containers, Components, Code. Kèm theo 1 nguyên tắc: thống nhất khái niệm trước, bàn về hình vẽ và màu sắc sau.
2.1. Các Khái Niệm Cốt Lõi
1 software system gồm nhiều container; mỗi container chứa nhiều component; và component được hiện thực bằng code.
- Person — người dùng hệ thống: khách hàng, admin, operator.
- Software System — mức trừu tượng cao nhất: 1 thứ mang lại giá trị cho người dùng. Hệ thống bạn đang xây là 1 software system; cổng thanh toán mà nó gọi sang là 1 software system khác.
- Container — 1 đơn vị deploy được độc lập: backend API, SPA, mobile app, database. Cái gì có process riêng và lần deploy riêng, cái đó là container.
- Component — 1 nhóm chức năng bên trong container: service, controller, repository. Component không deploy riêng được — nó nằm trong process của container.
C4 ra đời trước Docker. Container trong C4 là bất cứ thứ gì chạy được, deploy được độc lập — 1 API Spring Boot là 1 container, bất kể bạn chạy nó trong Docker, trên VM hay trên bare metal.
2.2. Các Level Trong C4 Model
Để dễ hình dung, mình lấy ví dụ về thiết kế hệ thống rút gọn URL Shortly: user tạo short link, visitor bấm vào thì được redirect về URL gốc, còn đăng nhập đi qua 1 identity provider bên ngoài.
2.2.1. Level 1: System Context
Level 1 mô tả: hệ thống là gì, ai dùng, và nó nói chuyện với những hệ thống nào?
Không database, không cache, không chi tiết bên trong — cả hệ thống chỉ là 1 box duy nhất. Nhờ vậy ai cũng đọc được, kể cả người không làm kỹ thuật. Đây cũng là hình ít thay đổi nhất, và với bất kỳ hệ thống nào, đây nên là hình được vẽ đầu tiên.
2.2.2. Level 2: Container
Level 2 mô tả: hệ thống gồm những khối kỹ thuật lớn nào, chúng giao tiếp với nhau ra sao?
1 web dashboard, 1 API Spring Boot, PostgreSQL, và Redis. Cache có vai trò quan trọng ở đây: hệ thống rút gọn URL có tỉ lệ đọc rất cao — trung bình 1 link được tạo sẽ có khoảng 100 lượt redirect — nên phần lớn redirect cần được trả lời ngay từ cache thay vì chạm vào database. Chú ý: mỗi container đều được ghi rõ công nghệ, mỗi mũi tên đều có động từ và protocol.
Với đa số hệ thống, Context + Container là đủ tài liệu kiến trúc. Nếu hệ thống có vài chục microservice, đừng gộp tất cả vào 1 hình — hãy vẽ mỗi service 1 hình riêng cùng các service liên quan trực tiếp.
2.2.3. Level 3: Component
Level 3 mô tả: bên trong 1 container có gì?
Request tạo link đi vào Link Controller, lượt bấm short link đi vào Redirect Controller. Cả 2 đều gọi xuống Shortener Service — nơi sinh mã Base62 — phía dưới là repository và cache. Nếu bạn từng làm việc với Spring Boot, cấu trúc này tương ứng khá tự nhiên với các package ngoài cùng của project.
Component diagram chỉ nên vẽ ở những chỗ thật sự cần: mức này thay đổi liên tục nên cũng lỗi thời nhanh nhất. Nhiều team bỏ qua hẳn, hoặc dùng tool generate từ code.
2.2.4. Level 4: Code
Class diagram của từng component. Không cần vẽ tay — IDE có thể generate ngay khi cần, và ở mức này thì bản thân code mới là source of truth.
Ngoài ra C4 còn 3 loại diagram bổ trợ: System Landscape (tất cả hệ thống trong tổ chức), Dynamic (các phần tử phối hợp lúc runtime, có đánh số bước), và Deployment (container nào chạy trên hạ tầng nào).
2.3. Tóm Tắt
| Level | Trả lời câu gì | Ai đọc | Tần suất thay đổi |
|---|---|---|---|
| 1. Context | Hệ thống là gì, ai dùng? | Tất cả mọi người | Hiếm khi |
| 2. Container | Gồm những khối nào? | Dân kỹ thuật | Thỉnh thoảng |
| 3. Component | Trong container có gì? | Dev của container đó | Thường xuyên |
| 4. Code | Code viết thế nào? | Dev, khi cần | Liên tục |
Có thể thấy quy luật: càng zoom sâu, đối tượng đọc càng hẹp và hình càng nhanh lỗi thời. Vì vậy hiếm khi cần vẽ đủ cả 4 mức.
2.4. Những Lưu Ý Và Sai Lầm Cần Tránh Khi Vẽ C4 Model
C4 không quy định hình khối hay màu sắc cụ thể, nhưng 1 diagram chuyên nghiệp sẽ luôn có đủ:
- Title — loại diagram + phạm vi ("Container diagram for Shortly").
- Legend — mọi hình khối, màu sắc, kiểu đường kẻ đều cần được chú thích.
- Mỗi phần tử ghi rõ loại và trách nhiệm — gói gọn trong 1 câu.
- Ghi rõ công nghệ:
[Java, Spring Boot],[PostgreSQL]. - Mũi tên 1 chiều, có nhãn: động từ cụ thể + protocol. Hạn chế tối đa chữ "uses" chung chung.
Dưới đây là 1 vài lỗi phổ biến hay gặp khi vẽ C4 model:
- Tự chế thêm level không có trong chuẩn ("sub-component", "sub-container").
- Vẽ chi tiết bên trong những hệ thống không thuộc quyền quản lý của mình.
- Trộn nhiều mức zoom trong cùng 1 hình — ví dụ class nằm cạnh container, database table nằm cạnh software system.
- Nhồi nhét quá nhiều phần tử trong 1 hình.
Lưu ý thêm: C4 chỉ mô tả cấu trúc tĩnh — để mô tả luồng xử lý hay data model, bạn vẫn cần sequence hoặc ER diagram. Và với 1 team nhỏ chỉ có 1 service thì có thể chỉ cần 1 Context diagram cùng 1 README tốt là đủ. C4 phát huy giá trị khi có nhiều người cần hiểu chung 1 bức tranh về hệ thống.
3. Tổng Kết
- C4 chia 4 mức zoom: Context, Containers, Components, Code — mỗi mức trả lời 1 câu hỏi, cho 1 nhóm người đọc.
- Container trong C4 là thứ deploy độc lập được — không phải Docker container.
- Vẽ tốt Context + Container là đủ dùng. Component chỉ vẽ ở những chỗ xứng đáng; Code để IDE generate.
- Mỗi diagram cần: title, legend, phần tử ghi rõ loại, công nghệ, mũi tên 1 chiều có nhãn.
Lần tới khi được nhờ "vẽ kiến trúc hệ thống", hãy hỏi lại: vẽ ở mức zoom nào, và cho ai xem?
Hẹn gặp lại các bạn trong những bài viết tiếp theo. Happy reading! 🍵
References
- The C4 model for visualising software architecture
- The C4 Model for Software Architecture — Simon Brown, InfoQ
- The C4 Model – Misconceptions, Misuses & Mistakes — Simon Brown, GOTO 2024
- Structurizr DSL documentation
- C4-PlantUML
- What is the C4 model? — IcePanel
- Design a URL Shortener — AlgoMaster
Bài viết liên quan
Distributed Lock và Cách Triển Khai với Redis
Trong các hệ thống phân tán, việc đảm bảo tính nhất quán của dữ liệu (data consistency) và ngăn chặn tranh chấp tài nguyên (race condition) là một thách thức lớn, đặc biệt khi nhiều tiến trình hoặc service truy cập đồng thời vào các tài nguyên dùng chung. Distributed lock là giải pháp hiệu quả để xử lý vấn đề này. Bài viết này mình sẽ giúp bạn hiểu rõ distributed lock là gì, tại sao nó cần thiết, các phương pháp để thực hiện và cách triển khai nó với Redis nhé.
Message Broker
Bạn có bao giờ tự hỏi điều gì giúp các dịch vụ thanh toán, mạng xã hội hay giao hàng hoạt động mượt mà mỗi ngày? Bí mật nằm ở Message Broker – công cụ “kết nối vô hình” giúp thông tin truyền đi an toàn và hiệu quả giữa các hệ thống. Hãy cùng mình khám phá Message Broker là gì nhé!
CronJob & Cron Expressions
CronJob là một công cụ quan trọng giúp lập trình viên tự động hóa các tác vụ theo lịch trình định kỳ. Tuy nhiên, để thiết lập CronJob một cách chính xác, bạn cần nắm vững Cron Expression – biểu thức giúp xác định lịch trình cho các công việc tự động. Bài viết này sẽ giới thiệu về CronJob, cách xây dựng Cron Expression, và các công cụ hữu ích để tạo biểu thức cron một cách dễ dàng.
