30 Ngày học Rust - Day 27: Xây dựng TCP Web Server Đa Luồng (Phần 3: The Thread Pool)
Day 27: Giải quyết vấn đề Nút cổ chai thảm hoạ của kiến trúc Single Thread. Đúc thủ công nhóm Máy băm Thread Pool để gánh hàng trăm ngàn Request cùng lúc.

Lời Tử Tế với Sự Bướng Bỉnh Của Lỗi Đồng Bộ Cứng (Synchronous)
Cuối bài Day 26, chúng ta có một Web API xịn. Nhược điểm chí tử? Cứ hễ có 1 khách vào truy cập hàm sleep(5_giay), TOÀN BỘ NHỮNG NGƯỜI KHÁCH CÒN LẠI đang truy cập web Đều phải đứng vòng cửa chực 5 giây mới vô được. Sự ứ đọng Đồng bộ này do bạn đang dùng 1 Thread (Luồng Xử Lý CPU duy nhất mang tên Main).
Ngây Thơ Bạn Đảo Khớp Viết Code Nhét Thread Bừa Trong Vòng For Socket Cho Mỗi Khách 1 Cái Thread: thread::spawn(|| { xu_ly_khach(stream) }); XÓA NGAY ÁP CHẾ NÀY. Nếu Bị tấn công DDOS có 100 ngàn khách đập tới, Core máy Bạn đẻ ra 100 Ngàn Cái Lõi Thread Đạp Crash Ram Nhồi Hết Pin Sập Ngây Máy Nguồn! Lệnh Chém Đầu Đuôi Mang Tính Cảnh Thức Ở Phức Kỹ Sư Cao Mạng Là: Nhóm Công Trình Giới Hạn Luồng (The Thread Pool).

1. Thiết Kế Mẫu Thread Pool Chặn Băng Cạnh
Thay vì liên tục Đẻ Sinh Con. Ta Gây Nên Một Giếng Lưu Trữ Gồm Cứng Ngắc 4 Worker Thợ Mỏ Từ Đầu Cột Điện (Khi App Khởi Tạo Cất Hàm). Hễ Có Lệnh Cục Xin Request Vô, Thợ 1 Cầm Làm. Lệnh 2 Tới, Thợ 2 Bợ Lấy. Tới Lệnh 5? Bốn Thợ Kẹt? Nó Xếp Hàng Móc Job Qua Kênh Channel Queue Đợi Mấy Gã Rảnh Ra Đỡ.
Khung Xương Mạch src/lib.rs (Bắt Đầu Tách Hãng Gói Lib):
pub struct ThreadPool {
cong_nhan: Vec<Worker>,
dau_gui: Option<mpsc::Sender<Job>>,
}
// Khái Niệm Job Nghĩa Lá 1 Box Cái Closure Mọi Cầm Gói Hàm!
type Job = Box<dyn FnOnce() + Send + 'static>; Gã Tà Đạo Khóc Đòi Giải Thích Job: Box bọc Khuôn Cho Lỗ Type, FnOnce Cứa Đợt Khớp Run Hàm Xong Bỏ Dọc, Send Ép Lệnh Bơm Luồng Xuyên Thread, ‘static Chứng Ký Lifetime Nghéo Vòng Không Dứt Lúc Khai Hàm Cốt.
2. Tạo Kiện Động Worker Nuốt Các Cục Nạp Nhám
Mỗi Worker Sẽ Rình Lấp Trong Cục Thread Của Nó. Đè Xoáy Ngang Tai Xem Ống Thu Receiver Nào Sủa Nôn Lệnh Từ App Tổng Xuống Mạch Hàm Phù Đổng. Đọc Lệnh Day 18 Liên Giao Channel!
struct Worker {
id: usize,
luong_xu_ly: Option<thread::JoinHandle<()>>,
}
impl Worker {
// Ép Bộ Arc Mutex Của Khớp Data Race Vòng Trọng! Cột Đầu Nhờ Giữ An Toàn Kẻ Nào Dốc Job Trước Thì Chiếm Lấy Mối Dây Receiver Cuộn Bảng Thép Nhanh Góc Nhìn Của Hắn
fn new(id: usize, thu_nhan: Arc<Mutex<mpsc::Receiver<Job>>>) -> Worker {
let l_xu_ly = thread::spawn(move || loop {
// Nằm Vạ Vuốt Rờ Lỗ Data Khớp. Có Nghẽn Khoá Nạp Phóng Nhíp Cú Recv. Lượm Thùng!
let m_lenh = thu_nhan.lock().unwrap().recv();
match m_lenh {
Ok(lenh_job) => {
println!("Tui Là Culi Mã Đích {id} đang Chiếc Job Kênh...");
lenh_job(); // Thả Đâm Lệnh Function!
}
Err(_) => {
println!("Ống Đòi Vỡ Rã Nhỉ, Culi Mạch {id} Đóng Treo!");
break;
}
}
});
Worker { id, luong_xu_ly: Some(l_xu_ly) }
}
}Ráp Chữ Đầu Vào Struct Thread Pool new(size) Cấu Vết Gốc Là Thong Dây mpsc::channel. Dãn Đầy Mảng Công Nhân Tạo Lỗ. Véo Xong Đốt 1 Trận Siêu Code Lừa Đảo Compiler!
Câu hỏi thường gặp (FAQ)
Ủa Tại Sao Phải Đút Quàng Cái Lệnh Kênh Giao Tiếp Receiver Vô Khớp Arc/Mutex Vậy Cha Nội?
Vì Chống Dãn Tà Thuật Cháy Chéo CPU Lệnh Race Nhau. Máy Bạn Có 4 Thread Thợ Song Song, Cả 4 Đều Kếch Vịn Tay Chung Nắm Bứt Đúng Ngay Chung 1 Cái Rổ Chặn Cuốn Dây Ống Cắm (Receiver Đầu Nhận). Không Bật Ổ Khóa Box Thép Từng Phiên Mutex Lượng, Quái Thread Vô Nhặt Sót Nhéo Đánh Nhau Tơi Tả. Bạn Hiểu Chức Năng Mutex/Arc Sâu Đậm Đỉnh Giáp Tại Lúc Này Đó Rứa À.
Sẵn sàng cho Ngày 28? Trận Cuồng Không Đè Dành Nhau Trơn Láng. 4 Lọng Channel Bơm Web Mòn Đẩy Cầu Socket Thoá Thoáng. Nhưng Đừng Quên, Nếu Bấm Nút Đóng App Thô Tụt Chẻ Giữa Dài Máy Chém Ctrl+C. Hệ Quả Web Bị Vứt Data Mưng Đứt Data Ngang Dòng Kéo. Hôm Nay Xứ Gọi Trật Tự Bấm Đỉnh Kéo Chặn Mạch Đỡ Đạn: [Day 28: Thiết Kế Web Graceful Shutdown Lớp Chào Mượt Trầm].
Chuỗi bài viết
30 Ngày Trở Thành Rustacean Tinh Hoa
Phần 27 / 30
- Phần 1 30 Ngày học Rust - Day 1: Lời chào thế giới và Vũ khí Cargo
- Phần 2 30 Ngày học Rust - Day 2: Biến, Bất biến (Mutability) và Shadowing
- Phần 3 30 Ngày học Rust - Day 3: Luồng điều khiển (Control Flow) và sức mạnh của Match
- Phần 4 30 Ngày học Rust - Day 4: Ownership - Khái niệm định hình cỗ thần khí Rust
- Phần 5 30 Ngày học Rust - Day 5: Khóa học nhặt đồ chung với References & Borrowing
- Phần 6 30 Ngày học Rust - Day 6: Đắp nặn dự án với Structs và Methods
- Phần 7 30 Ngày học Rust - Day 7: Quyền năng vô song của Enums và Pattern Matching
- Phần 8 30 Ngày học Rust - Day 8: Quản lý dự án với Packages, Crates và Modules
- Phần 9 30 Ngày học Rust - Day 9: Các bộ sưu tập chung (Vectors, Strings, Hash Maps)
- Phần 10 30 Ngày học Rust - Day 10: Trị dứt điểm Ác mộng Lỗi (Error Handling)
- Phần 11 30 Ngày học Rust - Day 11: Generics - Ma thuật Đa hình kiểu dữ liệu
- Phần 12 30 Ngày học Rust - Day 12: Traits - Kẻ ban phát quyền năng và Lập pháp Hành vi
- Phần 13 30 Ngày học Rust - Day 13: Vượt qua Boss cuối 'Lifetimes' - Sinh Mệnh Biến
- Phần 14 30 Ngày học Rust - Day 14: Tận diệt Bug từ trứng nước bằng Automated Tests
- Phần 15 30 Ngày học Rust - Day 15: Thực chiến Build Command Line App (CLI) đầu đời
- Phần 16 30 Ngày học Rust - Day 16: Functional Magic chốn trần gian (Closures & Iterators)
- Phần 17 30 Ngày học Rust - Day 17: Quyền năng của Smart Pointers
- Phần 18 30 Ngày học Rust - Day 18: Chinh phục Da luồng (Concurrency) - Cú đâm quyết định của Rust
- Phần 19 30 Ngày học Rust - Day 19: Tranh cãi Lập trình hướng đối tượng (OOP) trong Rust
- Phần 20 30 Ngày học Rust - Day 20: Mổ xẻ nghệ thuật Advanced Pattern Matching
- Phần 21 30 Ngày học Rust - Day 21: Sức mạnh tối thượng của Advanced Traits
- Phần 22 30 Ngày học Rust - Day 22: Về Phe Bóng Tối với Unsafe Rust
- Phần 23 30 Ngày học Rust - Day 23: Quyền năng của Đấng Tạo Hóa (Declarative Macros)
- Phần 24 30 Ngày học Rust - Day 24: Siêu Năng Lực Procedural Macros (Macro Thủ Tục)
- Phần 25 30 Ngày học Rust - Day 25: Xây dựng TCP Web Server Đa Luồng (Phần 1: Lõi Socket)
- Phần 26 30 Ngày học Rust - Day 26: Xây dựng TCP Web Server Đa Luồng (Phần 2: Bắn trả File HTML)
- Phần 27 30 Ngày học Rust - Day 27: Xây dựng TCP Web Server Đa Luồng (Phần 3: The Thread Pool)
- Phần 28 30 Ngày học Rust - Day 28: Xây dựng TCP Web Server Đa Luồng (Phần 4: Graceful Shutdown)
- Phần 29 30 Ngày học Rust - Day 29: Lên đỉnh Web Server Thực Chiến với Axum và Tokio
- Phần 30 30 Ngày học Rust - Day 30: Vượt Vọng Vàng - Đúc Kết Hành Trình Rustacean Tinh Hoa