بازگشت به وبلاگ

چگونه پروکسی را در AWS Lambda برای پارس کردن و API تنظیم کنیم: راهنمای کامل با مثال‌ها

راهنمای گام به گام برای تنظیم پروکسی در AWS Lambda برای پارس کردن، درخواست‌های API و اتوماسیون. نمونه‌های کد به زبان‌های Python و Node.js، راه‌حل مشکلات متداول.

📅۲۹ بهمن ۱۴۰۴
```html

AWS Lambda یک پلتفرم بدون سرور است که به شما امکان می‌دهد کد را بدون مدیریت سرورها اجرا کنید. با این حال، هنگام کار با پارس کردن وب‌سایت‌ها، API بازارها یا اتوماسیون وظایف، اغلب با مشکلی مواجه می‌شوید: توابع Lambda از آدرس‌های IP AWS استفاده می‌کنند که به راحتی قابل شناسایی و مسدود هستند. در این راهنما، نحوه ادغام پروکسی در Lambda، تنظیم چرخش IP و جلوگیری از اشتباهات رایج را بررسی خواهیم کرد.

این مقاله برای توسعه‌دهندگانی که وظایف را از طریق AWS Lambda اتوماسیون می‌کنند طراحی شده است: پارس کردن داده‌ها از وب‌سایت‌های محافظت‌شده، نظارت بر قیمت‌های رقباء، کار با API شبکه‌های اجتماعی یا بازارها. شما مثال‌های کد آماده‌ای در Python و Node.js دریافت خواهید کرد که می‌توانید بلافاصله پس از خواندن از آن‌ها استفاده کنید.

چرا به پروکسی در AWS Lambda نیاز داریم

AWS Lambda به‌طور پیش‌فرض از آدرس‌های IP موجود در استخر خدمات وب آمازون استفاده می‌کند. این آدرس‌ها در فهرست‌های عمومی قرار دارند و به راحتی توسط سیستم‌های محافظت از ربات‌ها شناسایی می‌شوند. در اینجا سناریوهای اصلی وجود دارد که در آن‌ها پروکسی‌ها ضروری می‌شوند:

مورد واقعی: یک توسعه‌دهنده Lambda را برای نظارت بر قیمت‌ها در Wildberries هر 15 دقیقه تنظیم کرد. پس از 2 روز، بازار شروع به بازگشت خطای 403 Forbidden کرد — IP AWS در لیست سیاه قرار گرفت. پس از اتصال پروکسی‌های مقیم، پارس کردن به‌طور پایدار برای 6 ماه ادامه داشت.

دلایل اصلی استفاده از پروکسی در Lambda:

  • پارس کردن وب‌سایت‌های محافظت‌شده: بسیاری از وب‌سایت‌ها درخواست‌ها را از IP‌های مراکز داده AWS مسدود می‌کنند. پروکسی‌ها به پنهان کردن Lambda به عنوان کاربران عادی کمک می‌کنند.
  • محدودیت‌های جغرافیایی: اگر نیاز دارید داده‌هایی را از وب‌سایتی که فقط از یک کشور خاص قابل دسترسی است (مثلاً قیمت‌های منطقه‌ای در Ozon) دریافت کنید، پروکسی‌هایی با جغرافیای مناسب این مشکل را حل می‌کنند.
  • دور زدن محدودیت نرخ: API بسیاری از خدمات تعداد درخواست‌ها را از یک IP محدود می‌کنند. چرخش پروکسی‌ها به توزیع بار کمک می‌کند.
  • آزمون A/B تبلیغات: بررسی نمایش تبلیغات از مناطق مختلف برای تحلیل رقبا.
  • نظارت بر بازارها: پیگیری موقعیت محصولات، قیمت‌های رقباء در Wildberries، Ozon، Avito بدون مسدودسازی.

توابع Lambda اغلب بر اساس زمان‌بندی (از طریق CloudWatch Events) یا محرک‌ها اجرا می‌شوند که آن‌ها را به ابزاری ایده‌آل برای اتوماسیون تبدیل می‌کند. با این حال، بدون پروکسی، چنین وظایفی به سرعت با مسدودسازی منابع هدف مواجه می‌شوند.

کدام نوع پروکسی را برای Lambda انتخاب کنیم

انتخاب نوع پروکسی به وظیفه‌ای که تابع Lambda شما حل می‌کند بستگی دارد. سه نوع اصلی و کاربرد آن‌ها در معماری بدون سرور را بررسی می‌کنیم:

نوع پروکسی سرعت ناشناس بودن بهترین سناریوها برای Lambda
پروکسی مراکز داده بسیار بالا (50-200 میلی‌ثانیه) متوسط پارس کردن API بدون حفاظت شدید، بررسی‌های انبوه دسترسی به وب‌سایت‌ها، نظارت SEO
پروکسی‌های مقیم متوسط (300-800 میلی‌ثانیه) بسیار بالا پارس کردن وب‌سایت‌های محافظت‌شده (بازارها، شبکه‌های اجتماعی)، دور زدن Cloudflare، کار با API اینستاگرام/Facebook
پروکسی‌های موبایل متوسط (400-1000 میلی‌ثانیه) حداکثر کار با API‌های موبایل (TikTok، Instagram)، آزمایش تبلیغات موبایل، دور زدن سخت‌ترین محافظت‌ها

توصیه‌ها برای انتخاب:

  • برای پارس کردن Wildberries، Ozon، Avito: از پروکسی‌های مقیم با جغرافیای روسیه استفاده کنید. این پلتفرم‌ها به‌طور فعال IP‌های مراکز داده را مسدود می‌کنند.
  • برای نظارت بر API بدون حفاظت شدید: پروکسی‌های مراکز داده کافی هستند، آن‌ها ارزان‌تر و سریع‌تر هستند.
  • برای کار با API اینستاگرام، Facebook، TikTok: فقط پروکسی‌های موبایل یا مقیم — این پلتفرم‌ها مراکز داده را شناسایی و مسدود می‌کنند.
  • برای دور زدن Cloudflare، PerimeterX: پروکسی‌های مقیم با چرخش، ترجیحاً با جلسات چسبنده (حفظ IP به مدت 5-30 دقیقه).

مهم: توابع Lambda محدودیت زمانی برای اجرا دارند (حداکثر 15 دقیقه). هنگام استفاده از پروکسی‌های کند (مقیم/موبایل) تأخیرها را در نظر بگیرید — اگر درخواست از طریق پروکسی 2 ثانیه طول بکشد، در 15 دقیقه حداکثر ~450 درخواست می‌توانید انجام دهید.

تنظیم پروکسی در Lambda با Python (requests، urllib3)

Python محبوب‌ترین زبان برای توابع Lambda است، به‌ویژه برای وظایف پارس کردن و اتوماسیون. بیایید تنظیم پروکسی را با کتابخانه requests که در 90% موارد استفاده می‌شود، بررسی کنیم.

تنظیمات پایه پروکسی HTTP

ساده‌ترین راه برای اتصال پروکسی — انتقال پارامتر proxies به متد requests.get() است:

import requests
import os

def lambda_handler(event, context):
    # دریافت اعتبارنامه‌های پروکسی از متغیرهای محیطی
    proxy_host = os.environ['PROXY_HOST']  # به عنوان مثال: proxy.example.com
    proxy_port = os.environ['PROXY_PORT']  # به عنوان مثال: 8080
    proxy_user = os.environ['PROXY_USER']
    proxy_pass = os.environ['PROXY_PASS']
    
    # تشکیل URL پروکسی با احراز هویت
    proxy_url = f"http://{proxy_user}:{proxy_pass}@{proxy_host}:{proxy_port}"
    
    proxies = {
        'http': proxy_url,
        'https': proxy_url
    }
    
    try:
        # انجام درخواست از طریق پروکسی
        response = requests.get(
            'https://api.example.com/data',
            proxies=proxies,
            timeout=10  # مهم! حتماً تایم‌اوت را تنظیم کنید
        )
        
        return {
            'statusCode': 200,
            'body': response.text
        }
    
    except requests.exceptions.ProxyError as e:
        print(f"خطای پروکسی: {e}")
        return {
            'statusCode': 500,
            'body': 'اتصال پروکسی ناموفق بود'
        }
    
    except requests.exceptions.Timeout as e:
        print(f"خطای تایم‌اوت: {e}")
        return {
            'statusCode': 504,
            'body': 'تایم‌اوت درخواست'
        }

نکات کلیدی این کد:

  • متغیرهای محیطی: هرگز اعتبارنامه‌های پروکسی را مستقیماً در کد ذخیره نکنید! از متغیرهای محیطی در تنظیمات Lambda استفاده کنید.
  • تایم‌اوت: حتماً تایم‌اوت (10-30 ثانیه) را تنظیم کنید. بدون آن، Lambda ممکن است تا زمان اتمام حداکثر زمان اجرا متوقف شود.
  • مدیریت خطا: پروکسی‌ها ممکن است در دسترس نباشند یا کند باشند — همیشه استثناهای ProxyError و Timeout را مدیریت کنید.
  • HTTP و HTTPS: هر دو پروتکل را در دیکشنری proxies مشخص کنید، حتی اگر فقط از HTTPS استفاده می‌کنید.

تنظیم پروکسی SOCKS5

پروکسی‌های SOCKS5 سطح بالاتری از ناشناس بودن را فراهم می‌کنند و در سطح TCP کار می‌کنند، که آن‌ها را برای برخی سیستم‌های محافظتی نامحسوس می‌کند. برای کار با SOCKS5 در requests به کتابخانه requests[socks] نیاز دارید:

import requests
import os

def lambda_handler(event, context):
    proxy_host = os.environ['PROXY_HOST']
    proxy_port = os.environ['PROXY_PORT']
    proxy_user = os.environ['PROXY_USER']
    proxy_pass = os.environ['PROXY_PASS']
    
    # پروکسی SOCKS5 با احراز هویت
    proxy_url = f"socks5://{proxy_user}:{proxy_pass}@{proxy_host}:{proxy_port}"
    
    proxies = {
        'http': proxy_url,
        'https': proxy_url
    }
    
    try:
        response = requests.get(
            'https://www.wildberries.ru/catalog/12345/detail.aspx',
            proxies=proxies,
            timeout=15
        )
        
        # پارس کردن داده‌ها
        return {
            'statusCode': 200,
            'body': response.text
        }
    
    except Exception as e:
        print(f"خطا: {e}")
        return {
            'statusCode': 500,
            'body': str(e)
        }

مهم برای استقرار در Lambda: هنگام استفاده از SOCKS5، در requirements.txt اضافه کنید:

requests[socks]
PySocks

بررسی IP از طریق پروکسی

قبل از اجرای منطق اصلی، مفید است که بررسی کنید که پروکسی کار می‌کند و IP مورد نظر را برمی‌گرداند:

def check_proxy_ip(proxies):
    """بررسی IP که جهان خارجی از طریق پروکسی می‌بیند"""
    try:
        response = requests.get(
            'https://api.ipify.org?format=json',
            proxies=proxies,
            timeout=10
        )
        ip_data = response.json()
        print(f"IP فعلی از طریق پروکسی: {ip_data['ip']}")
        return ip_data['ip']
    except Exception as e:
        print(f"بررسی پروکسی ناموفق بود: {e}")
        return None

def lambda_handler(event, context):
    # ... تنظیم پروکسی ...
    
    # بررسی IP قبل از کار اصلی
    current_ip = check_proxy_ip(proxies)
    if not current_ip:
        return {
            'statusCode': 500,
            'body': 'بررسی پروکسی ناموفق بود'
        }
    
    # منطق اصلی پارس کردن
    # ...

تنظیم پروکسی در Lambda با Node.js (axios، got)

Node.js دومین زبان محبوب برای توابع Lambda است، به‌ویژه زمانی که به عملکرد بالا در کار با API نیاز دارید. بیایید تنظیم پروکسی را با کتابخانه‌های axios و got بررسی کنیم.

تنظیم با axios

Axios محبوب‌ترین کتابخانه HTTP برای Node.js است. برای کار با پروکسی به بسته اضافی https-proxy-agent نیاز دارید:

const axios = require('axios');
const HttpsProxyAgent = require('https-proxy-agent');

exports.handler = async (event) => {
    // دریافت اعتبارنامه‌ها از متغیرهای محیطی
    const proxyHost = process.env.PROXY_HOST;
    const proxyPort = process.env.PROXY_PORT;
    const proxyUser = process.env.PROXY_USER;
    const proxyPass = process.env.PROXY_PASS;
    
    // تشکیل URL پروکسی
    const proxyUrl = `http://${proxyUser}:${proxyPass}@${proxyHost}:${proxyPort}`;
    
    // ایجاد عامل برای پروکسی
    const agent = new HttpsProxyAgent(proxyUrl);
    
    try {
        const response = await axios.get('https://api.example.com/data', {
            httpsAgent: agent,
            timeout: 10000  // 10 ثانیه
        });
        
        return {
            statusCode: 200,
            body: JSON.stringify(response.data)
        };
    } catch (error) {
        console.error('درخواست ناموفق بود:', error.message);
        
        return {
            statusCode: 500,
            body: JSON.stringify({
                error: error.message
            })
        };
    }
};

نصب وابستگی‌ها: در package.json اضافه کنید:

{
  "dependencies": {
    "axios": "^1.6.0",
    "https-proxy-agent": "^7.0.0"
  }
}

تنظیم SOCKS5 با axios

برای پروکسی‌های SOCKS5 از بسته socks-proxy-agent استفاده کنید:

const axios = require('axios');
const { SocksProxyAgent } = require('socks-proxy-agent');

exports.handler = async (event) => {
    const proxyUrl = `socks5://${process.env.PROXY_USER}:${process.env.PROXY_PASS}@${process.env.PROXY_HOST}:${process.env.PROXY_PORT}`;
    
    const agent = new SocksProxyAgent(proxyUrl);
    
    try {
        const response = await axios.get('https://www.ozon.ru/api/products', {
            httpAgent: agent,
            httpsAgent: agent,
            timeout: 15000
        });
        
        return {
            statusCode: 200,
            body: JSON.stringify(response.data)
        };
    } catch (error) {
        console.error('خطا:', error.message);
        return {
            statusCode: 500,
            body: JSON.stringify({ error: error.message })
        };
    }
};

جایگزین: کتابخانه got

Got — کتابخانه HTTP مدرن با پشتیبانی بومی از پروکسی (نیاز به عوامل جداگانه ندارد):

const got = require('got');

exports.handler = async (event) => {
    const proxyUrl = `http://${process.env.PROXY_USER}:${process.env.PROXY_PASS}@${process.env.PROXY_HOST}:${process.env.PROXY_PORT}`;
    
    try {
        const response = await got('https://api.example.com/data', {
            agent: {
                http: new (require('http-proxy-agent'))(proxyUrl),
                https: new (require('https-proxy-agent'))(proxyUrl)
            },
            timeout: {
                request: 10000
            },
            responseType: 'json'
        });
        
        return {
            statusCode: 200,
            body: JSON.stringify(response.body)
        };
    } catch (error) {
        console.error('خطا:', error.message);
        return {
            statusCode: 500,
            body: JSON.stringify({ error: error.message })
        };
    }
};

چرخش پروکسی در Lambda: چگونه IP را به‌طور خودکار تغییر دهیم

چرخش پروکسی برای وظایفی که نیاز به انجام درخواست‌های زیاد بدون مسدودسازی دارند، به شدت مهم است. دو رویکرد اصلی وجود دارد: استفاده از خدمات پروکسی با چرخش خودکار یا مدیریت دستی استخر پروکسی.

چرخش خودکار از طریق ارائه‌دهنده

بیشتر ارائه‌دهندگان پروکسی‌های مقیم (از جمله ProxyCove) نقطه پایانی با چرخش خودکار ارائه می‌دهند — هر درخواست یا هر N دقیقه IP به‌طور خودکار تغییر می‌کند:

import requests
import os

def lambda_handler(event, context):
    # پروکسی با چرخش خودکار
    # فرمت: rotating.proxy.com:port
    # هر درخواست = IP جدید
    proxy_url = f"http://{os.environ['PROXY_USER']}:{os.environ['PROXY_PASS']}@rotating.proxycove.com:8080"
    
    proxies = {
        'http': proxy_url,
        'https': proxy_url
    }
    
    results = []
    
    # انجام 10 درخواست — هر کدام با IP جدید
    for i in range(10):
        try:
            response = requests.get(
                f'https://api.wildberries.ru/products/{i}',
                proxies=proxies,
                timeout=10
            )
            results.append({
                'product_id': i,
                'status': response.status_code,
                'data': response.json()
            })
        except Exception as e:
            results.append({
                'product_id': i,
                'error': str(e)
            })
    
    return {
        'statusCode': 200,
        'body': json.dumps(results)
    }

چرخش دستی از استخر پروکسی

اگر لیستی از پروکسی‌ها دارید، می‌توانید چرخش را به‌صورت دستی پیاده‌سازی کنید. این برای زمانی مفید است که نیاز به کنترل بر روی اینکه کدام پروکسی برای هر درخواست استفاده می‌شود دارید:

import requests
import random
import json

def lambda_handler(event, context):
    # لیست پروکسی‌ها (می‌توان در DynamoDB یا S3 ذخیره کرد)
    proxy_pool = [
        {
            'host': 'proxy1.example.com',
            'port': '8080',
            'user': 'user1',
            'pass': 'pass1'
        },
        {
            'host': 'proxy2.example.com',
            'port': '8080',
            'user': 'user2',
            'pass': 'pass2'
        },
        {
            'host': 'proxy3.example.com',
            'port': '8080',
            'user': 'user3',
            'pass': 'pass3'
        }
    ]
    
    results = []
    
    for i in range(10):
        # انتخاب یک پروکسی تصادفی از استخر
        proxy = random.choice(proxy_pool)
        proxy_url = f"http://{proxy['user']}:{proxy['pass']}@{proxy['host']}:{proxy['port']}"
        
        proxies = {
            'http': proxy_url,
            'https': proxy_url
        }
        
        try:
            response = requests.get(
                f'https://api.example.com/item/{i}',
                proxies=proxies,
                timeout=10
            )
            results.append({
                'item': i,
                'proxy_used': proxy['host'],
                'status': response.status_code
            })
        except Exception as e:
            results.append({
                'item': i,
                'proxy_used': proxy['host'],
                'error': str(e)
            })
    
    return {
        'statusCode': 200,
        'body': json.dumps(results)
    }

جلسات چسبنده برای حفظ IP

برخی وظایف نیاز به حفظ یک IP در طول جلسه دارند (به عنوان مثال، احراز هویت در وب‌سایت). ارائه‌دهندگان پروکسی جلسات چسبنده را از طریق پارامتر در URL ارائه می‌دهند:

import requests
import uuid

def lambda_handler(event, context):
    # ایجاد یک session_id منحصر به فرد
    session_id = str(uuid.uuid4())
    
    # پروکسی با جلسه چسبنده (IP به مدت 10 دقیقه حفظ می‌شود)
    proxy_url = f"http://{os.environ['PROXY_USER']}-session-{session_id}:{os.environ['PROXY_PASS']}@sticky.proxycove.com:8080"
    
    proxies = {
        'http': proxy_url,
        'https': proxy_url
    }
    
    # تمام درخواست‌ها در این Lambda با یک IP انجام می‌شوند
    # 1. احراز هویت
    login_response = requests.post(
        'https://example.com/login',
        data={'user': 'test', 'pass': 'test'},
        proxies=proxies
    )
    
    # 2. دریافت داده‌ها (از همان IP استفاده می‌شود)
    data_response = requests.get(
        'https://example.com/dashboard',
        proxies=proxies,
        cookies=login_response.cookies
    )
    
    return {
        'statusCode': 200,
        'body': data_response.text
    }

ذخیره اعتبارنامه‌های پروکسی از طریق متغیرهای محیطی

هرگز اعتبارنامه‌های پروکسی (نام کاربری، رمز عبور، میزبان) را مستقیماً در کد تابع Lambda ذخیره نکنید. AWS چندین روش امن برای ذخیره داده‌های محرمانه ارائه می‌دهد:

1. متغیرهای محیطی (روش پایه)

در کنسول AWS Lambda → Configuration → Environment variables اضافه کنید:

  • PROXY_HOST = proxy.example.com
  • PROXY_PORT = 8080
  • PROXY_USER = your_username
  • PROXY_PASS = your_password

AWS به‌طور خودکار متغیرهای محیطی را در حالت استراحت رمزگذاری می‌کند. دسترسی به آن‌ها در کد:

# Python
import os
proxy_host = os.environ['PROXY_HOST']

// Node.js
const proxyHost = process.env.PROXY_HOST;

2. AWS Secrets Manager (توصیه شده برای تولید)

برای حداکثر امنیت از AWS Secrets Manager استفاده کنید — این ابزار چرخش خودکار اسرار و کنترل دقیق دسترسی را فراهم می‌کند:

import boto3
import json
from botocore.exceptions import ClientError

def get_proxy_credentials():
    secret_name = "proxy-credentials"
    region_name = "us-east-1"
    
    session = boto3.session.Session()
    client = session.client(
        service_name='secretsmanager',
        region_name=region_name
    )
    
    try:
        get_secret_value_response = client.get_secret_value(
            SecretId=secret_name
        )
        secret = json.loads(get_secret_value_response['SecretString'])
        return secret
    except ClientError as e:
        print(f"خطا در بازیابی راز: {e}")
        raise e

def lambda_handler(event, context):
    # دریافت اعتبارنامه‌ها از Secrets Manager
    creds = get_proxy_credentials()
    
    proxy_url = f"http://{creds['user']}:{creds['password']}@{creds['host']}:{creds['port']}"
    
    # استفاده از پروکسی
    # ...

مهم: فراموش نکنید که مجوزهای IAM را برای تابع Lambda خود برای دسترسی به Secrets Manager اضافه کنید:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "secretsmanager:GetSecretValue"
      ],
      "Resource": "arn:aws:secretsmanager:us-east-1:123456789:secret:proxy-credentials-*"
    }
  ]
}

اشتباهات رایج و راه‌حل‌های آن‌ها

هنگام کار با پروکسی در Lambda، توسعه‌دهندگان اغلب با مشکلات مشابهی مواجه می‌شوند. بیایید رایج‌ترین آن‌ها و راه‌حل‌هایشان را بررسی کنیم:

خطا: ProxyError / Connection timeout

علائم: requests.exceptions.ProxyError: HTTPConnectionPool(host='proxy.example.com', port=8080): Max retries exceeded

دلایل:

  • اعتبارنامه‌های پروکسی نادرست (نام کاربری/رمز عبور)
  • سرور پروکسی در دسترس نیست یا بار زیاد دارد
  • Firewall اتصالات خروجی Lambda را مسدود می‌کند
  • تایم‌اوت خیلی کوتاه است

راه‌حل:

# 1. اعتبارنامه‌ها را بررسی کنید
print(f"استفاده از پروکسی: {proxy_host}:{proxy_port}")
print(f"کاربر: {proxy_user}")

# 2. تایم‌اوت را افزایش دهید
response = requests.get(url, proxies=proxies, timeout=30)

# 3. منطق retry را اضافه کنید
from requests.adapters import HTTPAdapter
from requests.packages.urllib3.util.retry import Retry

session = requests.Session()
retry = Retry(
    total=3,
    backoff_factor=1,
    status_forcelist=[500, 502, 503, 504]
)
adapter = HTTPAdapter(max_retries=retry)
session.mount('http://', adapter)
session.mount('https://', adapter)

response = session.get(url, proxies=proxies, timeout=30)

خطا: SSL Certificate verification failed

علائم: SSLError: [SSL: CERTIFICATE_VERIFY_FAILED]

دلیل: برخی پروکسی‌ها (به‌ویژه ارزان) از گواهی‌نامه‌های SSL خودامضا استفاده می‌کنند.

راه‌حل (با احتیاط استفاده کنید!):

# غیرفعال کردن بررسی SSL (فقط برای آزمایش!)
response = requests.get(
    url,
    proxies=proxies,
    verify=False  # در تولید استفاده نکنید!
)

# بهتر: مسیر CA گواهی‌نامه را مشخص کنید
response = requests.get(
    url,
    proxies=proxies,
    verify='/path/to/ca-bundle.crt'
)

مهم: غیرفعال کردن بررسی SSL (verify=False) اتصال را در برابر حملات man-in-the-middle آسیب‌پذیر می‌کند. فقط برای اشکال‌زدایی در محیط توسعه استفاده کنید!

خطا: Lambda timeout (Task timed out after X seconds)

علائم: تابع Lambda با خطای تایم‌اوت به پایان می‌رسد، بدون اینکه منتظر پاسخ از پروکسی باشد.

دلیل: پروکسی‌های کند (به‌ویژه مقیم/موبایل) + تعداد زیاد درخواست‌ها.

راه‌حل:

  • تایم‌اوت تابع Lambda را افزایش دهید: Configuration → General configuration → Timeout (حداکثر 15 دقیقه)
  • تعداد درخواست‌ها را در یک اجرا کاهش دهید
  • از درخواست‌های غیرهمزمان استفاده کنید (asyncio در Python، Promise.all در Node.js)
  • برای وظایف غیرضروری از پروکسی‌های سریع‌تر استفاده کنید
# Python: درخواست‌های غیرهمزمان برای تسریع
import asyncio
import aiohttp

async def fetch_url(session, url, proxy):
    async with session.get(url, proxy=proxy, timeout=10) as response:
        return await response.text()

async def lambda_handler_async(event, context):
    proxy_url = f"http://{os.environ['PROXY_USER']}:{os.environ['PROXY_PASS']}@{os.environ['PROXY_HOST']}:{os.environ['PROXY_PORT']}"
    
    urls = [f'https://api.example.com/item/{i}' for i in range(50)]
    
    async with aiohttp.ClientSession() as session:
        tasks = [fetch_url(session, url, proxy_url) for url in urls]
        results = await asyncio.gather(*tasks)
    
    return {
        'statusCode': 200,
        'body': json.dumps({'count': len(results)})
    }

def lambda_handler(event, context):
    return asyncio.run(lambda_handler_async(event, context))

خطا: 407 Proxy Authentication Required

علائم: خطای HTTP 407 هنگام تلاش برای استفاده از پروکسی.

دلیل: فرمت نادرست ارسال اعتبارنامه‌ها یا پروکسی نیاز به احراز هویت IP به جای نام کاربری/رمز عبور دارد.

راه‌حل:

# فرمت URL پروکسی را بررسی کنید
# درست:
proxy_url = f"http://{user}:{password}@{host}:{port}"

# نادرست (پروتکل از دست رفته):
proxy_url = f"{user}:{password}@{host}:{port}"  # ❌

# اگر پروکسی نیاز به احراز هویت IP دارد:
# 1. IP خارجی Lambda خود را پیدا کنید (ممکن است تغییر کند!)
# 2. این IP را به لیست سفید ارائه‌دهنده پروکسی اضافه کنید
# 3. از پروکسی بدون user:pass استفاده کنید

# دریافت IP خارجی Lambda:
response = requests.get('https://api.ipify.org?format=json')
lambda_ip = response.json()['ip']
print(f"IP خارجی Lambda: {lambda_ip}")

بهینه‌سازی عملکرد Lambda با پروکسی

استفاده از پروکسی تأخیری به هر درخواست اضافه می‌کند. در اینجا روش‌های تأیید شده برای حداقل کردن تأثیر بر عملکرد آورده شده است:

1. اتصال‌های تجمعی

از اتصالات TCP مجدداً استفاده کنید به جای اینکه برای هر درخواست جدید ایجاد کنید:

# Python: از Session به جای requests.get() استفاده کنید
import requests

# یک بار session را ایجاد کنید (می‌توانید آن را خارج از handler قرار دهید)
session = requests.Session()
session.proxies = {
    'http': proxy_url,
    'https': proxy_url
}

def lambda_handler(event, context):
    # تمام درخواست‌ها از اتصالات مجدداً استفاده می‌کنند
    for i in range(100):
        response = session.get(f'https://api.example.com/item/{i}')
        # پردازش پاسخ...

2. درخواست‌های موازی

اگر نیاز به انجام درخواست‌های مستقل زیادی دارید، آن‌ها را به‌طور موازی انجام دهید:

// Node.js: درخواست‌های موازی با Promise.all
const axios = require('axios');
const HttpsProxyAgent = require('https-proxy-agent');

const agent = new HttpsProxyAgent(proxyUrl);

exports.handler = async (event) => {
    const urls = Array.from({length: 50}, (_, i) => 
        `https://api.example.com/item/${i}`
    );
    
    // تمام درخواست‌ها به‌طور موازی انجام می‌شوند
    const promises = urls.map(url => 
        axios.get(url, { 
            httpsAgent: agent,
            timeout: 10000
        })
    );
    
    try {
        const results = await Promise.all(promises);
        return {
            statusCode: 200,
            body: JSON.stringify({
                count: results.length,
                data: results.map(r => r.data)
            })
        };
    } catch (error) {
        console.error('خطا:', error.message);
        return {
            statusCode: 500,
            body: JSON.stringify({ error: error.message })
        };
    }
};

3. کش کردن نتایج

اگر داده‌ها به‌ندرت تغییر می‌کنند، نتایج را در DynamoDB یا S3 کش کنید:

import boto3
import json
import time

dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('proxy-cache')

def get_cached_or_fetch(url, proxies, cache_ttl=3600):
    """داده‌ها را از کش برمی‌گرداند یا از طریق پروکسی درخواست می‌کند"""
    
    # بررسی کش
    try:
        response = table.get_item(Key={'url': url})
        if 'Item' in response:
            item = response['Item']
            if time.time() - item['timestamp'] < cache_ttl:
                print(f"کش برای {url} پیدا شد")
                return item['data']
    except Exception as e:
        print(f"خطای کش: {e}")
    
    # کش خالی یا منقضی شده — درخواست می‌کنیم
    print(f"کش برای {url} پیدا نشد، در حال دریافت...")
    response = requests.get(url, proxies=proxies, timeout=10)
    data = response.text
    
    # ذخیره در کش
    try:
        table.put_item(Item={
            'url': url,
            'data': data,
            'timestamp': int(time.time())
        })
    except Exception as e:
        print(f"خطای ذخیره در کش: {e}")
    
    return data

4. انتخاب نوع مناسب پروکسی

مقایسه سرعت انواع مختلف پروکسی در شرایط واقعی:

نوع پروکسی تاخیر متوسط درخواست‌ها/دقیقه (Lambda 1GB RAM) توصیه
مراکز داده 50-200 میلی‌ثانیه 300-600 پارس کردن انبوه API
مقیم 300-800 میلی‌ثانیه 100-200 وب‌سایت‌های محافظت‌شده
موبایل 500-1500 میلی‌ثانیه ...
```