requests 多线程环境中 报 [WinError 10048] 通常每个套接字地址(协议/网络地址/端口)只允许使用一次

2020-03-04 17:07:46 +08:00
 wuwukai007
环境 windows python3.6 jupyter notebook
没有使用 requests.Session,只是单纯的 get 请求,
我把 线程数量控制在 os.cpu_count()后问题解决,
但是 这样就只能开 8 个线程,效率就低很多了。
4499 次点击
所在节点    Python
5 条回复
cz5424
2020-03-04 19:00:23 +08:00
你用多进程试试?
ysc3839
2020-03-04 19:06:11 +08:00
怀疑是连接池的什么 bug ?多个线程同时请求的时候重复使用了已经建立连接的 socket。
不过具体如何还得调试看看了,得先找到哪出的错误,再一步步回溯。
1462326016
2020-03-05 09:38:45 +08:00
直接 get 的话其实内部就是 with session as xx: 所以你其实是每一个请求开了一个连接池,可能频繁的发送请求,会导致系统回收一些端口不及时导致这个问题。
两个方案:
1. 多个线程共享一个 session,注意加锁,因为目前没办法证明它是线程安全的,我也没详细看过源码。
2. 使用异步,按照你现在的情况来看应该不会是很复杂的请求,只是效率问题。异步可以增加效率。例如 aiohttp。
ClericPy
2020-03-05 09:58:49 +08:00
楼主也不给点代码看看到底哪的问题, 这样提问题让人很困扰啊, 只看报错的话, 不像是客户端(也就是 requests) 的问题, 反而像是你在同一个端口下开了多个 server 报的错, 没有代码也猜不了更多了

另外提 requests 并发的几个常识吧

1. 多线程并不是越多越快, 毕竟压根又用不到多核 CPU, 直接用官方建议的并发数比较合理, https://docs.python.org/zh-cn/3/library/concurrent.futures.html#concurrent.futures.ThreadPoolExecutor , 以前默认为机器处理器的个数, 3.8 以后又建议了 min(32, os.cpu_count() + 4).

2. 如果是 Windows 操作系统, 那就更不用考虑把并发数开大了, 别说开到几千, 开到五六百可能就超了 Windows 的单进程默认最大 文件描述符(句柄) 限制而报错了, 在 GIL 的作用下, 走协程+多路复用的路子比传统多线程要合理的多.

3. 如果真想要性能, requests 比 aiohttp 慢了 4 倍, 而且还是在 Windows 上无法启用 uvloop 提速的前提下, 协程开销比线程小很多, 也快很多, aiohttp 有 Cython 加成, 也比同样是协程的 httpx 快一大截.

4. requests 的 Session 是共享连接池的一套逻辑, 速度比 requests.get 快一大截, 毕竟后者每次要开启一个新的 Session, 也就创建新的连接. PS: 就我目前测试结果来看, 是线程安全的, 没必要加无谓的锁

5. 突破默认 http 适配器连接数上限也可以用以下代码来实现

custom_adapter = HTTPAdapter(
pool_connections=n, pool_maxsize=n)
session.mount("http://", custom_adapter)
session.mount("https://", custom_adapter)
wuwukai007
2020-03-08 00:02:26 +08:00
@ClericPy 多谢回答,我改成了 gevent 方式做异步处理,效率提高了蛮多的,也不存在套接字那个问题了,就是有一个缺点,gevent 在 windows 中套接字限制 1024,所有 只能把每次的请求数量限制在 1000 之内,看了下 asyncio 的文档,应该也会有这个限制,windows 问题。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/649839

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX