文章类型网站,行业数据可以从哪里获取,大型企业网站欣赏,wordpress 初夏主题本文从WordPress迁移而来, 查看全部WordPress迁移文章
背景#xff1a;要从内部的一个web api拉取数据#xff0c;要请求大概15万次左右#xff08;15万个ID#xff0c;每个ID请求一次#xff09;
特点#xff1a;一个host#xff08;也可以以IP直接请求#xff09;要从内部的一个web api拉取数据要请求大概15万次左右15万个ID每个ID请求一次
特点一个host也可以以IP直接请求ID是作为请求参数发过去的。
一开始是非常简单地使用 requests.get(“htttp://www.myapi.com”)也没发现多大的问题
后来就出现了错误 (‘Connection aborted.’, error(99, ‘Cannot assign requested address’))数量巨大
问一下搜索引擎这个错误的原因是什么基本的说法就是
客户端频繁的连服务器由于每次连接都在很短的时间内结束导致很多的TIME_WAIT以至于用光了可用的端口号所以新的连接没办法绑定端口即“Cannot assign requested address”
看到这些解释的时候一点都不冤枉正好是我的请求请求了15万次每次请求都是短连接很短时间结束
netstat -an | grep TIME_WAIT 查看一下TIME_WAIT的情况果然数量巨大而且目的IP都是同一个host的IP。
然后在同学的指导下用了requests的连接池确实也符合我的需求场景。我只向一个host发请求变的只是请求参数所以HTTP连接完全可以使用长连接
也就是先向服务器建立好几十个连接多一点应该问题也不大我只建立了24个在这些TCP连接上传输我们的HTTP报文。
最后的结果就是再没出现过上面的错误了然后我们再用netstat看一下
netstat -an | grep host的IP
看到了 24条记录都是 ESTABLISHED 状态符合预期就是那24条连接一直持续着
代码如下
1
2
3
4
5
6
7
8
9def __get_http_session(self, pool_connections, pool_maxsize, max_retries):
session requests.Session()
# 创建一个适配器连接池的数量pool_connections, 最大数量pool_maxsize, 失败重试的次数max_retries
adapter requests.adapters.HTTPAdapter(pool_connections pool_connections,
pool_maxsize pool_maxsize, max_retries max_retries)
# 告诉requestshttp协议和https协议都使用这个适配器
session.mount(http://, adapter)
session.mount(https://, adapter)
return session
后续的使用也是很直接的最简单的使用是 requests.get, requests.post, requests.head 等这里我们就直接 session.get() session.post(), session.head() 即可
session就是 __get_http_session() 返回的对象
后面同学又问了一个问题这个问题是因为端口号用完而导致的要是能修改内核增加端口号行不行呢而后同学马上又说了这是不行的因为且不说修改linux内核行不行但TCP协议中是有字段来标识端口号的16位所以端口号最大只能到65535这不是由操作系统决定的是TCP协议决定的。
linux能修改的是缩短TIME_WAIT的时间
这个连接池的用法适合这种背景向一个host频繁发请求
但对于大量不同的host发请求是没什么效果的因为不可能建立长连接不同host一般IP都不同连接是以源IP源端口号目的IP目的端口号标识的