Cuộc khủng hoảng lúc 2:14 sáng: Tại sao máy chủ của bạn bị nghẽn?
Lúc 2:14 sáng, điện thoại của tôi rung liên hồi không dứt. Các cảnh báo PagerDuty đổ dồn cứ mỗi ba giây. Đến khi tôi mở máy tính xách tay lên, bảng điều khiển cho thấy tỷ lệ thành công đã tụt dốc không phanh từ 99.9% xuống còn 42% đầy thất vọng (một kịch bản quen thuộc khi xử lý sự cố mạng lúc 2 giờ sáng). Nhìn qua thì tổng mức sử dụng CPU có vẻ ổn—khoảng 30%—nhưng thông lượng 1.2 Gbps của chúng tôi đã giảm xuống chỉ còn 200 Mbps ít ỏi.
Tôi đăng nhập vào terminal và chạy lệnh top. Trong khi hầu hết các nhân (core) đang rảnh rỗi, Core 0 lại đang “gào thét”. Cột si (software interrupt) bị nghẽn ở mức 100%. Tiến trình ksoftirqd/0 đang ngốn sạch mọi chu kỳ CPU khả dụng.
Đây chính là lúc hầu hết các máy chủ có lưu lượng truy cập cao gặp phải bức tường cản trở. Ứng dụng của bạn có thể tối ưu, nhưng hệ điều hành (OS) và Card mạng (NIC) đang bị ngập trong các gói tin, dẫn đến hiện tượng tương tự như tại sao website bị treo do lỗi cấu hình tầng mạng. Khi mỗi gói tin 1500 byte đều kích hoạt một interrupt CPU, kernel sẽ dành nhiều thời gian để chuyển ngữ cảnh (context switching) hơn là chạy mã nguồn của bạn. Trong môi trường production, làm chủ NIC offloading là sự khác biệt giữa việc mở rộng quy mô hiệu quả và việc đổ tiền vào phần cứng mà không giải quyết được vấn đề.
Nút thắt cổ chai: CPU đối đầu với Gói tin
Mỗi gói tin đến đều gửi tín hiệu đến CPU: “Tôi có dữ liệu!”. CPU tạm dừng tác vụ hiện tại, xử lý interrupt và xử lý header. Điều này vẫn ổn ở mức 1.000 gói tin mỗi giây. Nhưng ở mức 800.000 gói tin mỗi giây, CPU sẽ rơi vào tình trạng “bão interrupt” (interrupt storm). Nó đơn giản là không thể theo kịp. NIC Offloading và Interrupt Coalescing là những giải pháp thiết yếu. Các tính năng này chuyển gánh nặng xử lý từ phần mềm sang phần cứng ngay trên card mạng của bạn.
Thiết lập bộ công cụ
Bạn sẽ cần ethtool để tinh chỉnh các thiết lập này. Đây là công cụ tiêu chuẩn để giao tiếp với driver mạng. Hầu hết các bản phân phối (distro) đều có sẵn nó, nhưng bạn có thể cần phải cài đặt trên một hệ thống mới.
# Trên Debian/Ubuntu
sudo apt update && sudo apt install ethtool -y
# Trên RHEL/CentOS/AlmaLinux
sudo dnf install ethtool -y
Hãy luôn kiểm tra khả năng phần cứng hiện tại trước. Giả sử giao diện mạng chính của bạn là eth0, hãy chạy lệnh này:
# Liệt kê tất cả các tính năng offloading và trạng thái của chúng
ethtool -k eth0
Kiểm tra trạng thái của tcp-segmentation-offload và generic-receive-offload. Nếu chúng đang ở trạng thái off, bạn đã tìm thấy điểm cần tối ưu đầu tiên.
Cấu hình NIC Offloading để tăng thông lượng
Offloading chuyển việc xử lý gói tin vào chip xử lý riêng của NIC. Điều này cực kỳ hiệu quả đối với lưu lượng TCP, vốn là nền tảng của hầu hết các máy chủ web.
1. TCP Segmentation Offload (TSO) & Generic Segmentation Offload (GSO)
Thông thường, kernel chia các khối dữ liệu lớn thành các gói tin 1500 byte trước khi gửi. Với TSO, kernel chuyển trực tiếp một buffer lớn 64KB cho NIC. Phần cứng sẽ đảm nhận việc chia nhỏ. Điều này giúp CPU không phải tính toán hàng ngàn checksum và header riêng lẻ.
# Kích hoạt TSO và GSO
sudo ethtool -K eth0 tso on gso on
2. Generic Receive Offload (GRO)
Ở phía nhận dữ liệu, GRO là người bạn đồng hành tốt nhất. NIC sẽ thu thập một luồng các gói tin nhỏ đến và kết hợp chúng thành một “siêu gói tin” lớn trước khi kernel xử lý. Điều này làm giảm số lượng interrupt mà CPU phải xử lý lên đến 90%.
# Kích hoạt GRO
sudo ethtool -K eth0 gro on
Interrupt Coalescing: Làm dịu cơn bão
Offloading làm cho gói tin lớn hơn; coalescing làm cho interrupt ít đi. Thay vì “hét” vào CPU cho mỗi gói tin, chúng ta yêu cầu NIC đợi vài micro giây hoặc cho đến khi nó có một lô gói tin sẵn sàng.
Kiểm tra các thiết lập hiện tại bằng lệnh:
ethtool -c eth0
Tham số quan trọng là rx-usecs. Nếu nó được đặt là 0, NIC sẽ tạo interrupt cho mọi gói tin đơn lẻ. Điều đó tạo ra độ trễ tuyệt vời cho chơi game nhưng lại bóp nghẹt thông lượng của một máy chủ web. Tôi thường bắt đầu với độ trễ 30 micro giây.
# Đặt độ trễ interrupt RX thành 30 micro giây
sudo ethtool -C eth0 rx-usecs 30
Nhiều card mạng hiện đại hỗ trợ Adaptive Interrupt Coalescing. Đây là một tính năng thông minh tự động điều chỉnh độ trễ. Nó giữ độ trễ thấp trong thời gian rảnh và tăng kích thước lô xử lý khi lưu lượng truy cập tăng đột biến.
# Kích hoạt adaptive coalescing
sudo ethtool -C eth0 adaptive-rx on adaptive-tx on
Xác minh và giám sát kết quả
Áp dụng các thay đổi mới chỉ là bước khởi đầu. Bạn phải xác minh hiệu quả. Sau lần khắc phục lúc 2 giờ sáng, tôi đã theo dõi sát sao mức sử dụng CPU trên từng nhân kết hợp với các công cụ kiểm thử hiệu năng mạng Linux. Sử dụng mpstat để xem tải software interrupt đã giảm hay chưa:
# Giám sát thông số CPU mỗi giây
mpstat -P ALL 1
Cột %soft sẽ giảm đáng kể trên nhân đã bị nghẽn trước đó. Bạn cũng có thể theo dõi số lượng interrupt thực tế trong thời gian thực:
# Theo dõi số lượng interrupt của eth0
watch -n 1 "cat /proc/interrupts | grep eth0"
Nếu con số tăng chậm trong khi thông lượng vẫn duy trì ở mức cao, bạn đã thành công. Hãy nhớ rằng các thiết lập này thường bị reset sau khi khởi động lại. Hãy lưu chúng vĩnh viễn bằng cấu hình Netplan hoặc một đơn vị systemd đơn giản. Việc tăng tốc hiệu suất mạng Linux giúp giải phóng CPU để nó làm tốt nhất công việc của mình: phục vụ người dùng.

