Xử Lý Lỗi Kết Nối Proxy Trong Node.js Axios: ECONNRESET, Timeout Và 429
12 tháng 10, 2026
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.
Bà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.
Các lỗi proxy thường gặp và nguyên nhâ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.
ECONNRESET: Kết nối bị ngắt bất ngờ
Lỗ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:
- Proxy quá tải hoặc bị chết (dead proxy).
- IP proxy bị target website chặn do hoạt động đáng ngờ.
- Proxy server đóng kết nối do hết thời gian giữ (idle timeout).
- Tường lửa mạng can thiệp vào luồng dữ liệu.
Khi 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.
ETIMEDOUT: Quá thời gian chờ
Lỗ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.
429 Too Many Requests: Bị giới hạn tốc độ
Target 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.
Cấu hình Axios với Proxy cơ bản
Bướ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.
const axios = require('axios');
const HttpProxyAgent = require('http-proxy-agent');
const proxyUrl = process.env.PROXY_URL || 'http://user:pass@ip:port';
const agent = new HttpProxyAgent(proxyUrl);
const client = axios.create({
httpsAgent: agent,
httpAgent: agent,
timeout: 10000,
});
Xây dựng Pool Proxy và Logic Xoay IP
Để 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.
class ProxyPool {
constructor(proxies) {
this.proxies = proxies;
this.index = 0;
}
get() {
const proxy = this.proxies[this.index];
this.index = (this.index + 1) % this.proxies.length;
return proxy;
}
remove(badProxy) {
this.proxies = this.proxies.filter(p => p !== badProxy);
}
}
Trong 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.
Duy trì Sticky Session với Keep-Alive Agent
Trong 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.
Để 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ễ.
const agents = {};
function getAgent(proxyUrl) {
if (!agents[proxyUrl]) {
agents[proxyUrl] = new HttpProxyAgent(proxyUrl, { keepAlive: true });
}
return agents[proxyUrl];
}
async function scrapeWithSession(url, proxyUrl) {
const agent = getAgent(proxyUrl);
const response = await axios.get(url, {
httpsAgent: agent,
httpAgent: agent,
});
return response.data;
}
Khi phiên kết thúc, hãy xóa agent khỏi bộ nhớ để tránh rò rỉ tài nguyên.
Triển Khai Retry Logic Với Backoff
Retry 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.
async function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function requestWithRetry(url, options, maxRetries = 3) {
let lastError;
for (let i = 0; i <= maxRetries; i++) {
try {
return await axios.get(url, options);
} catch (error) {
lastError = error;
const status = error.response ? error.response.status : null;
if (status === 429) {
await sleep(2000 * i + 1000);
continue;
}
if (status === 403 || status === 404) {
break;
}
if (i < maxRetries) {
await sleep(1000 * (i + 1));
}
}
}
throw lastError;
}
Logic 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.
Kiểm Tra và Xác Minh Proxy Trước Khi Dùng
Trướ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.
async function checkProxyHealth(proxyUrl) {
try {
const start = Date.now();
await axios.get('https://api.ipify.org', {
proxy: proxyUrl,
timeout: 5000,
});
return { healthy: true, latency: Date.now() - start };
} catch (error) {
return { healthy: false, error: error.message };
}
}
Kết Luận
Xử 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.