### [代理IP并发连接老超限?TCP连接池和线程池优化五条规则](https://www.jiyueip.com/article/13579) **Published:** 2026-07-30T09:44:54 **Author:** 斑斓助理 **Excerpt:** 代理IP用在高并发场景时最常见的报错:”Too many connections”(连接数超限)、”Connection reset by peer”(对端重置连接)、”Timeout”(超时)。不是你代码写得不好,是代理IP本身有连接数上 代理IP用在高并发场景时最常见的报错:”Too many connections”(连接数超限)、”Connection reset by peer”(对端重置连接)、”Timeout”(超时)。不是你代码写得不好,是代理IP本身有连接数上限,加上TCP连接没复用导致的资源浪费。本文把几条并发优化的规则讲清楚。 ## 代理IP为什么限制并发连接 代理服务器本质上是一台中转服务器,每有一个客户端连过来、它就要维持一条到目标网站的TCP连接。一台代理服务器能同时维持的TCP连接是有限的——取决于这台服务器的内存和操作系统的文件描述符上限。 共享代理IP的并发限制更严——同一个IP可能有几十个用户在用,代理服务器要保证每个用户都有可用连接。所以你看到的”连接数超限”,不是你一个人占了太多,是整个IP上所有用户加起来超了。 天行IP的独享代理(邀请码 **blsj**,月付6元起)没有共享用户的竞争,并发上限由代理服务器本身限制——通常单IP支持几十到上百并发连接。采集任务是够用的,但需要连接池优化才能发挥出来。 ## 规则一:用requests.Session复用TCP连接 Python requests库最大的性能陷阱是每次请求都开新连接。正确的做法是用Session复用: ``` # 错误做法:每次请求都在TCP握手 for url in urls: requests.get(url, proxies=proxy) # 每次新建TCP连接 # 正确做法:Session复用TCP连接 session = requests.Session() session.proxies = proxy for url in urls: session.get(url) # 复用同一个TCP连接 ``` Session背后是urllib3的连接池——默认每个host保持10个连接。改了Session之后,同一目标域名的请求都复用已有的TCP连接,省掉了三次握手和TLS握手的开销。 ## 规则二:设置连接池大小匹配并发量 连接池默认10个连接,如果你的并发线程超过10,多出来的线程会排队等连接。根据并发线程数调大连接池: ``` from requests.adapters import HTTPAdapter session = requests.Session() # 每个host的连接池扩大到50个 adapter = HTTPAdapter(pool_connections=50, pool_maxsize=50) session.mount('http://', adapter) session.mount('https://', adapter) session.proxies = proxy ``` pool\_connections是总连接池大小,pool\_maxsize是每个host的最大连接数。代理IP有连接限制的情况下,pool\_connections不建议设超过代理的并发上限。 ## 规则三:控制线程数和代理连接数的配比 如果代理IP支持最多50并发连接,你开了100个线程,多出来的50个线程在排队等连接——看起来是在跑但实际在空等。最佳配比:线程数 ≤ 代理IP并发上限 × 0.8。留20%余量,避免偶然的峰值把代理打满。 ThreadPoolExecutor设置并发: ``` from concurrent.futures import ThreadPoolExecutor # 代理支持50并发,实际用40个线程 with ThreadPoolExecutor(max_workers=40) as executor: results = executor.map(fetch_with_proxy, urls) ``` ## 规则四:断开不用的连接释放资源 有些场景下你用的是多个不同的代理IP轮流切换——每个代理的Session留在那儿占用着连接但不一定在用。定期清理空闲连接: ``` # 每处理完一批请求后,关闭空闲连接 session.close() # 关闭所有连接 # 或者只清理空闲连接 adapter = session.get_adapter('http://') adapter.poolmanager.clear() ``` 长时间运行的服务建议设连接keep-alive超时——超过30秒没活动的连接自动关闭,避免占着连接不干活。 ## 规则五:加上重试和退避策略 高并发时偶尔的连接超时是正常的,不能因为一次失败就整个任务停了。加上重试机制: ``` from requests.adapters import HTTPAdapter from urllib3.util.retry import Retry retry_strategy = Retry( total=3, # 最多重试3次 backoff_factor=0.5, # 每次重试间隔翻倍: 0.5s, 1s, 2s status_forcelist=[429, 500, 502, 503, 504] # 这些状态码才重试 ) adapter = HTTPAdapter(max_retries=retry_strategy) session.mount('http://', adapter) ``` backoff\_factor=0.5表示第1次重试等0.5秒、第2次等1秒、第3次等2秒——给了代理服务器喘息的时间。别不加退避直接狂重试,等于自己对自己DDoS。 ## 常见问题 ### 加了连接池为什么还是慢? 连接池优化TCP连接复用,解决的是连接建立的开销问题。如果加了连接池还是慢,问题不在连接而在延迟——代理IP本身的延迟高,每个请求都要等几秒。解决方案是换延迟更低的节点或地区。 ### 共享代理和独享代理的并发差距多大? 共享代理通常限制5-20并发连接,独享代理可以到50-200。差距是数量级的。采集任务选独享——鲸云IP的独享住宅代理(客服x31471626改价)和天行IP的独享静态都能撑更高并发。 ### 代理并发不够能不能多买几个IP并行? 可以,而且这是横向扩展的正确思路。10个代理IP各跑20线程,总并发200。比买一个”支持200并发”的高价套餐便宜且容错更好——一个IP挂了不影响另外9个。 **Tags:** 代理IP, 数据采集合规, 静态IP **Categories:** 行业洞察 ---