اگر پروکسیها در تولید استفاده میشوند — برای پارس کردن، اتوماسیون حسابهای SMM یا چندحسابی مقیاسپذیر — دیر یا زود لحظهای فرا میرسد که «به نظر کار میکند» دیگر پاسخ کافی نیست. به اعداد نیاز داریم: چند درخواست با خطا مواجه میشود، تأخیر پس از تغییر استخر IP چقدر افزایش یافته است، آیا محدودیت ترافیک از طرف ارائهدهنده تمام شده است یا خیر. 7 متریکی که باید در Prometheus جمعآوری شوند و در Grafana تجسم شوند تا مشکلات را زودتر از آنکه کاربران یا حسابهای مسدود شده آنها را ببینند، مشاهده کنیم.
اصلاً چرا باید پروکسیها را در تولید نظارت کنیم
پروکسیها یک زیرساخت ثابت مانند سرور با IP ثابت نیستند. این یک استخر آدرس در حال تغییر است که رفتار آن بستگی به ارائهدهنده، بار، منطقه و حتی زمان روز دارد. بدون نظارت، شما فقط زمانی از مشکل مطلع میشوید که پارسر Wildberries یا Ozon دیگر دادهها را ارائه نمیدهد، حساب تبلیغاتی Facebook Ads حساب را مسدود میکند، یا اسکریپت اتوماسیون Instagram شروع به ارسال CAPTCHA میکند.
هدف نظارت این است که «چیزی درست نیست» را به اعداد مشخص تبدیل کند: سهم خطاها از 2% به 15% در ساعت گذشته افزایش یافته است، تأخیر متوسط سه برابر شده است، ترافیک از یک پروکسی از حد مجاز فراتر رفته است. این امکان را میدهد که قبل از اینکه مشکل بحرانی شود، واکنش نشان دهیم — به طور خودکار استخر را تغییر دهیم، ارائهدهنده را عوض کنیم یا فرکانس درخواستها را کاهش دهیم.
برای جمعآوری متریکها از ترکیب Prometheus (ذخیرهسازی سریهای زمانی) + Grafana (تجسم و هشدارها) استفاده میکنیم. این یک استک استاندارد در DevOps است که به راحتی با هر زبانی — Python، Node.js، Go — ادغام میشود. در زیر، مثالهایی در Python با کتابخانه prometheus_client آورده شده است، اما اصل آن عمومی است.
متریک 1: نرخ موفقیت — سهم درخواستهای موفق
این متریک پایهای است که اولین علامتدهی به مشکلات با استخر پروکسی است. به عنوان نسبت درخواستهای با کد پاسخ 200-299 به مجموع درخواستها در یک دوره زمانی محاسبه میشود. کاهش نرخ موفقیت به زیر 90% معمولاً به این معنی است که بخشی از IP در استخر توسط سایت هدف مسدود شده است یا ارائهدهنده آدرسهای ناپایدار ارائه میدهد.
مثال ابزارسازی در Python:
from prometheus_client import Counter, start_http_server
import requests
REQUESTS_TOTAL = Counter(
'proxy_requests_total', 'تعداد کل درخواستها از طریق پروکسی',
['proxy_pool', 'status']
)
def fetch_with_proxy(url, proxy, pool_name="residential"):
try:
resp = requests.get(url, proxies={"http": proxy, "https": proxy}, timeout=10)
status = "success" if resp.status_code < 300 else "failure"
except requests.exceptions.RequestException:
status = "failure"
REQUESTS_TOTAL.labels(proxy_pool=pool_name, status=status).inc()
start_http_server(9100) # نقطه پایانی برای Prometheus scrape
درخواست PromQL برای محاسبه نرخ موفقیت در 5 دقیقه گذشته:
sum(rate(proxy_requests_total{status="success"}[5m]))
/
sum(rate(proxy_requests_total[5m])) * 100
اگر شما با چند نوع پروکسی به طور همزمان کار میکنید — به عنوان مثال، پروکسیهای مسکونی برای شبکههای اجتماعی و پروکسیهای مرکز داده برای پارس کردن — منطقی است که نرخ موفقیت را بر اساس برچسب proxy_pool تقسیم کنید تا ببینید کدام استخر واقعاً دچار افت کیفیت شده است.
متریک 2: تأخیر — تأخیر پاسخ
تأخیر نشان میدهد که پروکسی چقدر سریع پاسخ میدهد. افزایش ناگهانی تأخیر اغلب پیش از کاهش نرخ موفقیت رخ میدهد — ارائهدهنده تحت بار است، یا IP نزدیک به مسدود شدن است و سرور هدف شروع به کند کردن پاسخها به طور عمدی میکند. برای تأخیر مهم است که نه تنها میانگین را جمعآوری کنیم، بلکه پرسنطیلها — p50، p95، p99 — را نیز جمعآوری کنیم، زیرا میانگین تأخیرهای انتهایی را پنهان میکند که واقعاً بر عملکرد تأثیر میگذارد.
from prometheus_client import Histogram
import time
REQUEST_DURATION = Histogram(
'proxy_request_duration_seconds',
'مدت زمان درخواست از طریق پروکسی',
['proxy_pool'],
buckets=[0.1, 0.25, 0.5, 1, 2, 5, 10]
)
def fetch_timed(url, proxy, pool_name="mobile"):
start = time.time()
try:
requests.get(url, proxies={"http": proxy, "https": proxy}, timeout=10)
finally:
REQUEST_DURATION.labels(proxy_pool=pool_name).observe(time.time() - start)
PromQL برای p95 تأخیر:
histogram_quantile(0.95,
sum(rate(proxy_request_duration_seconds_bucket[5m])) by (le, proxy_pool)
)
برای وظایفی که سرعت حیاتی است — به عنوان مثال، در اتوماسیون تبلیغات TikTok، جایی که هر ثانیه برای بارگذاری صفحه خطر تایماوت را در مرورگر ضد شناسایی افزایش میدهد — بهتر است هشدار را برای p95 بالای 3-4 ثانیه تنظیم کنید.
متریک 3: نرخ خطا بر اساس نوع خطاها
فقط موفقیت/شکست برای تشخیص کافی نیست. باید خطاها را بر اساس نوع آنها تقسیم کنیم: 407 (نیاز به تأیید پروکسی) به معنای مشکل با احراز هویت است، 429 (تعداد درخواستها بیش از حد) — تجاوز از حد مجاز درخواستها، تایماوتها — مشکل شبکه، 403 — مسدود شدن به دلیل حفاظت ضد ربات سایت هدف. هر نوع خطا نیاز به واکنش متفاوتی دارد.
ERROR_BY_TYPE = Counter(
'proxy_errors_total', 'خطاهای پروکسی بر اساس نوع',
['proxy_pool', 'error_type']
)
def classify_error(resp=None, exc=None):
if exc:
if isinstance(exc, requests.exceptions.Timeout):
return "timeout"
return "connection_error"
if resp.status_code == 407:
return "auth_error"
if resp.status_code == 429:
return "rate_limited"
if resp.status_code == 403:
return "blocked_by_target"
return "other"
جدول خطاهای متداول و دلایل آنها:
| کد/نوع | دلیل احتمالی | چه چیزی را بررسی کنیم |
|---|---|---|
| 407 | اعتبارنامههای نادرست یا جلسه منقضی شده | نام کاربری/گذرواژه پروکسی، فرمت رشته اتصال |
| 429 | تعداد درخواستها بر روی IP فراتر رفته است | فرکانس درخواستها، اندازه استخر |
| 403 | حفاظت ضد ربات سایت هدف | User-Agent، اثر انگشت، نوع پروکسی |
| timeout | بارگذاری بیش از حد ارائهدهنده یا شبکه | بار بر روی استخر، تنظیمات تایماوت کلاینت |
متریک 4: سرعت چرخش و ماندگاری IP
اگر از پروکسیهای چرخشی استفاده میکنید، مهم است که بدانید IP چقدر به طور مکرر تغییر میکند و چند درخواست قبل از اینکه آدرس «بسوزد» (توسط سایت هدف مسدود شود) میتواند عبور کند. این متریک به ویژه برای چندحسابی حیاتی است — به عنوان مثال، در فارم کردن حسابهای Facebook Ads از طریق Dolphin Anty یا AdsPower، جایی که تغییر زودهنگام IP میتواند جلسه را قطع کرده و بررسی امنیتی را فعال کند.
from prometheus_client import Gauge
IP_LIFETIME = Gauge(
'proxy_ip_lifetime_seconds', 'زمان زندگی IP قبل از چرخش',
['proxy_pool']
)
IP_REQUESTS_BEFORE_BAN = Histogram(
'proxy_requests_before_ban',
'چند درخواست قبل از مسدود شدن IP عبور کرده است',
['proxy_pool'],
buckets=[10, 50, 100, 500, 1000, 5000]
)
برای پروکسیهای موبایل، این متریک به گونهای متفاوت از پروکسیهای مسکونی عمل میکند — چرخش از طریق تغییر ایستگاه پایه اپراتور IPهای «پاکتر» با احتمال کمتری برای مسدود شدن ارائه میدهد. اگر وظیفه شما دقیقاً اتوماسیون SMM با حساسیت بالا به مسدود شدن است، بهتر است که ماندگاری IP را بین پروکسیهای موبایل و پروکسیهای مسکونی با دادههای واقعی از داشبورد خود مقایسه کنید و به توصیههای عمومی تکیه نکنید.
متریک 5: پهنای باند — مصرف ترافیک
بیشتر تعرفههای پروکسی بر اساس حجم ترافیک محاسبه میشوند، نه تعداد درخواستها. بدون نظارت، به راحتی میتوان لحظهای را از دست داد که محدودیت تقریباً تمام شده است — به ویژه اگر وظیفه شامل بارگذاری تصاویر یا ویدیوها باشد، به عنوان مثال هنگام پارس کردن کارتهای محصولات Wildberries با تعداد زیادی عکس.
BANDWIDTH_USED = Counter(
'proxy_bandwidth_bytes_total', 'ترافیک مصرف شده از طریق پروکسی',
['proxy_pool', 'direction'] # direction: upload/download
)
def track_bandwidth(resp, pool_name):
size = len(resp.content)
BANDWIDTH_USED.labels(proxy_pool=pool_name, direction="download").inc(size)
در داشبورد Grafana، بهتر است که نه مقدار مطلق ترافیک، بلکه سرعت مصرف آن (rate) را بسازید — این کمک میکند تا پیشبینی کنید که چه زمانی محدودیت تمام میشود و از قبل برنامهریزی کنید که ترافیک بیشتری خریداری کنید یا به استخر دیگری منتقل شوید.
متریک 6: توزیع جغرافیایی و تطابق با منطقه
برای بازاریابانی که تبلیغات را از کشورهای مختلف آزمایش میکنند و برای آربیتراژکنندگان که با هدفگذاری جغرافیایی در Google Ads یا TikTok Ads کار میکنند، حیاتی است که IP واقعاً با منطقه اعلام شده مطابقت داشته باشد. خطای جغرافیایی میتواند منجر به نمایش تبلیغات به مخاطبان نادرست یا مسدود شدن حساب به دلیل عدم تطابق تنظیمات جغرافیایی شود.
GEO_MISMATCH = Counter(
'proxy_geo_mismatch_total',
'موارد عدم تطابق جغرافیایی اعلام شده و واقعی',
['expected_country', 'actual_country']
)
def verify_geo(proxy, expected_country):
resp = requests.get("https://ipapi.co/json/", proxies={"https": proxy}, timeout=5)
actual = resp.json().get("country_code")
if actual != expected_country:
GEO_MISMATCH.labels(expected_country=expected_country, actual_country=actual).inc()
توصیه میشود که جغرافیا را نه در هر درخواست (که از نظر ترافیک و زمان هزینهبر است)، بلکه به طور دورهای — هر ساعت بر روی نمونهای از IP از استخر، که برای اطمینان آماری کافی است، بررسی کنید.
متریک 7: اتصالات همزمان — جلسات موازی
تعداد اتصالات همزمان از طریق پروکسی بار واقعی بر روی استخر را نشان میدهد. اگر تعداد جلسات موازی بیشتر از IPهایی باشد که استخر میتواند بدون افت کیفیت پردازش کند، این مستقیماً به افزایش تأخیر و نرخ خطا از بندهای قبلی منجر میشود. این متریک به ویژه در مقیاسپذیری مهم است — زمانی که یک آژانس SMM تعداد حسابهای مشتریان فعال را از 10 به 50 افزایش میدهد.
from prometheus_client import Gauge
ACTIVE_CONNECTIONS = Gauge(
'proxy_active_connections', 'اتصالات فعال فعلی از طریق پروکسی',
['proxy_pool']
)
def on_request_start(pool_name):
ACTIVE_CONNECTIONS.labels(proxy_pool=pool_name).inc()
def on_request_end(pool_name):
ACTIVE_CONNECTIONS.labels(proxy_pool=pool_name).dec()
مقایسه این متریک با نرخ خطا در یک نمودار در Grafana به سرعت همبستگی را نشان میدهد: به محض اینکه تعداد جلسات موازی از یک آستانه خاص فراتر رود، خطاها به طور غیرخطی شروع به افزایش میکنند.
تنظیم داشبورد در Grafana: مرحله به مرحله
پس از اینکه متریکها ابزارسازی شدند و Prometheus آنها را جمعآوری کرد، باید دادهها را در Grafana تجسم کنیم. مراحل کار به شرح زیر است:
- Prometheus را به عنوان منبع داده اضافه کنید: Configuration → Data Sources → Add data source → Prometheus، URL سرور Prometheus خود را مشخص کنید (معمولاً
http://localhost:9090). - یک داشبورد جدید ایجاد کنید: Create → Dashboard → Add new panel.
- برای پنل نرخ موفقیت از درخواست PromQL از بخش متریک 1 استفاده کنید، نوع تجسم — Gauge یا Time series.
- برای تأخیر یک پنل با نوع Heatmap ایجاد کنید تا توزیع p50/p95/p99 را در زمان مشاهده کنید.
- برای نرخ خطا یک Stacked Bar Chart با تفکیک بر اساس برچسب
error_typeبسازید — این به وضوح نشان میدهد که کدام نوع خطا غالب است. - یک متغیر داشبورد (Dashboard Settings → Variables) برای
proxy_poolاضافه کنید تا بدون ایجاد داشبوردهای جداگانه بین استخرها جابجا شوید. - داشبورد را ذخیره کنید و تنظیمات خودکار بهروزرسانی هر 30 ثانیه برای نظارت نزدیک به زمان واقعی را تنظیم کنید.
JSON آماده داشبورد را میتوان از طریق Share → Export → Save to file صادر کرد و برای استخرهای مختلف پروکسی — مسکونی، موبایل و مرکز داده — مجدداً استفاده کرد و فقط مقدار متغیر را تغییر داد.
هشدارها: کی زمان عمل است
داشبورد بیفایده است اگر در زمان حادثه هیچکس به آن نگاه نکند. بنابراین تنظیم هشدارها در Grafana (Alerting → Alert rules) با آستانههای زیر که برای بیشتر سناریوهای تولید مناسب هستند، حیاتی است:
| متریک | آستانه هشدار | عمل |
|---|---|---|
| نرخ موفقیت | زیر 85% در 5 دقیقه | بررسی استخر، تغییر به پشتیبان |
| p95 تأخیر | بیشتر از 5 ثانیه | کاهش همزمانی، بررسی ارائهدهنده |
| نرخ 429 | بیشتر از 10% درخواستها | کاهش فرکانس درخواستها، افزایش استخر IP |
| نرخ پهنای باند | پیشبینی اتمام محدودیت در 24 ساعت | خرید ترافیک بیشتر یا بهینهسازی درخواستها |
بهتر است هشدارها را از طریق Telegram یا Slack از طریق webhook ارسال کنید — این واکنش فوری را تضمین میکند، نه بررسی داشبورد یک بار در روز.
نتیجهگیری
هفت متریک — نرخ موفقیت، تأخیر، نرخ خطا بر اساس نوع، ماندگاری IP، ترافیک، تطابق جغرافیایی و همزمانی اتصالات — تصویر کاملی از سلامت زیرساخت پروکسی در تولید ارائه میدهند. ترکیب Prometheus + Grafana به شما این امکان را میدهد که نه تنها مشکل را پس از وقوع ثبت کنید، بلکه روندها را ببینید و قبل از اینکه افت کیفیت استخر منجر به مسدود شدن حسابها یا توقف پارس کردن شود، واکنش نشان دهید.
انتخاب نوع پروکسی به طور مستقیم بر اینکه کدام متریکها در اولویت قرار میگیرند تأثیر میگذارد: برای وظایفی با حساسیت بالا به مسدود شدن، مانند چندحسابی در Instagram یا TikTok، بهتر است ابتدا ماندگاری IP و نرخ موفقیت را نظارت کنید، با استفاده از پروکسیهای مسکونی برای حداکثر شباهت به ترافیک واقعی کاربران. برای وظایفی که سرعت و حجم مهم است — پارس کردن انبوه Ozon، Avito یا Yandex.Market — تأخیر و پهنای باند در اولویت قرار میگیرند و در اینجا معمولاً پروکسیهای مرکز داده به دلیل ظرفیت بالاتر کارایی بیشتری دارند.