[{"data":1,"prerenderedAt":19},["ShallowReactive",2],{"blog:post:vi:cau-hinh-proxy-isp-throttling-test":3},{"slug":4,"lang":5,"title":6,"summary":7,"date":8,"tags":9,"tag_slugs":14,"thumbnail_url":15,"translations":16,"body":17,"asset_base":18},"cau-hinh-proxy-isp-throttling-test","vi","Cấu hình proxy để mô phỏng ISP throttling và kiểm tra độ bền của ứng dụng web","Hướng dẫn chi tiết cách sử dụng proxy để mô phỏng giới hạn băng thông của nhà cung cấp dịch vụ internet, giúp phát hiện và khắc phục vấn đề hiệu suất trước khi triển khai.","2026-09-09",[10,11,12,13],"proxy","testing","network","throttling",[10,11,12,13],"https://blog-api.ro-proxy.com/api/blog/posts/cau-hinh-proxy-isp-throttling-test/thumbnail.svg?lang=vi",[5],"## Giới thiệu\n\nTrong 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.\n\nBà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ả.\n\n## 1. Nguyên lý mô phỏng throttling qua proxy\n\nProxy 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:\n- **Bandwidth limit** (tốc độ tải xuống/tải lên, thường tính bằng kbps hoặc Mbps)\n- **Latency** (độ trễ một chiều, tính bằng ms)\n- **Packet loss** (tỷ lệ mất gói, tùy chọn)\n\nKhi 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.\n\n## 2. Chuẩn bị môi trường\n\nTa 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.\n\n### 2.1. Dockerfile cho proxy\n\nTạo file `Dockerfile.proxy`:\n\n```dockerfile\nFROM alpine:latest\n\n# Cài đặt tinyproxy và iproute2 (cho tc)\nRUN apk add --no-cache tinyproxy iproute2\n\n# Cấu hình tinyproxy mặc định (lắng nghe trên 8888)\nRUN echo \"Port 8888\" >> /etc/tinyproxy/tinyproxy.conf && \\\n    echo \"Allow 0.0.0.0/0\" >> /etc/tinyproxy/tinyproxy.conf\n\n# Sao chép script khởi chạy\nCOPY entrypoint.sh /usr/local/bin/entrypoint.sh\nRUN chmod +x /usr/local/bin/entrypoint.sh\n\nENTRYPOINT [\"/usr/local/bin/entrypoint.sh\"]\n```\n\n### 2.2. Script entrypoint\n\nTạo `entrypoint.sh`:\n\n```bash\n#!/bin/sh\n# Bắt đầu tinyproxy trong background\ntinyproxy -d &\nTX_PID=$!\n\n# Đợi tinyproxy sẵn sàng\nwhile ! nc -z localhost 8888; do\n    sleep 0.1\n done\n\n# Áp dụng quy tc vào giao diện mạng eth0 (mặc định của container)\n# Ví dụ: giới hạn 500 kbps download, 500 kbps upload, thêm 100ms latency\ntc qdisc add dev eth0 root handle 1: htb default 11\ntc class add dev eth0 parent 1: classid 1:1 htb rate 1000kbps\ntc class add dev eth0 parent 1:1 classid 1:10 htb rate 500kbps ceil 1000kbps\ntc class add dev eth0 parent 1:1 classid 1:11 htb rate 500kbps ceil 1000kbps\ntc qdisc add dev eth0 parent 1:10 handle 10: netem delay 100ms\ntc qdisc add dev eth0 parent 1:11 handle 11: netem delay 100ms\n\n# Giữ container chạy\nwait $TX_PID\n```\n\n### 2.3. Docker Compose\n\nTạo `docker-compose.yml`:\n\n```yaml\nversion: '3.8'\nservices:\n  proxy:\n    build:\n      context: .\n      dockerfile: Dockerfile.proxy\n    ports:\n      - \"8888:8888\"\n    cap_add:\n      - NET_ADMIN   # Cần để sử dụng tc\n```\n\nChạy:\n\n```bash\ndocker compose up --build -d\n```\n\nBạ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.\n\n## 3. Tích hợp proxy vào các công cụ test\n\n### 3.1. Python (requests)\n\n```python\nimport requests\nimport time\n\nproxies = {\n    \"http\": \"http://localhost:8888\",\n    \"https\": \"http://localhost:8888\",\n}\n\nstart = time.time()\nresponse = requests.get(\"https://speed.hetzner.de/100MB.bin\", proxies=proxies, timeout=60)\nelapsed = time.time() - start\nprint(f\"Status: {response.status_code}, Size: {len(response.content)} bytes, Time: {elapsed:.2f}s\")\n```\n\nLưu ý: tăng `timeout` đủ lớn để tránh bị couper khi tốc độ thấp.\n\n### 3.2. Node.js (axios)\n\n```js\nconst axios = require('axios');\n\nconst instance = axios.create({\n  proxy: {\n    host: 'localhost',\n    port: 8888,\n  },\n  timeout: 120000, // 2 phút\n});\n\n(async () => {\n  const start = Date.now();\n  try {\n    const res = await instance.get('https://speed.hetzner.de/100MB.bin');\n    const elapsed = (Date.now() - start) / 1000;\n    console.log(`Status: ${res.status}, Size: ${res.data.length} bytes, Time: ${elapsed.toFixed(2)}s`);\n  } catch (err) {\n    console.error('Request failed:', err.message);\n  }\n})();\n```\n\n### 3.3. cURL\n\n```bash\ncurl -x http://localhost:8888 -o /dev/null -w \"%{http_code} %{size_download} %{time_total}s\\n\" \\\n     https://speed.hetzner.de/100MB.bin\n```\n\n### 3.4. Playwright (Node.js)\n\n```js\nconst { chromium } = require('playwright');\n\n(async () => {\n  const browser = await chromium.launch({\n    proxy: { server: 'http://localhost:8888' },\n  });\n  const context = await browser.newContext();\n  const page = await context.newPage();\n  const start = Date.now();\n  await page.goto('https://example.com', { waitUntil: 'networkidle' });\n  const elapsed = (Date.now() - start) / 1000;\n  console.log(`Loaded in ${elapsed.toFixed(2)}s`);\n  await browser.close();\n})();\n```\n\n## 4. Đo lường và phân tích kết quả\n\nKhi chạy test, hãy ghi lại các chỉ số sau:\n- **Thời gian phản hồi (response time)**\n- **Tốc độ tải xuống thực tế (bytes/second)**\n- **Tỷ lệ lỗi (timeout, connection reset)**\n- **Số lượng request được phục vụ trước khi gặp giới hạn**\n\nBạn có thể sử dụng công cụ như **wrk**或**k6** để tạo tải đồng thời và quan sát cách throttling ảnh hưởng đến throughput.\n\n### 4.1. Ví dụ với k6\n\nTạo file `script.js`:\n\n```js\nimport http from 'k6/http';\nimport { sleep, check } from 'k6';\n\nexport let options = {\n  vus: 10,\n  duration: '30s',\n};\n\nconst params = {\n  proxy: {\n    http: 'http://localhost:8888',\n    https: 'http://localhost:8888',\n  },\n  timeout: '120s',\n};\n\nexport default function () {\n  const res = http.get('https://speed.hetzner.de/1MB.bin', params);\n  check(res, {\n    'status is 200': (r) => r.status === 200,\n    'body size is 1MB': (r) => r.body.length === 1024 * 1024,\n  });\n  sleep(1);\n}\n```\n\nChạy:\n\n```bash\nk6 run script.js\n```\n\nKết quả sẽ cho bạn thấy average request duration và rate under throttling.\n\n## 5. Điều chỉnh mức throttling cho các kịch bản khác nhau\n\nBạn có thể thay đổi các tham số trong `entrypoint.sh` để mô phỏng các trường hợp:\n- **Mạng di động 3G**: ~1.5Mbps download, 500kbps upload, latency 100ms\n- **Mạng cáp công cộng**: 5Mbps/2Mbps, latency 30ms\n- **Mạng có mất gói**: thêm `netem loss 2%` vào qdisc\n\nVí dụ để mô phỏng 3G:\n\n```bash\ntc class add dev eth0 parent 1:1 classid 1:10 htb rate 1500kbps ceil 1500kbps\ntc class add dev eth0 parent 1:1 classid 1:11 htb rate 500kbps ceil 500kbps\ntc qdisc add dev eth0 parent 1:10 handle 10: netem delay 100ms\ntc qdisc add dev eth0 parent 1:11 handle 11: netem delay 100ms\n```\n\n## 6. Lưu ý vàベスト 프랙티스\n\n1. **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.\n2. **Đó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`).\n3. **Kiểm tra độ trễ thực tế** bằng `ping` hoặc `tcptrace` để đảm bảo tc đã được áp dụng đúng.\n4. **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.\n5. **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.\n\n## 7. Kết luận\n\nViệ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.\n\nBắ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.\n","https://blog-api.ro-proxy.com/api/blog/posts/cau-hinh-proxy-isp-throttling-test/assets",1790057933917]