Quay lại blog

Cách cấu hình proxy trong ứng dụng serverless: AWS Lambda, Vercel, Cloudflare Workers

Hướng dẫn đầy đủ về việc tích hợp proxy vào các chức năng serverless: từ cấu hình HTTP clients đến việc vượt qua giới hạn tốc độ và chặn địa lý trong AWS Lambda, Vercel Edge Functions và Cloudflare Workers.

📅19 tháng 2, 2026
```html

Kiến trúc serverless đã trở thành tiêu chuẩn cho các ứng dụng web hiện đại, nhưng các nhà phát triển thường xuyên gặp phải vấn đề: tất cả các yêu cầu từ các chức năng Lambda hoặc Edge Functions đều đến từ địa chỉ IP của các trung tâm dữ liệu của các nhà cung cấp đám mây. Điều này dẫn đến việc bị chặn khi truy cập vào các API bên ngoài, thu thập dữ liệu hoặc tự động hóa các tác vụ. Trong hướng dẫn này, chúng ta sẽ xem xét cách tích hợp proxy vào các chức năng serverless để vượt qua các hạn chế, giới hạn tốc độ và chặn địa lý.

Tại sao các chức năng serverless cần proxy

Các nền tảng serverless (AWS Lambda, Google Cloud Functions, Vercel, Cloudflare Workers) thực thi mã trong cơ sở hạ tầng đám mây, sử dụng địa chỉ IP của các trung tâm dữ liệu. Điều này tạo ra một số vấn đề nghiêm trọng cho các nhà phát triển:

Vấn đề 1: Bị chặn theo IP của các trung tâm dữ liệu. Nhiều dịch vụ tự động chặn các yêu cầu từ các địa chỉ IP đã biết của AWS, Google Cloud hoặc Azure. Ví dụ, khi thu thập dữ liệu từ các trang thương mại điện tử (Amazon, eBay, Wildberries) hoặc mạng xã hội (Instagram API, TikTok API), các chức năng Lambda của bạn sẽ nhận được HTTP 403 hoặc captcha ngay từ yêu cầu đầu tiên. Các hệ thống bảo vệ chống bot (Cloudflare, Akamai, DataDome) ngay lập tức nhận diện lưu lượng truy cập từ các trung tâm dữ liệu đám mây.

Vấn đề 2: Giới hạn tốc độ theo IP. Nếu bạn triển khai một ứng dụng serverless với hàng nghìn yêu cầu đồng thời, tất cả các yêu cầu có thể đến từ một hoặc vài địa chỉ IP của AWS. Các API bên ngoài nhanh chóng đạt đến giới hạn (ví dụ, GitHub API — 60 yêu cầu/giờ từ một IP, Google Maps API — 100 yêu cầu/giây). Ngay cả khi bạn đã thanh toán cho gói API mở rộng, giới hạn theo IP vẫn sẽ được áp dụng.

Vấn đề 3: Chặn địa lý. Các chức năng serverless trong khu vực us-east-1 sẽ không thể truy cập vào nội dung chỉ có sẵn từ Nga, Châu Âu hoặc Châu Á. Điều này rất nghiêm trọng khi thu thập dữ liệu từ các thị trường khu vực (Ozon, Yandex.Market), kiểm tra quảng cáo từ các quốc gia khác nhau hoặc thử nghiệm việc địa phương hóa các trang web.

Vấn đề 4: IP chia sẻ với các người dùng khác. Trong môi trường serverless, các chức năng của bạn có thể nhận được một địa chỉ IP đã được sử dụng bởi các khách hàng khác của nhà cung cấp đám mây. Nếu ai đó trước đó đã lạm dụng địa chỉ IP này (spam, DDoS, thu thập dữ liệu), nó có thể nằm trong danh sách đen. Bạn sẽ bị chặn mà không có bất kỳ lỗi nào.

Giải pháp cho tất cả những vấn đề này là tích hợp các máy chủ proxy. Proxy cho phép các chức năng serverless của bạn gửi yêu cầu qua các địa chỉ IP dân cư hoặc di động, trông giống như người dùng bình thường. Điều này loại bỏ các chặn, vượt qua giới hạn tốc độ và cung cấp quyền truy cập vào nội dung bị chặn địa lý.

Các loại proxy nào phù hợp cho serverless

Việc lựa chọn loại proxy phụ thuộc vào nhiệm vụ của ứng dụng serverless của bạn. Hãy xem xét ba tùy chọn chính và các kịch bản sử dụng của chúng:

Loại proxy Tốc độ Ẩn danh Kịch bản sử dụng
Proxy trung tâm dữ liệu Rất cao (10-50 ms) Thấp Truy cập API mà không có giới hạn nghiêm ngặt, kiểm tra khả năng truy cập dịch vụ, giám sát uptime
Proxy dân cư Trung bình (100-500 ms) Cao Thu thập dữ liệu thương mại điện tử, làm việc với mạng xã hội, vượt qua Cloudflare, truy cập vào nội dung bị chặn địa lý
Proxy di động Trung bình (150-600 ms) Rất cao Làm việc với API di động (Instagram, TikTok), thử nghiệm ứng dụng di động, vượt qua các bảo vệ nghiêm ngặt nhất

Đối với hầu hết các ứng dụng serverless, nên sử dụng proxy dân cư. Chúng cung cấp sự cân bằng tối ưu giữa tốc độ và ẩn danh. Các IP dân cư trông giống như người dùng bình thường, điều này cho phép vượt qua các bảo vệ chống bot và giới hạn tốc độ mà không làm tăng đáng kể độ trễ.

Proxy trung tâm dữ liệu chỉ phù hợp cho các tác vụ đơn giản (kiểm tra trạng thái HTTP, làm việc với các API công khai mà không có giới hạn). Proxy di động cần thiết trong các trường hợp cụ thể — khi bạn làm việc với các API di động hoặc khi bạn cần ẩn danh tối đa.

Cấu hình proxy trong AWS Lambda

AWS Lambda là nền tảng serverless phổ biến nhất, và việc tích hợp proxy ở đây yêu cầu cấu hình HTTP client đúng cách. Các chức năng Lambda có thể sử dụng nhiều ngôn ngữ lập trình khác nhau (Node.js, Python, Go), hãy xem xét các ví dụ cho những ngôn ngữ phổ biến nhất.

Node.js (axios)

Axios là thư viện phổ biến nhất cho các yêu cầu HTTP trong Node.js. Để cấu hình proxy, hãy sử dụng tham số proxy trong cấu hình:

const axios = require('axios');

exports.handler = async (event) => {
  const proxyConfig = {
    host: 'proxy.example.com',
    port: 8080,
    auth: {
      username: 'your_username',
      password: 'your_password'
    },
    protocol: 'http'
  };

  try {
    const response = await axios.get('https://api.example.com/data', {
      proxy: proxyConfig,
      timeout: 10000 // 10 giây
    });

    return {
      statusCode: 200,
      body: JSON.stringify(response.data)
    };
  } catch (error) {
    console.error('Lỗi proxy:', error.message);
    return {
      statusCode: 500,
      body: JSON.stringify({ error: error.message })
    };
  }
};

Điểm quan trọng: hãy lưu trữ thông tin xác thực proxy trong AWS Systems Manager Parameter Store hoặc AWS Secrets Manager, thay vì trong mã. Điều này sẽ đảm bảo an toàn và cho phép bạn dễ dàng thay đổi proxy mà không cần tái biên dịch chức năng.

Python (requests)

Trong Python, để làm việc với proxy, hãy sử dụng thư viện requests với tham số proxies:

import requests
import json

def lambda_handler(event, context):
    proxies = {
        'http': 'http://username:password@proxy.example.com:8080',
        'https': 'http://username:password@proxy.example.com:8080'
    }
    
    try:
        response = requests.get(
            'https://api.example.com/data',
            proxies=proxies,
            timeout=10
        )
        
        return {
            'statusCode': 200,
            'body': json.dumps(response.json())
        }
    except requests.exceptions.RequestException as e:
        print(f'Lỗi proxy: {str(e)}')
        return {
            'statusCode': 500,
            'body': json.dumps({'error': str(e)})
        }

Đối với proxy SOCKS5 (giao thức bảo mật hơn), trong Python bạn cần cài đặt thư viện bổ sung requests[socks] và thay đổi định dạng URL:

proxies = {
    'http': 'socks5://username:password@proxy.example.com:1080',
    'https': 'socks5://username:password@proxy.example.com:1080'
}

Tối ưu hóa cho các lần khởi động lạnh

Các chức năng Lambda gặp vấn đề về khởi động lạnh — yêu cầu đầu tiên sau thời gian nghỉ sẽ mất 1-3 giây. Khi sử dụng proxy, thời gian này sẽ tăng lên. Để giảm thiểu độ trễ, hãy tạo HTTP client bên ngoài chức năng handler:

const axios = require('axios');

// Tạo client một lần khi khởi tạo container
const httpClient = axios.create({
  proxy: {
    host: 'proxy.example.com',
    port: 8080,
    auth: {
      username: process.env.PROXY_USER,
      password: process.env.PROXY_PASS
    }
  },
  timeout: 10000
});

exports.handler = async (event) => {
  // Tái sử dụng client cho mỗi lần gọi
  const response = await httpClient.get('https://api.example.com/data');
  return {
    statusCode: 200,
    body: JSON.stringify(response.data)
  };
};

Cách tiếp cận này giảm thời gian khởi động lạnh từ 200-500 ms, vì cấu hình proxy chỉ được thực hiện một lần khi tạo container Lambda.

Tích hợp proxy vào Vercel Edge Functions

Vercel cung cấp hai loại chức năng serverless: Node.js Functions (tương tự Lambda) và Edge Functions (thực thi trên CDN). Edge Functions hoạt động trong runtime gần giống với Cloudflare Workers, với các hạn chế về việc sử dụng API Node.js. Hãy xem xét cả hai tùy chọn.

Vercel Node.js Functions

Đối với các Vercel Functions thông thường, hãy sử dụng cùng một cách tiếp cận như đối với AWS Lambda. Tạo một tệp api/fetch-data.js:

import axios from 'axios';

export default async function handler(req, res) {
  const proxyConfig = {
    host: process.env.PROXY_HOST,
    port: parseInt(process.env.PROXY_PORT),
    auth: {
      username: process.env.PROXY_USER,
      password: process.env.PROXY_PASS
    }
  };

  try {
    const response = await axios.get(req.query.url, {
      proxy: proxyConfig,
      timeout: 8000
    });

    res.status(200).json(response.data);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
}

Thêm các biến môi trường vào Vercel Dashboard (Settings → Environment Variables): PROXY_HOST, PROXY_PORT, PROXY_USER, PROXY_PASS.

Vercel Edge Functions

Edge Functions sử dụng Web Fetch API thay vì các thư viện Node.js. Proxy được cấu hình thông qua các tiêu đề tùy chỉnh hoặc middleware:

export const config = {
  runtime: 'edge',
};

export default async function handler(req) {
  const proxyUrl = `http://${process.env.PROXY_USER}:${process.env.PROXY_PASS}@${process.env.PROXY_HOST}:${process.env.PROXY_PORT}`;
  
  // Đối với Edge Runtime cần fetch với proxy qua agent (cần polyfill)
  // Giải pháp thay thế: sử dụng proxy API trực tiếp
  const targetUrl = new URL(req.url).searchParams.get('target');
  
  const response = await fetch(targetUrl, {
    headers: {
      'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
    }
  });

  return new Response(await response.text(), {
    status: response.status,
    headers: response.headers
  });
}

Hạn chế quan trọng: Edge Runtime không hỗ trợ các proxy agent tiêu chuẩn của Node.js. Để làm việc hoàn chỉnh với proxy, nên sử dụng Node.js Functions hoặc tạo một máy chủ proxy trung gian trên một máy chủ riêng biệt, sẽ nhận các yêu cầu từ Edge Functions.

Proxy trong Cloudflare Workers

Cloudflare Workers hoạt động trong V8 isolates và có các hạn chế nghiêm ngặt hơn so với Vercel Edge Functions. Cách kết nối proxy tiêu chuẩn thông qua các thư viện Node.js không hoạt động ở đây. Có hai cách tiếp cận khả thi:

Phương pháp 1: Tunneling HTTP CONNECT

Sử dụng proxy hỗ trợ phương pháp HTTP CONNECT. Tạo một đường hầm qua máy chủ proxy:

addEventListener('fetch', event => {
  event.respondWith(handleRequest(event.request))
})

async function handleRequest(request) {
  const proxyUrl = 'http://proxy.example.com:8080';
  const targetUrl = 'https://api.example.com/data';
  
  const proxyAuth = btoa(`${PROXY_USER}:${PROXY_PASS}`);
  
  const response = await fetch(proxyUrl, {
    method: 'CONNECT',
    headers: {
      'Host': new URL(targetUrl).host,
      'Proxy-Authorization': `Basic ${proxyAuth}`
    }
  });

  if (response.status === 200) {
    // Đường hầm đã được thiết lập, thực hiện yêu cầu chính
    const finalResponse = await fetch(targetUrl, {
      headers: {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)'
      }
    });
    
    return finalResponse;
  }
  
  return new Response('Kết nối proxy thất bại', { status: 502 });
}

Phương pháp này chỉ hoạt động với các proxy HTTP hỗ trợ CONNECT. Hầu hết các nhà cung cấp proxy dân cư đều cung cấp khả năng này.

Phương pháp 2: Cổng proxy (được khuyến nghị)

Cách đáng tin cậy hơn là triển khai một cổng proxy trung gian trên một máy chủ riêng biệt (ví dụ: trên VPS hoặc AWS EC2). Cloudflare Worker gửi các yêu cầu đến cổng của bạn, và cổng đó sẽ chuyển tiếp chúng qua proxy:

// Cloudflare Worker
addEventListener('fetch', event => {
  event.respondWith(handleRequest(event.request))
})

async function handleRequest(request) {
  const targetUrl = new URL(request.url).searchParams.get('url');
  const gatewayUrl = 'https://your-proxy-gateway.com/fetch';
  
  const response = await fetch(gatewayUrl, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-API-Key': API_KEY // Bảo vệ cổng của bạn
    },
    body: JSON.stringify({
      url: targetUrl,
      method: 'GET'
    })
  });

  return response;
}

Ở phía cổng proxy (máy chủ Node.js):

const express = require('express');
const axios = require('axios');

const app = express();
app.use(express.json());

const proxyConfig = {
  host: 'proxy.example.com',
  port: 8080,
  auth: {
    username: process.env.PROXY_USER,
    password: process.env.PROXY_PASS
  }
};

app.post('/fetch', async (req, res) => {
  if (req.headers['x-api-key'] !== process.env.API_KEY) {
    return res.status(401).json({ error: 'Không được phép' });
  }

  try {
    const response = await axios({
      url: req.body.url,
      method: req.body.method || 'GET',
      proxy: proxyConfig,
      timeout: 10000
    });

    res.json(response.data);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

app.listen(3000);

Cách tiếp cận này thêm một bước nhảy (tăng độ trễ từ 50-100 ms), nhưng đảm bảo tính tương thích hoàn toàn và kiểm soát đối với kết nối proxy.

Xoay vòng địa chỉ IP trong môi trường serverless

Một trong những lý do chính để sử dụng proxy là phân phối các yêu cầu giữa nhiều địa chỉ IP để vượt qua giới hạn tốc độ. Trong kiến trúc serverless, có hai cách tiếp cận để xoay vòng:

Xoay vòng tự động từ phía nhà cung cấp proxy

Hầu hết các nhà cung cấp proxy dân cư cung cấp proxy xoay vòng — bạn kết nối với một endpoint, và IP sẽ tự động thay đổi mỗi khi có yêu cầu hoặc theo khoảng thời gian xác định (ví dụ: mỗi 5 phút). Đây là tùy chọn đơn giản nhất cho serverless:

// Một endpoint, IP tự động thay đổi
const proxyConfig = {
  host: 'rotating.proxy.example.com',
  port: 8080,
  auth: {
    username: 'user-session-' + Date.now(), // Phiên duy nhất
    password: 'password'
  }
};

Một số nhà cung cấp cho phép quản lý việc xoay vòng thông qua các tham số trong tên người dùng: user-session-random (IP mới cho mỗi yêu cầu), user-session-sticky-300 (một IP trong 300 giây).

Xoay vòng thủ công qua nhóm proxy

Nếu bạn có danh sách các proxy tĩnh (ví dụ: bạn đã mua proxy chuyên dụng), bạn có thể thực hiện việc xoay vòng ở cấp độ ứng dụng. Trong môi trường serverless, hãy sử dụng DynamoDB (AWS) hoặc KV Storage (Cloudflare) để lưu trữ trạng thái:

const AWS = require('aws-sdk');
const dynamodb = new AWS.DynamoDB.DocumentClient();

const PROXY_POOL = [
  { host: 'proxy1.example.com', port: 8080 },
  { host: 'proxy2.example.com', port: 8080 },
  { host: 'proxy3.example.com', port: 8080 }
];

async function getNextProxy() {
  // Lấy chỉ số hiện tại từ DynamoDB
  const result = await dynamodb.get({
    TableName: 'ProxyRotation',
    Key: { id: 'current_index' }
  }).promise();

  const currentIndex = result.Item?.index || 0;
  const nextIndex = (currentIndex + 1) % PROXY_POOL.length;

  // Cập nhật chỉ số
  await dynamodb.put({
    TableName: 'ProxyRotation',
    Item: { id: 'current_index', index: nextIndex }
  }).promise();

  return PROXY_POOL[currentIndex];
}

exports.handler = async (event) => {
  const proxy = await getNextProxy();
  
  const response = await axios.get('https://api.example.com/data', {
    proxy: {
      ...proxy,
      auth: {
        username: process.env.PROXY_USER,
        password: process.env.PROXY_PASS
      }
    }
  });

  return { statusCode: 200, body: JSON.stringify(response.data) };
};

Phương pháp này cung cấp kiểm soát hoàn toàn đối với việc xoay vòng, nhưng yêu cầu thêm các yêu cầu đến DynamoDB (tăng thêm 10-30 ms độ trễ). Đối với các ứng dụng có tải cao, nên lưu trữ chỉ số trong bộ nhớ của container Lambda và cập nhật nó mỗi 100-1000 yêu cầu.

Xử lý lỗi và thời gian chờ

Proxy thêm một điểm từ chối bổ sung vào ứng dụng serverless của bạn. Việc xử lý lỗi đúng cách là rất quan trọng để không mất các yêu cầu của người dùng.

Các lỗi điển hình khi làm việc với proxy

Lỗi Nguyên nhân Giải pháp
ETIMEDOUT Proxy không phản hồi hoặc hoạt động chậm Giảm thời gian chờ xuống 5-8 giây, thêm retry với proxy khác
ECONNREFUSED Máy chủ proxy không khả dụng Kiểm tra khả năng truy cập proxy, sử dụng fallback đến proxy khác
407 Proxy Authentication Required Thông tin xác thực không chính xác Kiểm tra username/password, đảm bảo rằng IP Lambda được phép trong whitelist của proxy
502 Bad Gateway Proxy không thể kết nối đến trang web mục tiêu Trang web có thể chặn proxy, thử một IP hoặc loại proxy khác

Triển khai logic retry với fallback

Thêm các lần thử tự động với việc chuyển sang proxy dự phòng khi có lỗi:

const axios = require('axios');

const PRIMARY_PROXY = {
  host: 'primary.proxy.com',
  port: 8080,
  auth: { username: 'user', password: 'pass' }
};

const FALLBACK_PROXY = {
  host: 'fallback.proxy.com',
  port: 8080,
  auth: { username: 'user', password: 'pass' }
};

async function fetchWithRetry(url, maxRetries = 3) {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    const proxy = attempt === 0 ? PRIMARY_PROXY : FALLBACK_PROXY;
    
    try {
      const response = await axios.get(url, {
        proxy,
        timeout: 8000
      });
      
      return response.data;
    } catch (error) {
      console.log(`Attempt ${attempt + 1} failed:`, error.message);
      
      // Không retry với lỗi của khách hàng (4xx)
      if (error.response && error.response.status < 500) {
        throw error;
      }
      
      // Lần thử cuối cùng — ném lỗi
      if (attempt === maxRetries - 1) {
        throw error;
      }
      
      // Đợi theo kiểu exponential trước khi retry
      await new Promise(resolve => setTimeout(resolve, 1000 * Math.pow(2, attempt)));
    }
  }
}

exports.handler = async (event) => {
  try {
    const data = await fetchWithRetry('https://api.example.com/data');
    return { statusCode: 200, body: JSON.stringify(data) };
  } catch (error) {
    return { statusCode: 500, body: JSON.stringify({ error: error.message }) };
  }
};

Triển khai này cung cấp ba lần thử yêu cầu: lần đầu tiên qua proxy chính, các lần còn lại qua proxy dự phòng. Giữa các lần thử có thêm độ trễ exponential (1 giây, 2 giây, 4 giây) để không tạo ra quá nhiều tải.

Giám sát và cảnh báo

Thiết lập giám sát lỗi proxy qua CloudWatch (AWS), Vercel Analytics hoặc Sentry. Theo dõi các chỉ số:

  • Tỷ lệ yêu cầu thành công qua proxy (nên >95%)
  • Độ trễ trung bình của các yêu cầu (tăng có thể chỉ ra vấn đề với proxy)
  • Số lượng lỗi thời gian chờ (nếu >5% — proxy bị quá tải hoặc chậm)
  • Phân phối lỗi theo mã (407, 502, ETIMEDOUT, v.v.)

Thiết lập cảnh báo khi vượt quá ngưỡng — điều này sẽ cho phép bạn nhanh chóng chuyển sang nhà cung cấp proxy dự phòng hoặc thay đổi cấu hình.

Kết luận

Tích hợp proxy vào các ứng dụng serverless giải quyết các vấn đề nghiêm trọng: chặn theo IP của các trung tâm dữ liệu, giới hạn tốc độ và chặn địa lý. Chúng ta đã xem xét cấu hình proxy trong AWS Lambda (Node.js và Python), Vercel Functions và Cloudflare Workers, cũng như triển khai việc xoay vòng địa chỉ IP và xử lý lỗi.

Các khuyến nghị chính: sử dụng proxy dân cư cho các tác vụ yêu cầu ẩn danh cao (thu thập dữ liệu, làm việc với API mạng xã hội), lưu trữ thông tin xác thực trong các kho bảo mật (AWS Secrets Manager, Vercel Environment Variables), triển khai logic retry với fallback đến các proxy dự phòng và thiết lập giám sát lỗi.

Đối với các ứng dụng serverless có yêu cầu cao về độ ổn định, chúng tôi khuyên bạn nên sử dụng proxy dân cư với việc xoay vòng tự động — chúng cung cấp sự cân bằng tối ưu giữa tốc độ, ẩn danh và độ tin cậy, giảm thiểu rủi ro bị chặn khi làm việc với các API và dịch vụ bên ngoài.

```