问题背景
问题发生在公司的一个js渲染的工具应用中。
环境
- python3.6
- requests_html 0.10.0
- Aliyun FC (函数计算)
基础代码
由于涉及到内部代码,这里仅给出问题的基础代码实现
from requests_html import HTMLSession
def main(url):
session = HTMLSession()
r = session.get(url, headers=headers)
r.html.render() # 进行渲染
print(r.html.html)
问题描述
今天测试在验证的时候,测试反馈,代码执行会超时报错:
Unable to render the page. Try increasing timeout
[
"File \"/opt/python/requests_html.py\"",
"line 605",
"in render",
"raise MaxRetries(\"Unable to render the page. Try increasing timeout\")"
]
问题排查
在排查日志后发现如下规律
- 一个实例启动后的前几次调用都是正常的
- 大约从第6次调用开始,会出现超时情况
- 新启动的实例运行时复现上述问题
异常原因
经过百度搜索,AI询问,找到了stackoverflow中的一个问题:Python Requests-HTML Render() - No Content
在它的问题描述中,发现对方使用HTMLSession的方式是这样的:
with HTMLSession() as session:
p = session.post(login_url, data=payload)
r = session.get(content_url)
r.html.render()
print(r.text)
也就是说:HTMLSession
可以作为资源被close
而我在使用中,既没有显式调用.close()
方法,也没有使用with xxxxx as xxx:
的语法
问题修复
找到了原因, 就可以修复了。上述实例代码修复如下:
from requests_html import HTMLSession
def main(url):
with HTMLSession() as session: # 通过with xxx语法,可以在使用完毕后自动关闭资源
r = session.get(url, headers=headers)
r.html.render() # 进行渲染
print(r.html.html)
思考
其实这个代码上线很久了。线上没有暴露问题,实际原因是:线上调用量低,负载在空闲5分钟后,会被关闭。几乎每次调用都是冷启动,不会导致资源堆积报错
而此次被发现的原因是测试同学一直在进行较高强度的测试。使得渲染后的资源得不到释放。