Sổ tay Kiến trúc Phần mềm
07 Phần II · Phong cách Chương 11 & 12

Pipeline & Microkernel

Pipeline & Microkernel Architecture

Hai phong cách monolith nữa, cùng họ với Layered: đều đơn giản & rẻ. Pipeline = dòng chảy một chiều qua các bộ lọc; Microkernel = lõi tối thiểu cắm thêm plug-in. Khác Layered ở chỗ tổ chức code.

01 Hai phong cách monolith

Cả hai đều là một đơn vị triển khai (một "lượng tử"), chia điểm mạnh/yếu giống Layered: mạnh chi phí & đơn giản, yếu mở rộng, đàn hồi, chịu lỗi. Điểm phân biệt nằm ở cách tổ chức xử lý.

Pipeline

pipes & filters

Dữ liệu chảy một chiều qua chuỗi bộ lọc, mỗi bộ làm đúng một việc. Nền của ETL, EDI, shell |.

Microkernel

plug-in architecture

Một lõi tối thiểu + các plug-in độc lập cắm vào. Nền của Eclipse, trình duyệt, phần mềm thuế/bảo hiểm.

02 Pipeline: pipes & filters

Topology gồm pipe (ống) & filter (bộ lọc). Pipe là kênh giao tiếp — thường điểm-điểm & một chiều, payload nhỏ để chạy nhanh. Filter tự đóng gói, độc lập, thường stateless, mỗi cái chỉ làm một nhiệm vụ.

Producer source Transformer map Tester filter/reduce Consumer sink Dòng dữ liệu một chiều — pipe nối filter →
Tính một chiều + đơn giản khuyến khích tái dùng kiểu lắp ghép (compositional reuse) — đúng tinh thần lệnh shell nối bằng |.

Bốn loại filter

Producer

source · chỉ ra

Điểm bắt đầu, chỉ có đầu ra. Vd: subscribe một topic Kafka để nhận dữ liệu.

Transformer

map

Nhận vào, biến đổi dữ liệu, đẩy ra pipe sau. Như map trong lập trình hàm.

Tester

filter / reduce

Kiểm tra tiêu chí rồi tùy chọn tạo đầu ra/định tuyến. Như filter/reduce.

Consumer

sink

Điểm kết thúc: lưu DB hoặc hiển thị lên màn hình.

Dùng ở đâu: công cụ ETL, EDI, điều phối như Apache Camel, hay pipeline xử lý telemetry stream từ Kafka → MongoDB. Tác vụ phức hợp thì nối nhiều filter, đừng nhồi vào một filter.

Đánh giá đặc tính — Pipeline

Chi phí tổng thể Overall cost
Tính đơn giản Simplicity
Khả năng tiến hóa Evolutionary
Tính mô-đun Modularity
Khả năng triển khai Deployability
Độ tin cậy Reliability
Khả năng kiểm thử Testability
Hiệu suất Performance
Tính đàn hồi Elasticity
Khả năng mở rộng Scalability
Khả năng chịu lỗi Fault tolerance

03 Microkernel: core & plug-in

Còn gọi là plug-in architecture. Hai phần: core system (chức năng tối thiểu để chạy / "happy path") + các plug-in độc lập chứa xử lý chuyên biệt, hay thay đổi.

Core happy path Plug-in A Plug-in B Plug-in C Plug-in D Registry
Lõi dùng registry để biết có plug-in nào & gọi ra sao. Plug-in độc lập, không phụ thuộc lẫn nhau — thêm/bớt mà không đụng phần còn lại.

Core system

chức năng tối thiểu

Đường đi thông thường, ít/không logic tùy biến. Đẩy độ phức tạp (cyclomatic) ra plug-in → dễ mở rộng, bảo trì, test hơn.

Plug-in

point-to-point / REST / messaging

Cô lập code hay biến động. Nối qua gọi hàm (shared lib: JAR/DLL/Gem), hoặc REST/messaging để decoupling & scale tốt hơn. Compile-based hoặc runtime (OSGi, Jigsaw…).

Registry & Contract

đăng ký + hợp đồng

Registry: tên + hợp đồng dữ liệu + giao thức. Contract (XML/JSON/object) chuẩn hoá hành vi vào–ra giữa lõi & plug-in.

Phong cách "lưỡng cư" duy nhất: microkernel có thể vừa technical vừa domain partitioned — phần domain đến từ tương quan mạnh giữa cấu trúc plug-in & nghiệp vụ (vd cấu hình riêng mỗi khách/khu vực, hay sản phẩm nặng tùy biến như Jira, Eclipse). Ví dụ: xử lý bồi thường bảo hiểm (mỗi bang một plug-in luật), phần mềm thuế (mỗi biểu mẫu một plug-in).

Đánh giá đặc tính — Microkernel

Tính đơn giản Simplicity
Chi phí tổng thể Overall cost
Khả năng triển khai Deployability
Khả năng kiểm thử Testability
Hiệu suất Performance
Khả năng tiến hóa Evolutionary
Tính mô-đun Modularity
Khả năng mở rộng (tính năng) Extensibility
Độ tin cậy Reliability
Khả năng mở rộng (quy mô) Scalability
Tính đàn hồi Elasticity
Khả năng chịu lỗi Fault tolerance

04 Dựng RAG theo hai kiểu

Hệ "Hỏi–đáp tài liệu" soi rất rõ qua hai phong cách này — và may mắn là cả hai cùng xuất hiện tự nhiên trong một RAG.

Ingest = một Pipeline kinh điển

RAG  Luồng nạp tài liệu chính là pipes & filters: producer → các transformer/tester → consumer.

flowchart LR
  P["Load tài liệu"]:::prod --> T1["Chunk"]:::tr --> T2["Lọc rác / quá ngắn"]:::test --> T3["Embed"]:::tr --> C[("Lưu Vector Store")]:::cons
  classDef prod fill:#e7ddf2,stroke:#6a4ca8,color:#1c1a14;
  classDef tr fill:#ddd2ef,stroke:#6a4ca8,color:#1c1a14;
  classDef test fill:#f3e6c8,stroke:#9a6712,color:#1c1a14;
  classDef cons fill:#14233b,stroke:#14233b,color:#f3ede0;
            
Load = producer · Chunk/Embed = transformer (map) · Lọc rác = tester (filter) · Lưu = consumer. Mỗi filter stateless, làm đúng một việc, nối bằng pipe một chiều.
Python · filter nối nhau như shell pipe
# mỗi filter là một hàm thuần, stateless — ghép kiểu compositional
for doc in load(path):                 # Producer (source)
    for ch in chunk(doc):              # Transformer (map)
        if is_meaningful(ch):          # Tester (filter)
            store.add(embed(ch))       # Transformer → Consumer (sink)

Vendor LLM/Embedder = Plug-in của Microkernel

RAG  Để "tháng sau đổi sang model khác" (đặc tính extensibility/adaptability ở topic 03), đặt mỗi nhà cung cấp thành một plug-in sau hợp đồng chung; lõi RAG không cần biết bên trong:

Python · core + plug-in qua registry
class EmbedderPlugin(Protocol):        # CONTRACT chung
    def embed(self, text: str) -> list[float]: ...

REGISTRY = {                           # REGISTRY: tên → plug-in
    "openai":  OpenAIEmbedder(),
    "local":   LocalBGEEmbedder(),     # cắm/gỡ không đụng lõi
}
def get_embedder(name): return REGISTRY[name]   # core chỉ tra registry
Đổi vendor = thêm một plug-in + cập nhật registry; lõi (happy path) không đổi. Đúng tinh thần phần mềm thuế thêm "biểu mẫu mới".

05 Ghi nhớ nhanh

Pipeline = pipes & filters một chiều — 4 loại filter: Producer, Transformer (map), Tester (filter/reduce), Consumer. Filter stateless, làm một việc.

Microkernel = lõi tối thiểu + plug-in — đẩy phần hay-đổi ra plug-in độc lập; lõi tra registry, giao tiếp qua contract.

Đều mạnh chi phí & đơn giản, yếu mở rộng/đàn hồi/chịu lỗi — vì là monolith một lượng tử (giống Layered).

Microkernel là phong cách "lưỡng cư" — duy nhất vừa technical vừa domain partitioned; hợp sản phẩm nặng tùy biến (IDE, thuế, bảo hiểm).

RAG dùng cả hai: ingest là Pipeline; vendor LLM/Embedder là Plug-in sau một contract chung.

NguồnChương 11 (Pipeline Architecture Style) & Chương 12 (Microkernel Architecture Style), Fundamentals of Software Architecture — Mark Richards & Neal Ford, O'Reilly 2020.