Quay lại danh sách
Cấu hình proxy để mô phỏng ISP throttling và kiểm tra độ bền của ứng dụng web

Cấu hình proxy để mô phỏng ISP throttling và kiểm tra độ bền của ứng dụng web

9 tháng 9, 2026

Giới thiệu

Trong quá trình phát triển ứng dụng web, équipe thường kiểm thử chức năng trong môi trường mạng lý tưởng – băng thông cao, độ trễ thấp và không mất gói. Tuy nhiên, trong thực tế, người dùng cuối thường kết nối qua các ISP có chính sách throttling (giới hạn tốc độ) tùy theo thời điểm, loại gói hoặc lượng dữ liệu đã sử dụng. Khi ứng dụng không được thiết kế để chịu đựng những giới hạn này, trải nghiệm người dùng sẽ giảm đáng kể: trang tải ch้า, gọi API bị timeout, hoặc thậm chí gây ra lỗi giao dịch.

Bài viết này tập trung vào cách mô phỏng ISP throttling bằng cách sử dụng proxy có khả năng giới hạn băng thông và độ trễ. Ta sẽ hướng dẫn cách thiết lập proxy local (có thể là một máy ảo hoặc container) sử dụng công cụ tc (traffic control) trên Linux kết hợp với mitmproxy hoặc tinyproxy để tạo ra các quy tắc throttling. Sau đó, minh họa cách tích hợp proxy vào các môi trường test phổ biến như Python requests, Node.js axios và cURL, đồng thời cung cấp một số mẹo để đo lường và phân tích kết quả.

1. Nguyên lý mô phỏng throttling qua proxy

Proxy không chỉ chuyển tiếp request/response mà còn có thể can thiệp vào lớp truyền輳. Khi chúng ta đặt giới hạn tốc độ trên kết nối TCP giữa client và proxy (hoặc giữa proxy và server), mọi dữ liệu qua đường đó sẽ bị hạn chế theo mức đã cấu hình. Các yếu tố thường được điều chỉnh:

  • Bandwidth limit (tốc độ tải xuống/tải lên, thường tính bằng kbps hoặc Mbps)
  • Latency (độ trễ một chiều, tính bằng ms)
  • Packet loss (tỷ lệ mất gói, tùy chọn)

Khi proxy được đặt giữa ứng dụng under test và máy chủ đích, mọi request sẽ trải qua lớp này, cho phép chúng ta mô phỏng các điều kiện mạng thực tế mà không cần thay đổi code ứng dụng.

2. Chuẩn bị môi trường

Ta sẽ sử dụng Docker để chạy một container proxy đơn giản dựa trên tinyproxy và thêm các quy tắc tc vào mạng container. Các bước sau giả định bạn đã cài đặt Docker và Docker Compose.

2.1. Dockerfile cho proxy

Tạo file Dockerfile.proxy:

FROM alpine:latest

# Cài đặt tinyproxy và iproute2 (cho tc)
RUN apk add --no-cache tinyproxy iproute2

# Cấu hình tinyproxy mặc định (lắng nghe trên 8888)
RUN echo "Port 8888" >> /etc/tinyproxy/tinyproxy.conf && \
    echo "Allow 0.0.0.0/0" >> /etc/tinyproxy/tinyproxy.conf

# Sao chép script khởi chạy
COPY entrypoint.sh /usr/local/bin/entrypoint.sh
RUN chmod +x /usr/local/bin/entrypoint.sh

ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]

2.2. Script entrypoint

Tạo entrypoint.sh:

#!/bin/sh
# Bắt đầu tinyproxy trong background
tinyproxy -d &
TX_PID=$!

# Đợi tinyproxy sẵn sàng
while ! nc -z localhost 8888; do
    sleep 0.1
 done

# Áp dụng quy tc vào giao diện mạng eth0 (mặc định của container)
# Ví dụ: giới hạn 500 kbps download, 500 kbps upload, thêm 100ms latency
tc qdisc add dev eth0 root handle 1: htb default 11
tc class add dev eth0 parent 1: classid 1:1 htb rate 1000kbps
tc class add dev eth0 parent 1:1 classid 1:10 htb rate 500kbps ceil 1000kbps
tc class add dev eth0 parent 1:1 classid 1:11 htb rate 500kbps ceil 1000kbps
tc qdisc add dev eth0 parent 1:10 handle 10: netem delay 100ms
tc qdisc add dev eth0 parent 1:11 handle 11: netem delay 100ms

# Giữ container chạy
wait $TX_PID

2.3. Docker Compose

Tạo docker-compose.yml:

version: '3.8'
services:
  proxy:
    build:
      context: .
      dockerfile: Dockerfile.proxy
    ports:
      - "8888:8888"
    cap_add:
      - NET_ADMIN   # Cần để sử dụng tc

Chạy:

docker compose up --build -d

Bạn sẽ có một proxy chạy tại http://localhost:8888 (hoặc socks5://localhost:8888 nếu thay đổi cấu hình). Mọi kết nối qua proxy sẽ bị giới hạn ở 500kbps và có độ trễ 100ms.

3. Tích hợp proxy vào các công cụ test

3.1. Python (requests)

import requests
import time

proxies = {
    "http": "http://localhost:8888",
    "https": "http://localhost:8888",
}

start = time.time()
response = requests.get("https://speed.hetzner.de/100MB.bin", proxies=proxies, timeout=60)
elapsed = time.time() - start
print(f"Status: {response.status_code}, Size: {len(response.content)} bytes, Time: {elapsed:.2f}s")

Lưu ý: tăng timeout đủ lớn để tránh bị couper khi tốc độ thấp.

3.2. Node.js (axios)

const axios = require('axios');

const instance = axios.create({
  proxy: {
    host: 'localhost',
    port: 8888,
  },
  timeout: 120000, // 2 phút
});

(async () => {
  const start = Date.now();
  try {
    const res = await instance.get('https://speed.hetzner.de/100MB.bin');
    const elapsed = (Date.now() - start) / 1000;
    console.log(`Status: ${res.status}, Size: ${res.data.length} bytes, Time: ${elapsed.toFixed(2)}s`);
  } catch (err) {
    console.error('Request failed:', err.message);
  }
})();

3.3. cURL

curl -x http://localhost:8888 -o /dev/null -w "%{http_code} %{size_download} %{time_total}s\n" \
     https://speed.hetzner.de/100MB.bin

3.4. Playwright (Node.js)

const { chromium } = require('playwright');

(async () => {
  const browser = await chromium.launch({
    proxy: { server: 'http://localhost:8888' },
  });
  const context = await browser.newContext();
  const page = await context.newPage();
  const start = Date.now();
  await page.goto('https://example.com', { waitUntil: 'networkidle' });
  const elapsed = (Date.now() - start) / 1000;
  console.log(`Loaded in ${elapsed.toFixed(2)}s`);
  await browser.close();
})();

4. Đo lường và phân tích kết quả

Khi chạy test, hãy ghi lại các chỉ số sau:

  • Thời gian phản hồi (response time)
  • Tốc độ tải xuống thực tế (bytes/second)
  • Tỷ lệ lỗi (timeout, connection reset)
  • Số lượng request được phục vụ trước khi gặp giới hạn

Bạn có thể sử dụng công cụ như wrkk6 để tạo tải đồng thời và quan sát cách throttling ảnh hưởng đến throughput.

4.1. Ví dụ với k6

Tạo file script.js:

import http from 'k6/http';
import { sleep, check } from 'k6';

export let options = {
  vus: 10,
  duration: '30s',
};

const params = {
  proxy: {
    http: 'http://localhost:8888',
    https: 'http://localhost:8888',
  },
  timeout: '120s',
};

export default function () {
  const res = http.get('https://speed.hetzner.de/1MB.bin', params);
  check(res, {
    'status is 200': (r) => r.status === 200,
    'body size is 1MB': (r) => r.body.length === 1024 * 1024,
  });
  sleep(1);
}

Chạy:

k6 run script.js

Kết quả sẽ cho bạn thấy average request duration và rate under throttling.

5. Điều chỉnh mức throttling cho các kịch bản khác nhau

Bạn có thể thay đổi các tham số trong entrypoint.sh để mô phỏng các trường hợp:

  • Mạng di động 3G: ~1.5Mbps download, 500kbps upload, latency 100ms
  • Mạng cáp công cộng: 5Mbps/2Mbps, latency 30ms
  • Mạng có mất gói: thêm netem loss 2% vào qdisc

Ví dụ để mô phỏng 3G:

tc class add dev eth0 parent 1:1 classid 1:10 htb rate 1500kbps ceil 1500kbps
tc class add dev eth0 parent 1:1 classid 1:11 htb rate 500kbps ceil 500kbps
tc qdisc add dev eth0 parent 1:10 handle 10: netem delay 100ms
tc qdisc add dev eth0 parent 1:11 handle 11: netem delay 100ms

6. Lưu ý vàベスト 프랙티스

  1. Không sử dụng proxy throttling trong môi trường sản xuất – chỉ dùng cho staging, CI hoặc local dev.
  2. Đóng gói cấu hình proxy thành biến môi trường để dễ bật/tắt (ví dụ HTTP_PROXY, HTTPS_PROXY).
  3. Kiểm tra độ trễ thực tế bằng ping hoặc tcptrace để đảm bảo tc đã được áp dụng đúng.
  4. Kết hợp với công cụ giám sát (Prometheus + Grafana) để lưu lại metrics từ các test và so sánh trước/sau khi áp dụng throttling.
  5. Luôn có kế hoạch rollback – nếu test thất bại vì quá mức throttling, giảm mức hạn chế và chạy lại.

7. Kết luận

Việc mô phỏng ISP throttling bằng proxy cho phép các nhóm phát triển phát hiện sớm các bottleneck về băng thông và độ trễ trước khi ảnh hưởng đến người dùng thực tế. Với cách triển khai đơn giản dựa trên Docker + tc, bạn có thể tạo ra các môi trường mạng linh hoạt, tái sử dụng và dễ dàng tích hợp vào các pipeline test tự động (GitHub Actions, GitLab CI, Jenkins). Từ đó, ứng dụng sẽ trở nên bền bější, cung cấp trải nghiệm ổn định dù người dùng kết nối qua bất kỳ loại kết nối mạng nào.

Bắt đầu ngay hôm nay bằng cách thêm proxy throttling vào bộ công cụ kiểm thử của bạn và quan sát sự khác biệt trong hiệu suất khi mạng thực tế bắt đầu chậm lại.