Mô Phỏng Network Chaos Với tc và NetEm: Kiểm Thử Hệ Thống Phân Tán Dưới Độ Trễ, Mất Gói và Jitter

Networking tutorial - IT technology blog
Networking tutorial - IT technology blog

Bối Cảnh & Lý Do

Môi trường staging nội bộ thường vẽ nên một bức tranh hoàn hảo giả tạo. Các service phản hồi trong vòng 2 mili-giây, độ trễ replication gần như bằng không, và việc network timeout chỉ giống như lý thuyết xa vời. Nhưng khi bạn đưa hệ thống lên cụm cloud đa khu vực (multi-region), thực tế phũ phàng sẽ xuất hiện ngay lập tức.

Vào những đợt cao điểm, các đường truyền giữa các datacenter dễ bị nghẽn và làm rớt gói tin. Những đợt tăng vọt latency đột ngột sẽ kích hoạt chuỗi timeout dây chuyền. Cụm Raft hoảng loạn rồi liên tục rơi vào các vòng bầu leader bất tận, trong khi thread pool cạn kiệt vì phải chờ đợi các downstream service không hồi đáp. Nếu chỉ test trên mạng loopback nội bộ lý tưởng, các cơ chế circuit breaker và retry policy của bạn thực chất chỉ là những lý thuyết chưa được kiểm chứng, chực chờ đổ vỡ vào lúc 3 giờ sáng.

Thay vì ngồi chờ một AWS transit gateway gặp trục trặc ngay trong dịp Black Friday, bạn hoàn toàn có thể chủ động bơm chaos có kiểm soát ngay ở tầng nhân Linux. Kết hợp tc (Traffic Control) với cơ chế hàng đợi netem (Network Emulator) cho phép bạn tùy chỉnh đường truyền chập chờn, mất gói (packet loss) và biến thiên độ trễ (jitter) theo ý muốn bất cứ lúc nào.

Cài Đặt

Linux đã tích hợp sẵn tính năng kiểm soát lưu lượng mạng ngay trong kernel. Bạn có thể quản trị thông qua lệnh tc, vốn đi kèm trong gói chuẩn iproute2 có mặt trên hầu hết các bản phân phối hiện đại.

Trên Debian, Ubuntu hoặc các bản phân phối phái sinh:

sudo apt-get update
sudo apt-get install -y iproute2

Trên RHEL, Rocky Linux hoặc Fedora:

sudo dnf install -y iproute

Tiếp theo, hãy đảm bảo kernel module sch_netem đã được nạp vào bộ nhớ:

sudo modprobe sch_netem
lsmod | grep sch_netem

Trước khi can thiệp vào bất kỳ routing rule nào, hãy tìm tên interface mục tiêu bằng lệnh ip -br link. Hãy tìm các network adapter vật lý như eth0 hoặc ens3, hoặc các bridge interface của container như docker0 và cni0.

Cấu Hình

Traffic control gắn các cơ chế hàng đợi (qdisc – queuing discipline) vào lưu lượng egress đi ra ngoài. Hãy nhớ rằng: NetEm chỉ định hình các gói tin đi ra (outgoing packets) trên interface được chỉ định. Nếu muốn mô phỏng latency trên các request đi vào (incoming requests), bạn cần áp dụng các rule này ở phía client hoặc định tuyến lưu lượng qua một gateway interface trung gian.

1. Thiết Lập Độ Trễ Cố Định và Biến Thiên (Jitter)

Mô phỏng độ trễ round-trip xuyên lục địa giữa các microservice bằng cách thêm một qdisc netem với mức delay cơ sở tùy ý. Để thêm 100ms độ trễ, hãy chạy:

sudo tc qdisc add dev eth0 root netem delay 100ms

Các kết nối mạng trong thực tế hiếm khi duy trì ổn định ở một con số mili-giây chính xác tuyệt đối. Jitter sẽ tạo ra sự biến thiên và độ tương quan giữa các gói tin. Chẳng hạn, để thiết lập mức delay trung bình 100ms với biên độ dao động đều ±20ms, trong đó độ trễ của mỗi gói tin có 25% tương quan với gói trước đó:

sudo tc qdisc change dev eth0 root netem delay 100ms 20ms 25%

Lưu lượng Internet thực tế thường tuân theo phân phối hình chuông hơn là một dải đồng đều phẳng. Để mô phỏng lưu lượng WAN chính xác hơn, hãy áp dụng phân phối chuẩn (Gaussian):

sudo tc qdisc change dev eth0 root netem delay 100ms 20ms distribution normal

2. Mô Phỏng Mất Gói (Packet Loss) và Lỗi Dữ Liệu (Corruption)

Các switch top-of-rack bị quá tải hay các kết nối không dây nhiều nhiễu thường xuyên làm rơi frame. Để buộc kernel ngẫu nhiên làm rớt 5% số frame đi ra ngoài:

sudo tc qdisc change dev eth0 root netem loss 5%

Tình trạng rớt gói tin thường xảy ra theo từng đợt (burst) khi bộ đệm của router bị tràn. Bạn có thể mô hình hóa hiện tượng này bằng cách thêm tỷ lệ tương quan. Mức tương quan 50% đồng nghĩa với việc nếu một gói tin bị rớt, khả năng gói tin tiếp theo cũng bị rớt sẽ tăng gấp đôi:

sudo tc qdisc change dev eth0 root netem loss 5% 50%

Card mạng hỏng hoặc dây cáp kém chất lượng cũng có thể làm đảo bit (flip bit) hoặc trùng lặp frame. Những trường hợp biên (edge case) này thường phơi bày các bug ngầm trong những custom binary protocol hoặc logic de-serialization:

# Làm hỏng ngẫu nhiên 0.2% gói tin bằng cách đảo các bit đơn lẻ
sudo tc qdisc change dev eth0 root netem corrupt 0.2%

# Trùng lặp 1% số gói tin gửi đi
sudo tc qdisc change dev eth0 root netem duplicate 1%

3. Kết Hợp Nhiều Tác Vụ Gây Lỗi

Sự cố thực tế rất phức tạp. Một kết nối mạng di động chập chờn hay đường hầm VPN bị nghẽn thường gặp phải tình trạng trễ, jitter và rớt gói tin cùng một lúc. Rất may là NetEm cho phép bạn kết hợp các tham số này lại với nhau trong một rule duy nhất:

sudo tc qdisc change dev eth0 root netem delay 150ms 30ms loss 3% duplicate 1%

Chỉ một câu lệnh này đã tái hiện lại toàn bộ môi trường mạng di động khắc nghiệt. Đây là bài test tải lý tưởng để xác minh xem gRPC deadline, Redis connection pool và cơ chế Kafka retry backoff có hoạt động trơn tru hay không, tránh việc làm quá tải các downstream worker bằng những đợt retry storm dồn dập.

4. Dọn Dẹp và Khôi Phục Trạng Thái Ban Đầu

Luôn nhớ xóa bỏ các thiết lập chaos sau khi hoàn tất quá trình kiểm thử. Thao tác xóa root qdisc sẽ lập tức khôi phục interface về lại cơ chế hàng đợi mặc định của kernel (thường là fq_codel hoặc pfifo_fast):

sudo tc qdisc del dev eth0 root

Xác Minh & Giám Sát

Đừng bao giờ mặc định rằng các rule chaos đang hoạt động hiệu quả. Hãy luôn kiểm tra hành vi ở cả tầng kernel Linux lẫn tầng network client.

Kiểm Tra Các Rule Đã Cấu Hình

Truy vấn interface để kiểm tra các rule hàng đợi đang hoạt động và xác nhận các tham số của bạn đã được nạp chính xác:

tc qdisc show dev eth0

Bạn sẽ thấy kết quả hiển thị tương tự như sau:

qdisc netem 8001: root refcnt 2 limit 1000 delay 100ms loss 5%

Kiểm Thử Bằng Lệnh Ping

Từ một node đồng cấp hoặc client test nhắm đến host, hãy gửi 20 gói tin ICMP echo để kiểm chứng mức delay và tỷ lệ rớt gói đã áp dụng:

ping -c 20 192.168.1.50

Xem xét phần tóm tắt thống kê ở cuối kết quả chạy ping:

20 packets transmitted, 19 received, 5% packet loss, time 19024ms
rtt min/avg/max/mdev = 99.842/101.314/104.120/1.240 ms

Bảng tóm tắt của ping phản ánh chính xác mức round-trip delay 100ms đã cấu hình và ghi nhận đúng 5% packet loss có chủ đích.

Giám Sát Thống Kê Interface Trực Tiếp

Theo dõi các bộ đếm rớt gói và thông lượng theo thời gian thực trong khi chạy các bài load test ở tầng ứng dụng:

tc -s qdisc show dev eth0

Hãy chú ý đến các bộ đếm dropped và overlimits. Khi ứng dụng của bạn bắt đầu đẩy traffic, các con số này sẽ tăng dần lên, xác nhận rằng NetEm đang chủ động chặn và loại bỏ các frame.

Việc tích hợp các bước kiểm thử tc netem nhẹ nhàng này vào quy trình CI staging tự động sẽ giúp bạn phát hiện sớm các lỗi timeout lỏng lẻo và rò rỉ kết nối nghiêm trọng từ trước khi chúng kịp biến thành sự cố Sev-1 trên môi trường production.

Share: