← C4 Model: vẽ kiến trúc phần mềm

Bài 4 · Vận dụng · 22 phút

Level 2: Container

Biên soạn bởi Nguyễn Anh Tuấn

Sơ đồ container: web app, mobile app, API, database, message bus - mỗi container là một đơn vị chạy/triển khai riêng (KHÔNG phải Docker container).

bài trước, hệ thống của ta là một hộp duy nhất ở giữa Context. Giờ ta zoom vào trong chiếc hộp đó: sơ đồ Container cho thấy hệ thống được tạo từ những khối chạy được nào.

Đây là chiếc hộp Ngân Hàng Số ở bài trước mở ra - cùng một hệ thống, giờ thấy các container bên trong và công nghệ của từng cái:

Container - bên trong Ngân Hàng Số

[Người dùng]

Khách hàng

Giao dịch trực tuyến.

[Container: React]

Web App

Ngân hàng trên trình duyệt.

[Container: Swift / Kotlin]

Mobile App

App ngân hàng trên điện thoại.

[Container: Java / Spring]

API Application

Cung cấp API cho web & mobile.

[Container: Oracle]

Cơ sở dữ liệu

Lưu đăng nhập, nhật ký giao dịch.

[Container: RabbitMQ]

Hàng đợi tin

Xử lý giao dịch bất đồng bộ.

[Hệ thống ngoài]

Hệ thống lõi (Core Banking)

Tài khoản & giao dịch.

Dùng [HTTPS]Dùng [HTTPS]Gọi [JSON/HTTPS]Gọi [JSON/HTTPS]Đọc/ghi [SQL/TCP]Đẩy giao dịch [AMQP]Lấy số dư [XML/HTTPS]
  • Container là tầng zoom thứ hai: bên trong một Software System.
  • Đây là nơi CÔNG NGHỆ bắt đầu xuất hiện (mỗi container ghi rõ viết bằng gì).
  • Khán giả: đội kỹ thuật và vận hành (ops), không còn là người ngoài kỹ thuật.

Đây là khái niệm hay bị hiểu lầm nhất trong C4. Một containermột đơn vị chạy/triển khai được - một thứ phải đang chạy thì hệ thống mới hoạt động. Nó có từ trước Docker và nghĩa khác hẳn.

  • Ứng dụng: web app phía máy chủ, SPA (chạy trong trình duyệt), mobile app, desktop app, hàm serverless, console/script.
  • Kho dữ liệu (data store): cơ sở dữ liệu, file system, blob storage, cache như Redis.
  • Hạ tầng giao tiếp: message bus / hàng đợi tin (RabbitMQ, Kafka).
  • Tiêu chí chung: nó CHẠY/TRIỂN KHAI riêng được - không phải một mẩu code bên trong app.

Trung thực: container ≠ Docker container

Một cơ sở dữ liệu Oracle là một container trong C4 dù bạn không hề dùng Docker. Ngược lại, đóng gói một app bằng Docker không "biến" nó thành container C4 - nó vốn đã là container rồi. Hai chữ "container" này trùng tên nhưng khác khái niệm; đừng để Docker chiếm mất nghĩa gốc.

Khác với Context (cố tình giấu kỹ thuật), mức Container là chỗ phơi bày lựa chọn công nghệ. Mỗi hộp và mỗi mũi tên đều mang thêm thông tin:

  • Mỗi container ghi CÔNG NGHỆ: "Web App [React]", "API [Java/Spring]", "Cơ sở dữ liệu [Oracle]".
  • Mỗi quan hệ ghi GIAO THỨC: web gọi API qua [JSON/HTTPS]; API đọc CSDL qua [SQL/TCP]; đẩy việc qua [AMQP].
  • Nhờ vậy người đọc hiểu các khối GHÉP với nhau ra sao, không chỉ chúng là gì.

Vì sao điều này quan trọng

Một sơ đồ Container tốt là tài liệu kỹ thuật sống: người mới vào đội nhìn là biết hệ thống gồm những gì, viết bằng công nghệ nào, và dữ liệu chảy qua đâu - mà không phải đọc hết code.

Hãy mổ một hệ thống thật hơn. Trong widget, chọn Ngân Hàng Số rồi zoom vào mức Container (bấm hộp "Ngân Hàng Số" có dấu 🔍, hoặc chọn rồi bấm vào hệ thống ở mức Context):

🗺️ Bản đồ kiến trúc:

Nền tảng học online: học viên xem bài, làm quiz, theo dõi tiến độ.

Mức 1 Mức 2 Mức 3

Mức 1 - System Context

System Context - Lớp Học Trực Tuyến

Học viên
Mèo con học bài, làm quiz, xem tiến độ.
Giảng viên
Soạn bài giảng, chấm bài.
Cổng thanh toán ngoài
Thu học phí.
Dịch vụ Email ngoài
Gửi email thông báo.

Quan hệ (có nhãn & hướng)

  • Học viên Lớp Học Trực Tuyến : Học & làm bài [HTTPS]
  • Giảng viên Lớp Học Trực Tuyến : Soạn bài & chấm [HTTPS]
  • Lớp Học Trực Tuyến Cổng thanh toán : Thu học phí [API]
  • Lớp Học Trực Tuyến Dịch vụ Email : Gửi email [SMTP]
  • Web App và Mobile App là hai container giao diện, cùng gọi tới một API Application.
  • API nói chuyện với cơ sở dữ liệu (Oracle), hàng đợi tin (RabbitMQ) và hệ thống lõi bên ngoài.
  • Chỉ MỘT container (API) làm cầu nối với hệ thống lõi - các app không gọi thẳng, dễ kiểm soát hơn.
  • Mọi quan hệ đều ghi giao thức: [JSON/HTTPS], [SQL/TCP], [AMQP], [XML/HTTPS].

Cùng một sơ đồ Container phục vụ vài nhóm trong đội kỹ thuật:

  • Lập trình viên: biết có những app/dịch vụ nào, viết bằng gì, gọi nhau ra sao.
  • Vận hành (ops): biết cái gì cần được triển khai và chạy (app, CSDL, hàng đợi).
  • Quản lý dự án (PM): thấy các khối lớn để chia việc, ước lượng và quản lý rủi ro.
  • Người mới vào đội: nắm tổng thể kỹ thuật trong vài phút thay vì vài ngày đọc code.

Mẹo

Với phần lớn dự án, Context + Container là đã ĐỦ để giao tiếp. Đừng vội zoom sâu hơn nếu chưa có ai thực sự cần - vẽ thêm là thêm thứ phải bảo trì.
  • Hiểu "container" thành Docker - bỏ sót cơ sở dữ liệu, SPA, hàng đợi vốn cũng là container.
  • Quên ghi giao thức trên quan hệ - người đọc không biết các khối nói chuyện kiểu gì.
  • Nhồi component (chi tiết bên trong một container) vào đây - đó là việc của mức sau.
  • Quá nhiều container chen chúc - dấu hiệu nên tách hệ thống hoặc nhóm lại.

Bước tiếp theo

Khi một container đủ phức tạp để cần soi vào trong, ta zoom tiếp một mức: Level 3: Component - các nhóm chức năng bên trong một container.

Câu hỏi thường gặp

Không. Container trong C4 nghĩa là một đơn vị chạy/triển khai được - một web app, một API, một cơ sở dữ liệu, một file system. Khái niệm này có từ trước Docker. Một container C4 có thể được đóng gói bằng Docker, hoặc chạy trên máy chủ thường, hoặc là dịch vụ serverless - cách đóng gói không đổi việc nó là một container.

Đúng. Kho dữ liệu (data store) như PostgreSQL, Oracle, Redis là container trong C4, ngang hàng với các app. Lý do: nó là một thứ chạy riêng mà hệ thống cần để hoạt động.

Thường thì mỗi service triển khai độc lập là một container. Nhưng đừng máy móc "một container = một tiến trình". Tiêu chí là "đơn vị chạy/triển khai riêng" - một SPA chạy trong trình duyệt cũng là container dù nó không phải tiến trình phía máy chủ.

Thường từ vài đến khoảng chục. Nếu nhiều hơn nhiều, có thể hệ thống của bạn thực ra là nhiều hệ thống - cân nhắc tách ra, hoặc dùng sơ đồ bổ trợ. Một sơ đồ Container vẫn phải đọc được trong một lần nhìn.

Ở mức Container thì rất nên. Ghi rõ công nghệ trong mỗi hộp và giao thức trên mỗi quan hệ (JSON/HTTPS, SQL/TCP, AMQP...) giúp đội kỹ thuật và ops hiểu các khối ghép với nhau ra sao.

Tick những điều em tự tin làm được. Càng lên cao, em càng hiểu sâu.

Tick những điều em tự tin làm được sau khi học bài này. 0/6

Trả lời vài câu để chắc rằng em đã nắm bài.

Câu 1/3 Điểm: 0

Trong C4, "container" được định nghĩa chính xác nhất là gì?

  1. 1

    Liệt kê container

    Chọn một app mèo con đang dùng. Đoán các container của nó: có web app không, mobile không, API, cơ sở dữ liệu, hàng đợi tin...?

    Hoàn thành khi: Liệt kê ≥4 container; mỗi cái ghi một dòng vai trò ngắn.

  2. 2

    Container hay không?

    Phân loại: (a) một Docker image, (b) một class trong code, (c) một cơ sở dữ liệu MySQL, (d) một SPA chạy trên trình duyệt. Cái nào là container trong C4?

    Hoàn thành khi: Nhận ra (c) và (d) là container; (b) là code element; (a) là cách đóng gói, không phải khái niệm container C4.

  3. 3

    Gắn công nghệ & giao thức

    Lấy một sơ đồ container (hoặc dùng widget Bước 4). Với mỗi container ghi công nghệ phỏng đoán, với mỗi mũi tên ghi giao thức.

    Hoàn thành khi: Mọi container có công nghệ; mọi quan hệ có giao thức rõ ràng.

  4. 4

    Ngân hàng nói với hệ thống lõi

    Dùng widget Bước 4, chọn Ngân Hàng Số ở mức Container. Cho biết container nào nói chuyện với hệ thống lõi (Core Banking) và qua giao thức gì.

    Hoàn thành khi: Chỉ đúng container (API Application) và giao thức ([XML/HTTPS]); giải thích vì sao chỉ một container làm việc đó.

  5. 5

    Mô tả cho ops

    Dựa trên một sơ đồ Container, viết 2-3 câu mô tả "cái gì chạy ở đâu" như đang bàn giao cho đội vận hành (ops).

    Hoàn thành khi: Nêu được các đơn vị triển khai và chúng cần gì để chạy (CSDL, hàng đợi...).

  6. 6

    Khi nào nên tách hệ thống

    Viết một đoạn ngắn: nếu một sơ đồ Container có quá nhiều hộp, mèo con sẽ làm gì? Khi nào nên tách thành nhiều hệ thống?

    Hoàn thành khi: Nêu được dấu hiệu "quá nhiều container" và một hướng xử lý (nhóm lại hoặc tách hệ thống).