जब आप मार्केटप्लेस के हजारों पेज पार्स करते हैं, बल्क API अनुरोध भेजते हैं या सैकड़ों अकाउंट्स के साथ काम को ऑटोमेट करते हैं, तो प्रॉक्सी के माध्यम से सही लोड वितरण महत्वपूर्ण हो जाता है। उचित बैलेंसिंग के बिना आप ब्लॉकिंग, टाइमआउट और प्रदर्शन में गिरावट का सामना करेंगे। इस गाइड में हम लोड वितरण आर्किटेक्चर, बैलेंसिंग एल्गोरिदम और हाई-लोड सिस्टम के लिए व्यावहारिक रणनीतियों को समझेंगे।
यह सामग्री उन डेवलपर्स और तकनीकी विशेषज्ञों के लिए है जो डेटा पार्सिंग, API अनुरोधों के ऑटोमेशन के साथ काम करते हैं या व्यावसायिक कार्यों के लिए प्रॉक्सी के बड़े पूल का प्रबंधन करते हैं।
प्रॉक्सी के माध्यम से लोड बैलेंसिंग क्यों आवश्यक है
प्रॉक्सी के माध्यम से लोड बैलेंसिंग हाई-लोड सिस्टम की कई महत्वपूर्ण समस्याओं को हल करता है। पहली और मुख्य समस्या - ब्लॉकिंग से सुरक्षा। जब आप एक संसाधन (मार्केटप्लेस, सोशल नेटवर्क API, सर्च इंजन) को हजारों अनुरोध भेजते हैं, तो लक्ष्य सर्वर एक IP पते से असामान्य रूप से उच्च गतिविधि देखता है और इसे ब्लॉक कर देता है। दर्जनों या सैकड़ों प्रॉक्सी के बीच अनुरोधों का वितरण आपकी गतिविधि को सामान्य उपयोगकर्ताओं की क्रियाओं के समान बनाता है।
दूसरी समस्या - प्रदर्शन। एक प्रॉक्सी सर्वर की सीमित बैंडविड्थ (आमतौर पर 100-1000 Mbps) होती है और यह सीमित संख्या में समवर्ती कनेक्शन संभाल सकता है। प्रति मिनट 10000 पेज पार्स करते समय या बल्क API अनुरोध भेजते समय एक प्रॉक्सी सिस्टम की बाधा बन जाएगी। बैलेंसिंग पूल में नए प्रॉक्सी जोड़कर बैंडविड्थ को क्षैतिज रूप से स्केल करने की अनुमति देता है।
तीसरा कार्य - विश्वसनीयता। यदि कोई प्रॉक्सी विफल हो जाती है (तकनीकी खराबी, ब्लॉकिंग, लीज समाप्ति), तो सिस्टम स्वचालित रूप से ट्रैफ़िक को काम कर रहे प्रॉक्सी पर पुनर्निर्देशित करता है। बैलेंसिंग और health checks तंत्र के बिना एक प्रॉक्सी की विफलता पूरे सिस्टम को रोक सकती है।
वास्तविक उदाहरण: प्रतिस्पर्धियों की कीमतों की निगरानी के लिए Wildberries को पार्स करते समय आपको हर घंटे 50000 उत्पादों को प्रोसेस करना होता है। यह लगभग 14 अनुरोध प्रति सेकंड है। एक प्रॉक्सी इस लोड को संभाल लेगी, लेकिन Wildberries एक पते से 100-200 अनुरोधों के बाद IP को ब्लॉक कर देगी। 20 रेजिडेंशियल प्रॉक्सी के बीच अनुरोधों को वितरित करके, आप प्रत्येक IP पर लोड को 0.7 अनुरोध प्रति सेकंड तक कम कर देते हैं - यह एक सामान्य उपयोगकर्ता की गतिविधि जैसा दिखता है।
चौथा कारण - भौगोलिक वितरण। कई सेवाएं उपयोगकर्ता के क्षेत्र के आधार पर अलग-अलग सामग्री या कीमतें दिखाती हैं। विभिन्न देशों और शहरों से प्रॉक्सी के बीच बैलेंसिंग सभी लक्षित क्षेत्रों से एक साथ डेटा एकत्र करने की अनुमति देता है। उदाहरण के लिए, Ozon पर कीमतों की निगरानी के लिए आपको मॉस्को, सेंट पीटर्सबर्ग, येकातेरिनबर्ग और अन्य प्रमुख शहरों से प्रॉक्सी की आवश्यकता है।
लोड वितरण सिस्टम की आर्किटेक्चर
प्रॉक्सी के माध्यम से लोड बैलेंसिंग सिस्टम की क्लासिक आर्किटेक्चर कई घटकों से बनी होती है। शीर्ष स्तर पर बैलेंसर (load balancer) होता है - एक सॉफ्टवेयर मॉड्यूल जो आने वाले कार्यों (पार्सिंग अनुरोध, API कॉल) को स्वीकार करता है और उन्हें उपलब्ध प्रॉक्सी के बीच वितरित करता है। बैलेंसर एक अलग सेवा के रूप में काम कर सकता है या एप्लिकेशन में एम्बेडेड हो सकता है।
दूसरा घटक - प्रॉक्सी पूल मैनेजर। यह सभी उपलब्ध प्रॉक्सी की सूची उनकी विशेषताओं के साथ संग्रहीत करता है: IP पता, पोर्ट, प्रोटोकॉल (HTTP/SOCKS5), भौगोलिक स्थान, प्रकार (रेजिडेंशियल, मोबाइल, डेटा सेंटर), वर्तमान स्थिति (सक्रिय, ब्लॉक, जांच में)। पूल मैनेजर नए प्रॉक्सी जोड़ने, काम न करने वाले को हटाने और उपलब्धता की आवधिक जांच के लिए जिम्मेदार है।
तीसरा तत्व - मॉनिटरिंग और health checks सिस्टम। यह लगातार प्रत्येक प्रॉक्सी की कार्यक्षमता की जांच करता है: परीक्षण अनुरोध भेजता है, प्रतिक्रिया समय मापता है, कनेक्शन की सफलता की जांच करता है। यदि प्रॉक्सी प्रतिक्रिया नहीं देती या त्रुटियां लौटाती है, तो सिस्टम इसे अनुपलब्ध के रूप में चिह्नित करता है और अस्थायी रूप से रोटेशन से बाहर कर देता है।
| घटक | कार्य | तकनीकें |
|---|---|---|
| Load Balancer | प्रॉक्सी के बीच अनुरोधों का वितरण | HAProxy, Nginx, Python/Node.js लाइब्रेरी |
| Proxy Pool Manager | प्रॉक्सी सूची का प्रबंधन | Redis, PostgreSQL, in-memory स्टोरेज |
| Health Check System | प्रॉक्सी उपलब्धता की जांच | Scheduled tasks, Celery, cron |
| Rate Limiter | अनुरोध आवृत्ति नियंत्रण | Token bucket, leaky bucket एल्गोरिदम |
| Monitoring & Metrics | प्रदर्शन मेट्रिक्स संग्रह | Prometheus, Grafana, ELK Stack |
चौथा घटक - rate limiter (अनुरोध आवृत्ति सीमक)। यह सुनिश्चित करता है कि प्रत्येक प्रॉक्सी लक्ष्य संसाधन के लिए स्वीकार्य अनुरोध आवृत्ति से अधिक न हो। उदाहरण के लिए, यदि आप Instagram पार्स करते हैं और जानते हैं कि प्लेटफ़ॉर्म प्रति मिनट 60 अनुरोधों के बाद IP को ब्लॉक करता है, तो rate limiter एक प्रॉक्सी के माध्यम से प्रति मिनट 50 से अधिक अनुरोध भेजने की अनुमति नहीं देगा, सुरक्षा मार्जिन छोड़ते हुए।
पांचवां तत्व - मेट्रिक्स और एनालिटिक्स सिस्टम। यह प्रत्येक प्रॉक्सी के प्रदर्शन के बारे में डेटा एकत्र करता है: सफल अनुरोधों की संख्या, त्रुटियों की संख्या, औसत प्रतिक्रिया समय, ब्लॉकिंग का प्रतिशत। इस डेटा का उपयोग बैलेंसिंग एल्गोरिदम को अनुकूलित करने और समस्याग्रस्त प्रॉक्सी की पहचान करने के लिए किया जाता है।
बैलेंसिंग एल्गोरिदम: Round Robin, Least Connections, Weighted
Round Robin एल्गोरिदम - सबसे सरल और सामान्य बैलेंसिंग विधि। यह सूची से प्रॉक्सी को क्रमिक रूप से चुनता है: पहला अनुरोध प्रॉक्सी #1 के माध्यम से जाता है, दूसरा प्रॉक्सी #2 के माध्यम से, तीसरा प्रॉक्सी #3 के माध्यम से, और इसी तरह। जब सूची समाप्त होती है, तो बैलेंसर शुरुआत में वापस आ जाता है। यह एल्गोरिदम समान रूप से लोड वितरित करता है, यदि सभी प्रॉक्सी का प्रदर्शन समान हो।
class RoundRobinBalancer:
def __init__(self, proxies):
self.proxies = proxies
self.current_index = 0
def get_next_proxy(self):
proxy = self.proxies[self.current_index]
self.current_index = (self.current_index + 1) % len(self.proxies)
return proxy
# उपयोग
proxies = [
"http://proxy1.example.com:8080",
"http://proxy2.example.com:8080",
"http://proxy3.example.com:8080"
]
balancer = RoundRobinBalancer(proxies)
for i in range(10):
proxy = balancer.get_next_proxy()
print(f"Request {i+1} → {proxy}")
Least Connections (न्यूनतम कनेक्शन) एल्गोरिदम वर्तमान समय में न्यूनतम सक्रिय कनेक्शन वाली प्रॉक्सी का चयन करता है। यह तब उपयोगी है जब अनुरोधों का निष्पादन समय अलग-अलग हो। उदाहरण के लिए, पार्सिंग करते समय एक अनुरोध 100 ms में प्रोसेस हो सकता है, और दूसरा - 5 सेकंड में (यदि पेज धीरे लोड होता है)। Least Connections स्वचालित रूप से नए अनुरोधों को कम लोडेड प्रॉक्सी पर निर्देशित करता है।
class LeastConnectionsBalancer:
def __init__(self, proxies):
self.proxies = {proxy: 0 for proxy in proxies}
def get_next_proxy(self):
# न्यूनतम कनेक्शन वाली प्रॉक्सी चुनें
proxy = min(self.proxies.items(), key=lambda x: x[1])[0]
self.proxies[proxy] += 1
return proxy
def release_proxy(self, proxy):
# अनुरोध पूर्ण होने पर काउंटर घटाएं
self.proxies[proxy] -= 1
# कॉन्टेक्स्ट मैनेजर के साथ उपयोग
balancer = LeastConnectionsBalancer(proxies)
def make_request(url):
proxy = balancer.get_next_proxy()
try:
# चयनित प्रॉक्सी के माध्यम से अनुरोध निष्पादित करें
response = requests.get(url, proxies={"http": proxy})
return response
finally:
balancer.release_proxy(proxy)
Weighted Round Robin (भारित चक्रीय चयन) क्लासिक Round Robin को विस्तारित करता है, प्रत्येक प्रॉक्सी को उसके प्रदर्शन या गुणवत्ता के आधार पर वजन प्रदान करता है। अधिक वजन वाली प्रॉक्सी अधिक अनुरोध प्राप्त करती हैं। यह तब उपयोगी है जब आपके पास विभिन्न गुणवत्ता की प्रॉक्सी हों: उदाहरण के लिए, उच्च गति वाली प्रीमियम रेजिडेंशियल प्रॉक्सी और सीमाओं वाली सस्ती डेटा सेंटर प्रॉक्सी।
class WeightedRoundRobinBalancer:
def __init__(self, weighted_proxies):
# weighted_proxies = [(proxy, weight), ...]
self.proxies = []
for proxy, weight in weighted_proxies:
# प्रॉक्सी को weight बार सूची में जोड़ें
self.proxies.extend([proxy] * weight)
self.current_index = 0
def get_next_proxy(self):
proxy = self.proxies[self.current_index]
self.current_index = (self.current_index + 1) % len(self.proxies)
return proxy
# वजन के साथ उपयोग
weighted_proxies = [
("http://premium-proxy1.com:8080", 5), # उच्च गुणवत्ता
("http://premium-proxy2.com:8080", 5),
("http://cheap-proxy1.com:8080", 2), # निम्न गुणवत्ता
("http://cheap-proxy2.com:8080", 1) # बहुत निम्न गुणवत्ता
]
balancer = WeightedRoundRobinBalancer(weighted_proxies)
Random (यादृच्छिक चयन) एल्गोरिदम उपलब्ध सूची से यादृच्छिक रूप से प्रॉक्सी का चयन करता है। यह Round Robin की तुलना में कार्यान्वयन में सरल है और बड़ी संख्या में प्रॉक्सी (100+) के साथ अच्छा काम करता है। पर्याप्त अनुरोध मात्रा पर यादृच्छिक वितरण स्वचालित रूप से संतुलित हो जाता है। नुकसान - असमान लोड की छोटी अवधि संभव है।
IP Hash - एक एल्गोरिदम जो लक्ष्य URL या अन्य पैरामीटर के हैश के आधार पर प्रॉक्सी का चयन करता है। यह गारंटी देता है कि एक ही संसाधन के अनुरोध हमेशा एक ही प्रॉक्सी के माध्यम से जाते हैं। उन साइटों के लिए उपयोगी जो सत्र का उपयोग करती हैं या एक IP से अनुरोधों के अनुक्रम की आवश्यकता होती है (उदाहरण के लिए, प्राधिकरण + डेटा प्राप्त करना)।
प्रॉक्सी पूल प्रबंधन: रोटेशन और health checks
प्रॉक्सी पूल का प्रभावी प्रबंधन प्रत्येक प्रॉक्सी की स्थिति की निरंतर निगरानी और स्वचालित रोटेशन की आवश्यकता होती है। Health check - परीक्षण अनुरोध भेजकर प्रॉक्सी की उपलब्धता की आवधिक जांच। आमतौर पर एक विश्वसनीय सेवा (उदाहरण के लिए, httpbin.org या अपना एंडपॉइंट) के लिए एक सरल GET अनुरोध का उपयोग किया जाता है, जो IP पते के बारे में जानकारी लौटाता है।
import requests
import time
from datetime import datetime
class ProxyHealthChecker:
def __init__(self, test_url="http://httpbin.org/ip", timeout=10):
self.test_url = test_url
self.timeout = timeout
def check_proxy(self, proxy_url):
"""प्रॉक्सी की कार्यक्षमता की जांच करता है"""
try:
start_time = time.time()
response = requests.get(
self.test_url,
proxies={"http": proxy_url, "https": proxy_url},
timeout=self.timeout
)
response_time = time.time() - start_time
if response.status_code == 200:
return {
"status": "healthy",
"response_time": response_time,
"timestamp": datetime.now(),
"ip": response.json().get("origin")
}
else:
return {
"status": "unhealthy",
"error": f"HTTP {response.status_code}",
"timestamp": datetime.now()
}
except requests.exceptions.Timeout:
return {
"status": "unhealthy",
"error": "timeout",
"timestamp": datetime.now()
}
except Exception as e:
return {
"status": "unhealthy",
"error": str(e),
"timestamp": datetime.now()
}
# उपयोग
checker = ProxyHealthChecker()
proxies = ["http://proxy1.com:8080", "http://proxy2.com:8080"]
for proxy in proxies:
result = checker.check_proxy(proxy)
print(f"{proxy}: {result['status']} ({result.get('response_time', 'N/A')}s)")
पूल प्रबंधन सिस्टम को स्वचालित रूप से काम न करने वाली प्रॉक्सी को अनुपलब्ध के रूप में चिह्नित करना चाहिए और आवधिक रूप से जांच दोहरानी चाहिए। सामान्य रणनीति - circuit breaker pattern: लगातार तीन असफल जांचों के बाद प्रॉक्सी को 5-10 मिनट के लिए पूल से बाहर कर दिया जाता है, फिर फिर से जांचा जाता है। यदि जांच सफल होती है, तो प्रॉक्सी सक्रिय पूल में वापस आ जाती है।
class ProxyPoolManager:
def __init__(self, health_checker, max_failures=3, cooldown_seconds=300):
self.health_checker = health_checker
self.max_failures = max_failures
self.cooldown_seconds = cooldown_seconds
self.proxies = {} # {proxy_url: ProxyInfo}
def add_proxy(self, proxy_url, metadata=None):
"""पूल में प्रॉक्सी जोड़ता है"""
self.proxies[proxy_url] = {
"url": proxy_url,
"status": "active",
"failures": 0,
"last_check": None,
"cooldown_until": None,
"metadata": metadata or {}
}
def get_active_proxies(self):
"""सक्रिय प्रॉक्सी की सूची लौटाता है"""
now = datetime.now()
active = []
for proxy_url, info in self.proxies.items():
# जांचें कि प्रॉक्सी cooldown में तो नहीं
if info["cooldown_until"] and now < info["cooldown_until"]:
continue
if info["status"] == "active":
active.append(proxy_url)
return active
def mark_failure(self, proxy_url):
"""प्रॉक्सी उपयोग के असफल प्रयास को चिह्नित करता है"""
if proxy_url not in self.proxies:
return
info = self.proxies[proxy_url]
info["failures"] += 1
if info["failures"] >= self.max_failures:
# cooldown में स्थानांतरित करें
info["status"] = "cooldown"
info["cooldown_until"] = datetime.now() + timedelta(seconds=self.cooldown_seconds)
print(f"Proxy {proxy_url} moved to cooldown until {info['cooldown_until']}")
def mark_success(self, proxy_url):
"""प्रॉक्सी के सफल उपयोग को चिह्नित करता है"""
if proxy_url not in self.proxies:
return
info = self.proxies[proxy_url]
info["failures"] = 0
info["status"] = "active"
info["cooldown_until"] = None
प्रॉक्सी रोटेशन - निश्चित अंतराल या निश्चित संख्या में अनुरोधों के बाद प्रॉक्सी के स्वचालित परिवर्तन की रणनीति। कई दृष्टिकोण हैं: समय द्वारा रोटेशन (हर 5-10 मिनट में परिवर्तन), अनुरोधों की संख्या द्वारा रोटेशन (100-500 अनुरोधों के बाद परिवर्तन), सत्रों द्वारा रोटेशन (पार्सिंग के एक सत्र के लिए एक प्रॉक्सी)। रणनीति का चयन लक्ष्य साइट की आवश्यकताओं पर निर्भर करता है।
सलाह: मार्केटप्लेस (Wildberries, Ozon) की पार्सिंग के लिए अनुरोधों की संख्या द्वारा रोटेशन इष्टतम है: एक प्रॉक्सी पर 50-100 अनुरोध, फिर परिवर्तन। सोशल नेटवर्क API (Instagram, Facebook) के साथ काम करने के लिए सत्रों द्वारा रोटेशन बेहतर है: पूरे चक्र प्राधिकरण → क्रियाएं → लॉगआउट के लिए एक प्रॉक्सी।
Rate limiting और अनुरोध आवृत्ति नियंत्रण
Rate limiting - लोड बैलेंसिंग सिस्टम का एक महत्वपूर्ण घटक। यह लक्ष्य संसाधन के लिए स्वीकार्य अनुरोध आवृत्ति से अधिक होने से रोकता है, जो प्रॉक्सी की ब्लॉकिंग का कारण बन सकता है। दो मुख्य एल्गोरिदम हैं: Token Bucket (टोकन बाल्टी) और Leaky Bucket (लीकी बाल्टी)।
Token Bucket इस प्रकार काम करता है: प्रत्येक प्रॉक्सी के पास टोकन के साथ एक आभासी "बाल्टी" होती है। प्रत्येक टोकन एक अनुरोध का अधिकार देता है। बाल्टी धीरे-धीरे निर्धारित गति से टोकन से भरती है (उदाहरण के लिए, प्रति सेकंड 10 टोकन)। बाल्टी की अधिकतम क्षमता सीमित है (उदाहरण के लिए, 50 टोकन)। जब अनुरोध आता है, तो सिस्टम टोकन की उपलब्धता की जांच करता है: यदि है - एक टोकन लेता है और अनुरोध निष्पादित करता है, यदि नहीं - नए टोकन की प्रतीक्षा करता है।
import time
from threading import Lock
class TokenBucketRateLimiter:
def __init__(self, rate, capacity):
"""
rate: प्रति सेकंड टोकन की संख्या
capacity: बाल्टी में टोकन की अधिकतम संख्या
"""
self.rate = rate
self.capacity = capacity
self.tokens = capacity
self.last_update = time.time()
self.lock = Lock()
def _add_tokens(self):
"""बीते समय के आधार पर टोकन जोड़ता है"""
now = time.time()
elapsed = now - self.last_update
new_tokens = elapsed * self.rate
self.tokens = min(self.capacity, self.tokens + new_tokens)
self.last_update = now
def acquire(self, tokens=1):
"""निर्दिष्ट संख्या में टोकन प्राप्त करने का प्रयास करता है"""
with self.lock:
self._add_tokens()
if self.tokens >= tokens:
self.tokens -= tokens
return True
return False
def wait_and_acquire(self, tokens=1):
"""टोकन की उपस्थिति की प्रतीक्षा करता है और उन्हें प्राप्त करता है"""
while not self.acquire(tokens):
# प्रतीक्षा समय की गणना करें
wait_time = (tokens - self.tokens) / self.rate
time.sleep(wait_time)
# प्रत्येक प्रॉक्सी के लिए उपयोग
proxy_limiters = {
"http://proxy1.com:8080": TokenBucketRateLimiter(rate=10, capacity=50),
"http://proxy2.com:8080": TokenBucketRateLimiter(rate=10, capacity=50)
}
def make_request_with_limit(url, proxy_url):
limiter = proxy_limiters[proxy_url]
limiter.wait_and_acquire() # टोकन की उपलब्धता की प्रतीक्षा करें
response = requests.get(url, proxies={"http": proxy_url})
return response
Leaky Bucket (लीकी बाल्टी) अलग तरह से काम करता है: अनुरोधों को एक कतार (बाल्टी) में रखा जाता है, जो स्थिर गति से "रिसता" है। यदि बाल्टी भर जाती है, तो नए अनुरोधों को अस्वीकार कर दिया जाता है या प्रतीक्षा में रखा जाता है। यह एल्गोरिदम समय के साथ अधिक समान लोड वितरण प्रदान करता है, लेकिन गतिविधि के उछाल पर देरी का कारण बन सकता है।
विभिन्न लक्ष्य प्लेटफार्मों के लिए विभिन्न सीमाओं की आवश्यकता होती है। Instagram API एक IP पर प्रति घंटे लगभग 200 अनुरोधों की अनुमति देता है (लगभग 3.3 अनुरोध प्रति मिनट)। Wildberries एक IP से प्रति मिनट 100-200 अनुरोधों के बाद ब्लॉक करता है। Google Search प्रति मिनट 10-20 अनुरोधों की अनुमति देता है। आपके rate limiting सिस्टम को इन सीमाओं को ध्यान में रखना चाहिए और सुरक्षा मार्जिन (आमतौर पर 20-30%) जोड़ना चाहिए।
| प्लेटफ़ॉर्म | अनुरोध सीमा | अनुशंसित सेटिंग |
|---|---|---|
| ~200 अनुरोध/घंटा | 2-3 अनुरोध/मिनट (मार्जिन के साथ) | |
| Wildberries | 100-200 अनुरोध/मिनट | 60-80 अनुरोध/मिनट |
| Google Search | 10-20 अनुरोध/मिनट | 8-12 अनुरोध/मिनट |
| Ozon | 50-100 अनुरोध/मिनट | 30-50 अनुरोध/मिनट |
| Facebook API | 200 अनुरोध/घंटा | 2-3 अनुरोध/मिनट |
प्रदर्शन मॉनिटरिंग और स्वचालित स्केलिंग
प्रभावी लोड बैलेंसिंग सिस्टम को मुख्य मेट्रिक्स की निरंतर निगरानी की आवश्यकता होती है। पहला मेट्रिक्स समूह - प्रॉक्सी प्रदर्शन: औसत प्रतिक्रिया समय (response time), सफल अनुरोधों का प्रतिशत (success rate), टाइमआउट की संख्या, 4xx और 5xx त्रुटियों की संख्या। यह डेटा समस्याग्रस्त प्रॉक्सी की पहचान करने और बैलेंसिंग एल्गोरिदम को अनुकूलित करने की अनुमति देता है।
class ProxyMetrics:
def __init__(self):
self.metrics = {} # {proxy_url: metrics_dict}
def record_request(self, proxy_url, response_time, status_code, success):
"""अनुरोध मेट्रिक्स रिकॉर्ड करता है"""
if proxy_url not in self.metrics:
self.metrics[proxy_url] = {
"total_requests": 0,
"successful_requests": 0,
"failed_requests": 0,
"total_response_time": 0,
"timeouts": 0,
"errors_4xx": 0,
"errors_5xx": 0
}
m = self.metrics[proxy_url]
m["total_requests"] += 1
if success:
m["successful_requests"] += 1
m["total_response_time"] += response_time
else:
m["failed_requests"] += 1
if status_code == 0: # timeout
m["timeouts"] += 1
elif 400 <= status_code < 500:
m["errors_4xx"] += 1
elif 500 <= status_code < 600:
m["errors_5xx"] += 1
def get_success_rate(self, proxy_url):
"""सफल अनुरोधों का प्रतिशत लौटाता है"""
m = self.metrics.get(proxy_url, {})
total = m.get("total_requests", 0)
if total == 0:
return 0
return (m.get("successful_requests", 0) / total) * 100
def get_avg_response_time(self, proxy_url):
"""औसत प्रतिक्रिया समय लौटाता है"""
m = self.metrics.get(proxy_url, {})
successful = m.get("successful_requests", 0)
if successful == 0:
return 0
return m.get("total_response_time", 0) / successful
def get_report(self, proxy_url):
"""प्रॉक्सी पर पूर्ण रिपोर्ट लौटाता है"""
m = self.metrics.get(proxy_url, {})
return {
"proxy": proxy_url,
"total_requests": m.get("total_requests", 0),
"success_rate": self.get_success_rate(proxy_url),
"avg_response_time": self.get_avg_response_time(proxy_url),
"timeouts": m.get("timeouts", 0),
"errors_4xx": m.get("errors_4xx", 0),
"errors_5xx": m.get("errors_5xx", 0)
}
दूसरा मेट्रिक्स समूह - सिस्टम का समग्र प्रदर्शन: प्रति सेकंड कुल अनुरोधों की संख्या (RPS — requests per second), औसत विलंबता (latency), अनुरोध कतार का आकार, सक्रिय प्रॉक्सी की संख्या, प्रॉक्सी पूल उपयोग का प्रतिशत। ये मेट्रिक्स दिखाते हैं कि सिस्टम लोड को संभाल रहा है या स्केलिंग की आवश्यकता है।
स्वचालित स्केलिंग (auto-scaling) लोड के आधार पर प्रॉक्सी को गतिशील रूप से जोड़ने या हटाने की अनुमति देती है। सरल रणनीति: यदि 5 मिनट के लिए पूल का औसत लोड 80% से अधिक है, तो सिस्टम स्वचालित रूप से नई प्रॉक्सी जोड़ता है। यदि लोड 15 मिनट के लिए 30% से नीचे गिरता है, तो सिस्टम संसाधनों की बचत के लिए अतिरिक्त प्रॉक्सी को हटा देता है।
मॉनिटरिंग सेटअप का उदाहरण: प्रति घंटे 100000 Wildberries उत्पादों की पार्सिंग के लिए (लगभग 28 अनुरोध प्रति सेकंड) आपको प्रति प्रॉक्सी 60 अनुरोध प्रति मिनट की सीमा पर कम से कम 30-40 प्रॉक्सी की आवश्यकता होगी। अलर्ट सेट करें: यदि success rate 85% से नीचे गिरती है या औसत response time 3 सेकंड से अधिक हो जाती है, तो सिस्टम को स्वचालित रूप से पूल से 10-15 रिजर्व प्रॉक्सी जोड़नी चाहिए।
मेट्रिक्स के विज़ुअलाइज़ेशन के लिए Prometheus के साथ Grafana या ELK Stack का उपयोग करें। ग्राफ़ के साथ डैशबोर्ड बनाएं: समय के अनुसार RPS, response time का वितरण, शीर्ष-10 सबसे तेज़/धीमी प्रॉक्सी, प्रकार के अनुसार त्रुटियों का मानचित्र। यह समस्याओं को जल्दी से पहचानने और सिस्टम को अनुकूलित करने की अनुमति देगा।
Python और Node.js पर व्यावहारिक कार्यान्वयन
आइए लोकप्रिय लाइब्रेरी का उपयोग करके Python पर लोड बैलेंसिंग सिस्टम का पूर्ण कार्यान्वयन देखें। यह उदाहरण सभी वर्णित घटकों को जोड़ता है: बैलेंसर, पूल मैनेजर, health checks, rate limiting और मॉनिटरिंग।
import requests
import time
import random
from datetime import datetime, timedelta
from threading import Lock, Thread
from collections import defaultdict
class ProxyLoadBalancer:
def __init__(self, proxies, algorithm="round_robin", rate_limit=10):
"""
proxies: प्रॉक्सी की सूची [{"url": "...", "weight": 1}, ...]
algorithm: round_robin, least_connections, weighted, random
rate_limit: प्रति प्रॉक्सी प्रति सेकंड अनुरोधों की अधिकतम संख्या
"""
self.proxies = proxies
self.algorithm = algorithm
self.rate_limit = rate_limit
# बैलेंसर की स्थिति
self.current_index = 0
self.connections = defaultdict(int)
self.rate_limiters = {}
self.metrics = defaultdict(lambda: {
"total": 0, "success": 0, "failed": 0,
"response_times": [], "last_check": None
})
# rate limiters का आरंभीकरण
for proxy in proxies:
proxy_url = proxy["url"]
self.rate_limiters[proxy_url] = TokenBucketRateLimiter(
rate=rate_limit,
capacity=rate_limit * 5
)
self.lock = Lock()
# बैकग्राउंड health check शुरू करें
self.health_check_thread = Thread(target=self._health_check_loop, daemon=True)
self.health_check_thread.start()
def get_next_proxy(self):
"""एल्गोरिदम के अनुसार अगली प्रॉक्सी का चयन करता है"""
with self.lock:
if self.algorithm == "round_robin":
return self._round_robin()
elif self.algorithm == "least_connections":
return self._least_connections()
elif self.algorithm == "weighted":
return self._weighted_random()
elif self.algorithm == "random":
return random.choice(self.proxies)["url"]
def _round_robin(self):
proxy = self.proxies[self.current_index]["url"]
self.current_index = (self.current_index + 1) % len(self.proxies)
return proxy
def _least_connections(self):
min_conn = min(self.connections.values()) if self.connections else 0
candidates = [p["url"] for p in self.proxies if self.connections[p["url"]] == min_conn]
return random.choice(candidates)
def _weighted_random(self):
weights = [p.get("weight", 1) for p in self.proxies]
return random.choices(self.proxies, weights=weights)[0]["url"]
def make_request(self, url, method="GET", **kwargs):
"""बैलेंसर के माध्यम से अनुरोध निष्पादित करता है"""
proxy_url = self.get_next_proxy()
# rate limit की उपलब्धता की प्रतीक्षा करें
self.rate_limiters[proxy_url].wait_and_acquire()
# कनेक्शन काउंटर बढ़ाएं
with self.lock:
self.connections[proxy_url] += 1
try:
start_time = time.time()
response = requests.request(
method,
url,
proxies={"http": proxy_url, "https": proxy_url},
timeout=kwargs.get("timeout", 30),
**kwargs
)
response_time = time.time() - start_time
# मेट्रिक्स रिकॉर्ड करें
self._record_metrics(proxy_url, response_time, True, response.status_code)
return response
except Exception as e:
self._record_metrics(proxy_url, 0, False, 0)
raise
finally:
# कनेक्शन काउंटर घटाएं
with self.lock:
self.connections[proxy_url] -= 1
def _record_metrics(self, proxy_url, response_time, success, status_code):
"""अनुरोध मेट्रिक्स रिकॉर्ड करता है"""
with self.lock:
m = self.metrics[proxy_url]
m["total"] += 1
if success:
m["success"] += 1
m["response_times"].append(response_time)
# केवल अंतिम 1000 मान संग्रहीत करें
if len(m["response_times"]) > 1000:
m["response_times"].pop(0)
else:
m["failed"] += 1
def _health_check_loop(self):
"""प्रॉक्सी कार्यक्षमता की बैकग्राउंड जांच"""
while True:
for proxy in self.proxies:
proxy_url = proxy["url"]
try:
response = requests.get(
"http://httpbin.org/ip",
proxies={"http": proxy_url},
timeout=10
)
with self.lock:
self.metrics[proxy_url]["last_check"] = datetime.now()
proxy["status"] = "healthy" if response.status_code == 200 else "unhealthy"
except:
with self.lock:
proxy["status"] = "unhealthy"
time.sleep(60) # हर मिनट जांच
def get_stats(self):
"""सभी प्रॉक्सी के लिए सांख्यिकी लौटाता है"""
stats = []
with self.lock:
for proxy in self.proxies:
proxy_url = proxy["url"]
m = self.metrics[proxy_url]
avg_response_time = (
sum(m["response_times"]) / len(m["response_times"])
if m["response_times"] else 0
)
success_rate = (
(m["success"] / m["total"] * 100)
if m["total"] > 0 else 0
)
stats.append({
"proxy": proxy_url,
"status": proxy.get("status", "unknown"),
"total_requests": m["total"],
"success_rate": round(success_rate, 2),
"avg_response_time": round(avg_response_time, 3),
"active_connections": self.connections[proxy_url]
})
return stats
मार्केटप्लेस पार्सिंग के लिए इस बैलेंसर का उपयोग:
# बैलेंसर सेटअप
proxies = [
{"url": "http://proxy1.example.com:8080", "weight": 5},
{"url": "http://proxy2.example.com:8080", "weight": 5},
{"url": "http://proxy3.example.com:8080", "weight": 3},
{"url": "http://proxy4.example.com:8080", "weight": 2}
]
balancer = ProxyLoadBalancer(
proxies=proxies,
algorithm="weighted",
rate_limit=60 # प्रति प्रॉक्सी प्रति मिनट 60 अनुरोध
)
# उत्पादों की सूची की पार्सिंग
product_urls = [f"https://www.wildberries.ru/catalog/{i}/detail.aspx" for i in range(1000)]
results = []
for url in product_urls:
try:
response = balancer.make_request(url)
# प्रतिक्रिया प्रोसेसिंग
results.append({"url": url, "status": "success", "data": response.text})
except Exception as e:
results.append({"url": url, "status": "error", "error": str(e)})
# हर 100 अनुरोधों पर सांख्यिकी प्रदर्शित करें
if len(results) % 100 == 0:
stats = balancer.get_stats()
for stat in stats:
print(f"{stat['proxy']}: {stat['success_rate']}% success, "
f"{stat['avg_response_time']}s avg response")
# अंतिम सांख्यिकी
print("\n=== Final Statistics ===")
for stat in balancer.get_stats():
print(f"{stat['proxy']}:")
print(f" Total requests: {stat['total_requests']}")
print(f" Success rate: {stat['success_rate']}%")
print(f" Avg response time: {stat['avg_response_time']}s")
print(f" Status: {stat['status']}")
Node.js के लिए HTTP अनुरोधों के लिए axios लाइब्रेरी और आवृत्ति नियंत्रण के लिए node-rate-limiter के साथ समान आर्किटेक्चर का उपयोग किया जा सकता है:
const axios = require('axios');
const { RateLimiter } = require('limiter');
class ProxyLoadBalancer {
constructor(proxies, algorithm = 'round_robin', rateLimit = 10) {
this.proxies = proxies;
this.algorithm = algorithm;
this.currentIndex = 0;
this.connections = new Map();
this.limiters = new Map();
this.metrics = new Map();
// rate limiters का आरंभीकरण
proxies.forEach(proxy => {
this.limiters.set(proxy.url, new RateLimiter({
tokensPerInterval: rateLimit,
interval: 'second'
}));
this.connections.set(proxy.url, 0);
this.metrics.set(proxy.url, {
total: 0,
success: 0,
failed: 0,
responseTimes: []
});
});
}
getNextProxy() {
if (this.algorithm === 'round_robin') {
const proxy = this.proxies[this.currentIndex].url;
this.currentIndex = (this.currentIndex + 1) % this.proxies.length;
return proxy;
} else if (this.algorithm === 'least_connections') {
let minConn = Infinity;
let selectedProxy = null;
this.connections.forEach((count, proxy) => {
if (count < minConn) {
minConn = count;
selectedProxy = proxy;
}
});
return selectedProxy;
}
}
async makeRequest(url, options = {}) {
const proxyUrl = this.getNextProxy();
const limiter = this.limiters.get(proxyUrl);
// rate limit की उपलब्धता की प्रतीक्षा करें
await limiter.removeTokens(1);
// कनेक्शन काउंटर बढ़ाएं
this.connections.set(proxyUrl, this.connections.get(proxyUrl) + 1);
try {
const startTime = Date.now();
const response = await axios({
url,
proxy: this.parseProxyUrl(proxyUrl),
timeout: options.timeout || 30000,
...options
});
const responseTime = (Date.now() - startTime) / 1000;
this.recordMetrics(proxyUrl, responseTime, true);
return response;
} catch (error) {
this.recordMetrics(proxyUrl, 0, false);
throw error;
} finally {
this.connections.set(proxyUrl, this.connections.get(proxyUrl) - 1);
}
}
parseProxyUrl(proxyUrl) {
const url = new URL(proxyUrl);
return {
host: url.hostname,
port: parseInt(url.port)
};
}
recordMetrics(proxyUrl, responseTime, success) {
const m = this.metrics.get(proxyUrl);
m.total++;
if (success) {
m.success++;
m.responseTimes.push(responseTime);
if (m.responseTimes.length > 1000) {
m.responseTimes.shift();
}
} else {
m.failed++;
}
}
getStats() {
const stats = [];
this.proxies.forEach(proxy => {
const m = this.metrics.get(proxy.url);
const avgResponseTime = m.responseTimes.length > 0
? m.responseTimes.reduce((a, b) => a + b, 0) / m.responseTimes.length
: 0;
const successRate = m.total > 0 ? (m.success / m.total * 100) : 0;
stats.push({
proxy: proxy.url,
totalRequests: m.total,
successRate: successRate.toFixed(2),
avgResponseTime: avgResponseTime.toFixed(3),
activeConnections: this.connections.get(proxy.url)
});
});
return stats;
}
}
// उपयोग
const proxies = [
{ url: 'http://proxy1.example.com:8080', weight: 5 },
{ url: 'http://proxy2.example.com:8080', weight: 5 }
];
const balancer = new ProxyLoadBalancer(proxies, 'round_robin', 60);
async function parseProducts() {
const urls = Array.from({ length: 1000 }, (_, i) =>
`https://www.wildberries.ru/catalog/${i}/detail.aspx`
);
for (const url of urls) {
try {
const response = await balancer.makeRequest(url);
console.log(`Success: ${url}`);
} catch (error) {
console.error(`Error: ${url} - ${error.message}`);
}
}
console.log('\n=== Statistics ===');
console.log(balancer.getStats());
}
parseProducts();
विशिष्ट कार्यों के लिए अनुकूलन: पार्सिंग, API, ऑटोमेशन
विभिन्न कार्यों के लिए विभिन्न लोड बैलेंसिंग रणनीतियों की आवश्यकता होती है। मार्केटप्लेस (Wildberries, Ozon, Avito) की पार्सिंग के लिए अनुरोधों की संख्या और भौगोलिक वितरण द्वारा रोटेशन के साथ रणनीति इष्टतम है। रूस के विभिन्न शहरों से रेजिडेंशियल प्रॉक्सी का उपयोग करें, हर 50-100 अनुरोधों पर प्रॉक्सी बदलें, मानव व्यवहार की नकल के लिए अनुरोधों के बीच यादृच्छिक देरी (1-3 सेकंड) जोड़ें।
सोशल नेटवर्क API (Instagram, Facebook, VK) के साथ काम करने के लिए एक सत्र के भीतर IP पते की स्थिरता महत्वपूर्ण है। IP Hash या sticky sessions एल्गोरिदम का उपयोग करें: एक अकाउंट के सभी अनुरोध एक ही प्रॉक्सी के माध्यम से जाने चाहिए। यह संदिग्ध भौगोलिक स्थान परिवर्तन को रोकता है, जो अकाउंट ब्लॉकिंग का कारण बन सकता है। मोबाइल प्रॉक्सी की सिफारिश की जाती है, क्योंकि सोशल नेटवर्क रेजिडेंशियल या डेटा सेंटर की तुलना में मोबाइल IP पर अधिक भरोसा करते हैं।
# Instagram के लिए sticky sessions का उदाहरण
class StickySessionBalancer:
def __init__(self, proxies):
self.proxies = proxies
self.session_map = {} # {account_id: proxy_url}
self.proxy_usage = defaultdict(int)
def get_proxy_for_account(self, account_id):
"""अकाउंट के लिए निश्चित प्रॉक्सी लौटाता है"""
if account_id in self.session_map:
return self.session_map[account_id]
# सबसे कम लोडेड प्रॉक्सी चुनें
proxy = min(self.proxies, key=lambda p: self.proxy_usage[p])
self.session_map[account_id] = proxy
self.proxy_usage[proxy] += 1
return proxy
def release_account(self, account_id):
"""अकाउंट के साथ काम पूरा होने पर प्रॉक्सी मुक्त करता है"""
if account_id in self.session_map:
proxy = self.session_map[account_id]
self.proxy_usage[proxy] -= 1
del self.session_map[account_id]
# Instagram के लिए उपयोग
balancer = StickySessionBalancer([
"http://mobile-proxy1.com:8080",
"http://mobile-proxy2.com:8080",
"http://mobile-proxy3.com:8080"
])
# प्रत्येक अकाउंट के लिए निश्चित प्रॉक्सी
accounts = ["account1", "account2", "account3"]
for account in accounts:
proxy = balancer.get_proxy_for_account(account)
print(f"Account {account} → {proxy}")
# अकाउंट के साथ काम करें
# ...
# काम पूरा होने पर प्रॉक्सी मुक्त करें
balancer.release_account(account)
Google Search या Yandex जैसे सर्च इंजन के साथ काम करने के लिए, भौगोलिक वितरण और कम अनुरोध आवृत्ति महत्वपूर्ण है। विभिन्न देशों और शहरों से प्रॉक्सी का उपयोग करें, प्रति प्रॉक्सी प्रति मिनट 8-12 अनुरोधों की सीमा निर्धारित करें, अनुरोधों के बीच 5-10 सेकंड की देरी जोड़ें। सर्च इंजन बॉट गतिविधि के प्रति बहुत संवेदनशील होते हैं और आक्रामक पार्सिंग को जल्दी ब्लॉक कर देते हैं।
ई-कॉमर्स प्लेटफ़ॉर्म (Amazon, eBay, AliExpress) के लिए, सत्र स्थिरता और कुकी प्रबंधन का संयोजन महत्वपूर्ण है। एक पार्सिंग सत्र के लिए एक प्रॉक्सी का उपयोग करें (उदाहरण के लिए, एक श्रेणी के सभी उत्पाद), कुकी को सहेजें और पुन: उपयोग करें, User-Agent और अन्य हेडर को बदलें। यह सामान्य उपयोगकर्ता व्यवहार की नकल करता है और ब्लॉकिंग के जोखिम को कम करता है।
निष्कर्ष
प्रॉक्सी के माध्यम से लोड बैलेंसिंग किसी भी हाई-लोड पार्सिंग, API ऑटोमेशन या मल्टी-अकाउंट सिस्टम का एक महत्वपूर्ण घटक है। सही आर्किटेक्चर, उपयुक्त बैलेंसिंग एल्गोरिदम, प्रभावी rate limiting और निरंतर मॉनिटरिंग आपको ब्लॉकिंग से बचने, उच्च प्रदर्शन बनाए रखने और आवश्यकतानुसार सिस्टम को स्केल करने की अनुमति देती है।
मुख्य सिद्धांत: अपने कार्य के लिए सही प्रॉक्सी प्रकार चुनें (मार्केटप्लेस के लिए रेजिडेंशियल, सोशल नेटवर्क के लिए मोबाइल, सर्च इंजन के लिए रेजिडेंशियल), लक्ष्य प्लेटफ़ॉर्म की सीमाओं के अनुसार rate limiting सेट करें, मेट्रिक्स की निगरानी करें और समस्याग्रस्त प्रॉक्सी को समय पर बदलें, आवश्यकतानुसार पूल को स्केल करें। इन सिफारिशों का पालन करके, आप एक विश्वसनीय और प्रभावी लोड बैलेंसिंग सिस्टम बना सकते हैं जो लंबे समय तक स्थिर रूप से काम करेगा।