V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
aiqier
V2EX  ›  Python

tornado 的 AsyncHTTPClient 和 requests 库为什么不关闭连接?

  •  
  •   aiqier · 2015-12-17 15:13:05 +08:00 · 4272 次点击
    这是一个创建于 3257 天前的主题,其中的信息可能已经有所发展或是发生改变。

    之前一段时间,一直在用 tornado 的异步客户端。

    http_client = AsyncHTTPClient()
    response = yield http_client.fetch(url, method=‘ POST ’, body=data)
    response.body …..

    但是从来没写过:
    http_client.close()这样的代码。

    类似的,同步的阻塞请求,我一般使用 python 的 requests 库:

    response = requests.post(url, body)
    response.content

    但是也没有调用过类似 close()的方法,

    按理来说,数据库连接,文件句柄,网络连接,这些非托管资源,不是都应该手动去关闭的么?我记得比较“低级”的 http 库确实会调用关闭:
    HTTPConnection.close(),

    那么我的问题是

    1.我在 tornado 的 http 客户端,和 requests 库中,如何关闭它们?
    2.是否是因为本质上,这两个客户端在关闭方式上就是不同的。
    3.如果不关,我的服务长期这样跑着,总有一天会大量内存泄露吧?

    10 条回复    2015-12-17 18:38:51 +08:00
    zeayes
        2
    zeayes  
       2015-12-17 16:11:20 +08:00   ❤️ 1
    tornado 的 AsyncHTTPClient 都是短链接,请求处理完了,自动关闭,具体代码位置: httpclient.py -> simple_httpclient.py -> http1connection.py
    requests 的请求链接是有连接池的,具体可看源代码,位置:models.py -> sessions.py -> adapters.py 里面的 send 方法。
    dozer47528
        3
    dozer47528  
       2015-12-17 16:15:35 +08:00
    建议用 Apache 的 HttpAsyncClient ,底层有连接池管理,也可以自己实现。

    这个性能很好,只要服务端性能够,用 HttpAsyncClient 轻轻松松上万 QPS 。

    我在高并发环境下用的就是它。稳定运行一年了。
    dozer47528
        4
    dozer47528  
       2015-12-17 16:15:58 +08:00
    忽略我吧,我还以为说的是 Java …
    tywtyw2002
        5
    tywtyw2002  
       2015-12-17 16:19:34 +08:00
    tornado 的 AsyncHTTPClient 不是这么用的啊。。。。。

    看你的 code 你是用 AsyncHTTPClient 去做一个 post ,然后对结果去处理吧。如果是这个样子你用 HTTPClient ,因为这个会自动 block 。(这 block 的意思是说,不需要 yield 去防止执行到下一条语句。)

    如果我没记错的关闭 AsyncHTTPClient 就是把这个对象在 ioloop 中移除,然后设置 close flag 。
    这个跟 web.RequestHandler 里面的 self.finish()很类似,防止在 call finish 后在去进行写操作。

    对于 AsyncHTTPClient 的应用我比较偏向于 chunk 数据的处理,比如说视频的转码,对于普通的 get/post 操作我个人认为用 AsyncHTTPClient 的意义不大,真不如用 HTTPClient 。
    用 requests 的话能会 block 其他 http 请求。因为他无法注册到 ioloop 里面。只要这个 requests 请求结束, tornado 才会处理下一个 http 请求。


    查了下文档,文档中提到 AsyncHTTPClient 是可以不关闭的,除非你用了 force_instance=True 。
    http://www.tornadoweb.org/en/stable/httpclient.html#tornado.httpclient.AsyncHTTPClient.close
    est
        6
    est  
       2015-12-17 16:21:18 +08:00
    @dozer47528 有没有试过一个很卡的网站。你同时并发 1w 个请求过去,会卡成什么样?
    aiqier
        7
    aiqier  
    OP
       2015-12-17 16:34:04 +08:00
    @tywtyw2002 用 post 就不能 yield 异步了?我现在的服务从来没 block 过,
    wy315700
        8
    wy315700  
       2015-12-17 16:35:04 +08:00
    因为会重用连接
    neoblackcap
        9
    neoblackcap  
       2015-12-17 16:46:02 +08:00
    @aiqier 用 AsyncHTTPClient 就是 non-block ,其他包括 requests 都是 block
    dozer47528
        10
    dozer47528  
       2015-12-17 18:38:51 +08:00
    @est 我做的是个 proxy ,所以目标 server 会有很多,不是都压在一台上。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2661 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 40ms · UTC 11:31 · PVG 19:31 · LAX 03:31 · JFK 06:31
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.