[{"data":1,"prerenderedAt":20},["ShallowReactive",2],{"blog:post:vi:xu-ly-loi-proxy-nodejs-axios-econnreset-timeout-429":3},{"slug":4,"lang":5,"title":6,"summary":7,"date":8,"tags":9,"tag_slugs":15,"thumbnail_url":16,"translations":17,"body":18,"asset_base":19},"xu-ly-loi-proxy-nodejs-axios-econnreset-timeout-429","vi","Xử Lý Lỗi Kết Nối Proxy Trong Node.js Axios: ECONNRESET, Timeout Và 429","Hướng dẫn khắc phục lỗi kết nối proxy phổ biến khi scraping bằng Node.js Axios, kèm cấu hình xoay IP, session dính và retry logic.","2026-10-12",[10,11,12,13,14],"nodejs","proxy","axios","web-scraping","troubleshooting",[10,11,12,13,14],"https://blog-api.ro-proxy.com/api/blog/posts/xu-ly-loi-proxy-nodejs-axios-econnreset-timeout-429/thumbnail.svg?lang=vi",[5],"Khi xây dựng hệ thống scraping hoặc tự động hóa bằng Node.js, Axios là lựa chọn hàng đầu nhờ cú pháp đơn giản, hỗ trợ Promise và khả năng xử lý bất đồng bộ hiệu quả. Tuy nhiên, khi tích hợp proxy, đặc biệt là proxy xoay (rotating proxy), các nhà phát triển thường gặp phải hàng loạt lỗi kết nối khiến quy trình bị gián đoạn hoặc dữ liệu bị thiếu.\n\nBài viết này đi sâu vào nguyên nhân và cách khắc phục ba lỗi phổ biến nhất: ECONNRESET, ETIMEDOUT và 429 Too Many Requests. Bạn sẽ học cách cấu hình Axios, xây dựng pool proxy, duy trì sticky session và triển khai retry logic với backoff để hệ thống của bạn hoạt động ổn định hơn.\n\n## Các lỗi proxy thường gặp và nguyên nhân\n\nĐể sửa lỗi, trước hết bạn cần hiểu rõ nguồn gốc của chúng. Mỗi mã lỗi phản ánh một vấn đề cụ thể ở một lớp khác nhau của mô hình OSI.\n\n### ECONNRESET: Kết nối bị ngắt bất ngờ\n\nLỗi connect ECONNRESET xảy ra khi kết nối TCP bị ngắt đột ngột bởi máy chủ proxy, firewall hoặc target website. Đây là dấu hiệu cho thấy phía server đã đóng kết nối mà không báo trước. Nguyên nhân thường gặp bao gồm:\n\n- Proxy quá tải hoặc bị chết (dead proxy).\n- IP proxy bị target website chặn do hoạt động đáng ngờ.\n- Proxy server đóng kết nối do hết thời gian giữ (idle timeout).\n- Tường lửa mạng can thiệp vào luồng dữ liệu.\n\nKhi Axios nhận được tín hiệu ngắt kết nối, nó sẽ ném ra lỗi connect ECONNRESET. Việc retry ngay lập tức thường thất bại vì kết nối thực sự đã bị đóng.\n\n### ETIMEDOUT: Quá thời gian chờ\n\nLỗi này xuất hiện khi request không hoàn thành trong khoảng thời gian quy định. Proxy chậm hoặc mạng không ổn định là nguyên nhân chính. Bạn không nên tăng timeout vô hạn vì sẽ làm nghẽn tài nguyên. Thay vào đó, hãy tìm cách giảm độ trễ hoặc chọn proxy tốt hơn.\n\n### 429 Too Many Requests: Bị giới hạn tốc độ\n\nTarget website phát hiện bạn gửi quá nhiều request từ cùng một IP trong một khoảng thời gian. Proxy xoay giúp giảm thiểu rủi ro này, nhưng nếu xoay quá nhanh hoặc không đủ IP, bạn vẫn bị chặn. Xử lý 429 khác với lỗi mạng: bạn cần giảm tốc độ gửi request, không phải thử lại ngay.\n\n## Cấu hình Axios với Proxy cơ bản\n\nBước đầu tiên là cấu hình Axios để sử dụng proxy. Trong Node.js, bạn cần sử dụng `http-proxy-agent` để tạo một agent tùy chỉnh. Đừng quên đặt timeout hợp lý vì timeout mặc định của Axios là 0 (không giới hạn), điều này có thể khiến một request treo mãi nếu proxy bị chết.\n\n```javascript\nconst axios = require('axios');\nconst HttpProxyAgent = require('http-proxy-agent');\n\nconst proxyUrl = process.env.PROXY_URL || 'http://user:pass@ip:port';\nconst agent = new HttpProxyAgent(proxyUrl);\n\nconst client = axios.create({\n  httpsAgent: agent,\n  httpAgent: agent,\n  timeout: 10000,\n});\n```\n\n## Xây dựng Pool Proxy và Logic Xoay IP\n\nĐể tránh bị chặn, bạn không nên dùng một proxy duy nhất. Thay vào đó, hãy duy trì một danh sách các proxy và xoay vòng chúng. Đây là logic xoay cơ bản, không cần đến API bên ngoài.\n\n```javascript\nclass ProxyPool {\n  constructor(proxies) {\n    this.proxies = proxies;\n    this.index = 0;\n  }\n\n  get() {\n    const proxy = this.proxies[this.index];\n    this.index = (this.index + 1) % this.proxies.length;\n    return proxy;\n  }\n\n  remove(badProxy) {\n    this.proxies = this.proxies.filter(p => p !== badProxy);\n  }\n}\n```\n\nTrong môi trường production, bạn sẽ tải danh sách proxy từ dịch vụ của mình hoặc từ file cấu hình. Logic xoay vòng đơn giản giúp phân phối tải đều và tránh bị phát hiện.\n\n## Duy trì Sticky Session với Keep-Alive Agent\n\nTrong một số trường hợp, việc xoay IP liên tục là không mong muốn. Ví dụ, khi đăng nhập vào một trang web, bạn cần giữ nguyên một IP cho đến khi phiên kết thúc. Nếu không, hệ thống sẽ yêu cầu xác thực lại.\n\nĐể duy trì sticky session, bạn cần tạo một agent riêng cho mỗi proxy và sử dụng lại nó cho toàn bộ request trong phiên. Điều này cũng giúp tận dụng kết nối keep-alive, giảm độ trễ.\n\n```javascript\nconst agents = {};\n\nfunction getAgent(proxyUrl) {\n  if (!agents[proxyUrl]) {\n    agents[proxyUrl] = new HttpProxyAgent(proxyUrl, { keepAlive: true });\n  }\n  return agents[proxyUrl];\n}\n\nasync function scrapeWithSession(url, proxyUrl) {\n  const agent = getAgent(proxyUrl);\n  const response = await axios.get(url, {\n    httpsAgent: agent,\n    httpAgent: agent,\n  });\n  return response.data;\n}\n```\n\nKhi phiên kết thúc, hãy xóa agent khỏi bộ nhớ để tránh rò rỉ tài nguyên.\n\n## Triển Khai Retry Logic Với Backoff\n\nRetry logic là chìa khóa để xử lý các lỗi tạm thời như ECONNRESET và ETIMEDOUT. Tuy nhiên, bạn cần phân biệt giữa lỗi mạng và lỗi nghiệp vụ như 429.\n\n```javascript\nasync function sleep(ms) {\n  return new Promise(resolve => setTimeout(resolve, ms));\n}\n\nasync function requestWithRetry(url, options, maxRetries = 3) {\n  let lastError;\n  for (let i = 0; i \u003C= maxRetries; i++) {\n    try {\n      return await axios.get(url, options);\n    } catch (error) {\n      lastError = error;\n      const status = error.response ? error.response.status : null;\n\n      if (status === 429) {\n        await sleep(2000 * i + 1000);\n        continue;\n      }\n\n      if (status === 403 || status === 404) {\n        break;\n      }\n\n      if (i \u003C maxRetries) {\n        await sleep(1000 * (i + 1));\n      }\n    }\n  }\n  throw lastError;\n}\n```\n\nLogic trên sẽ thử lại với backoff cho các lỗi mạng, nhưng dừng lại đối với 403/404 để tránh lãng phí thời gian.\n\n## Kiểm Tra và Xác Minh Proxy Trước Khi Dùng\n\nTrước khi đưa proxy vào vòng xoay, hãy kiểm tra sức khỏe của nó. Proxy chết hoặc không hoạt động sẽ gây ra lỗi liên tục. Bạn có thể chạy kiểm tra này định kỳ để loại bỏ các proxy hỏng khỏi pool.\n\n```javascript\nasync function checkProxyHealth(proxyUrl) {\n  try {\n    const start = Date.now();\n    await axios.get('https://api.ipify.org', {\n      proxy: proxyUrl,\n      timeout: 5000,\n    });\n    return { healthy: true, latency: Date.now() - start };\n  } catch (error) {\n    return { healthy: false, error: error.message };\n  }\n}\n```\n\n## Kết Luận\n\nXử lý lỗi proxy trong Node.js Axios đòi hỏi sự kết hợp giữa cấu hình đúng đắn, pool proxy linh hoạt và retry logic thông minh. Bằng cách hiểu rõ nguyên nhân của ECONNRESET, ETIMEDOUT và 429, bạn có thể xây dựng một hệ thống scraping bền vững, tự phục hồi và hiệu quả. Hãy bắt đầu với các cấu hình cơ bản và tinh chỉnh dần dựa trên phản hồi từ target website.\n","https://blog-api.ro-proxy.com/api/blog/posts/xu-ly-loi-proxy-nodejs-axios-econnreset-timeout-429/assets",1792303105367]