Django请求处理中是否需要显式关闭requests.Session会话
问题解答
结论
你当前的代码实现下,请求处理结束后requests_session不会被立刻自动关闭,建议显式手动关闭会话,避免连接资源泄漏。
原理说明
requests库的Session对象内部维护了HTTP连接池,只要你不主动调用Session.close()方法,连接池里的空闲连接不会立刻释放,只会等到Python垃圾回收机制销毁Session对象时,才会通过内置的__del__方法间接关闭连接,而垃圾回收的时机是完全不可控的。- 你当前的写法是在每个
put请求的处理逻辑里局部实例化Pipe对象,请求结束后这个局部对象虽然没有了引用,但并不会被立刻销毁,这段空窗期里Session占用的网络连接资源会一直被持有,高并发场景下很容易出现连接堆积、文件句柄耗尽的问题。
优化方案
方案1:手动新增关闭方法调用
给Pipe类新增关闭方法,请求处理结束后手动调用:
class Pipe(object): def __init__(self, imp_url=IAMPORT_API_URL): requests_session = requests.Session() requests_adapters = requests.adapters.HTTPAdapter(max_retries=3) requests_session.mount('https://', requests_adapters) self.requests_session = requests_session def get(self, url, payload=None): return self.requests_session.get(url, headers=headers, params=payload) # 新增关闭方法 def close(self): self.requests_session.close()
视图层用try...finally保证异常场景也能正常关闭:
class RequestAPIView(APIView): def put(self, request): pipe = Pipe() try: pipe.get(...) pipe.get(...) # 其余业务逻辑 finally: pipe.close()
方案2:实现上下文管理器自动关闭
给Pipe类补充上下文管理器协议实现,用with语句自动处理关闭逻辑,避免漏写:
class Pipe(object): def __init__(self, imp_url=IAMPORT_API_URL): requests_session = requests.Session() requests_adapters = requests.adapters.HTTPAdapter(max_retries=3) requests_session.mount('https://', requests_adapters) self.requests_session = requests_session # 补充上下文管理器方法 def __enter__(self): return self def __exit__(self, exc_type, exc_val, exc_tb): self.requests_session.close() def get(self, url, payload=None): return self.requests_session.get(url, headers=headers, params=payload)
视图层使用方式:
class RequestAPIView(APIView): def put(self, request): with Pipe() as pipe: pipe.get(...) pipe.get(...) # 其余业务逻辑 # 退出with块时自动调用close方法关闭session
额外性能优化建议
如果这个接口的访问量很高,每次请求都新建Session对象的开销也不小,可以把Pipe实现为线程安全的单例对象,复用Session的连接池进一步提升性能,只要注意不要在Session里存储请求私有的状态即可。
内容的提问来源于stack exchange,提问作者Sammy Kim
相关产品推荐
相关产品推荐

