使用Bottlepy-Gevent产生多个greenlets

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用Bottlepy-Gevent产生多个greenlets相关的知识,希望对你有一定的参考价值。

我是异步编程的新手,并且遵循Bottlepy-gevent教程here

我运行了页面上给出的程序:

from gevent import monkey; monkey.patch_all()

from time import sleep
from bottle import route, run

@route('/stream')
def stream():
    yield 'START'
    sleep(3)
    yield 'MIDDLE'
    sleep(5)
    yield 'END'

run(host='0.0.0.0', port=8080, server='gevent')

当我访问URL http://localhost:8080/stream,打印START,然后分别以3和5秒的睡眠间隔打印MIDDLEEND时,它按预期工作。

按照文档,

猴子修补使gevent能够阻止Python的阻塞API(以及time.sleep()等函数)阻塞当前线程,并将CPU传递给下一个greenlet。

但是,当我修改上面的代码以打印当前的greenlet信息时,我得到了用于所有三个yield语句的相同greenlet实例。

import gevent
from gevent import monkey
monkey.patch_all()

from time import sleep
from bottle import route, run

@route('/stream')
def stream():
    print(gevent.getcurrent())
    yield 'START '
    sleep(3)
    print(gevent.getcurrent())
    yield 'MIDDLE '
    sleep(5)
    print(gevent.getcurrent())
    yield 'END'

run(host='0.0.0.0', port=8080, server='gevent')

控制台输出:

<Greenlet at 0x7f9fd733a9c8: _handle_and_close_when_done(<bound method WSGIServer.handle of <WSGIServer at , <bound method StreamServer.do_close of <WSGIServer, (<gevent._socket3.socket object, fd=7, family=2, t)>
<Greenlet at 0x7f9fd733a9c8: _handle_and_close_when_done(<bound method WSGIServer.handle of <WSGIServer at , <bound method StreamServer.do_close of <WSGIServer, (<gevent._socket3.socket object, fd=7, family=2, t)>
<Greenlet at 0x7f9fd733a9c8: _handle_and_close_when_done(<bound method WSGIServer.handle of <WSGIServer at , <bound method StreamServer.do_close of <WSGIServer, (<gevent._socket3.socket object, fd=7, family=2, t)>

根据bottlepy文档,每次执行time.sleep()时都不应该生成新的greenlet实例吗?

而且,当我运行类似的程序而不使用gevent和monkey-patching时,如下所示:

from time import sleep
from bottle import route, run

@route('/stream')
def stream():
    yield 'START \n'
    sleep(3)
    yield 'MIDDLE \n'
    sleep(5)
    yield 'END'

run(host='0.0.0.0', port=8080)

我得到了与以前相同的响应(START跟随MIDDLE和END 3和5秒),与Bottlepy docs的评论相反,下面用黑体字表示:

如果您运行此脚本并将浏览器指向http://localhost:8080/stream,您应该看到START,MIDDLE和END逐个显示(而不是等待8秒钟才能一次看到它们)。

我错过了什么吗?

答案

2答案:

  • 来自服务器的每个请求都会产生一个新的greenlet,因此在同一个请求中你会看到相同的一个暂停和恢复。尝试在同一时间发送一些请求,以查看更多的greelets打印出来。
  • 您的示例在我的Mac上使用chrome,瓶子文档说明您可能需要在某些浏览器上产生更多字节: 注意:某些浏览器在开始呈现页面之前会缓冲一定数量的数据。您可能需要产生多个字节才能在这些浏览器中看到效果。此外,许多浏览器每个URL限制一个并发连接。如果是这种情况,您可以使用第二个浏览器或基准工具(例如ab或httperf)来衡量性能。
另一答案

根据bottlepy文档,每次执行time.sleep()时都不应该生成新的greenlet实例吗?

不,那个瓶子的文件在那里有点混乱,我很害怕。

每个传入的HTTP请求都会生成一个新的greenlet。然后,衍生的greenlet从头到尾处理整个请求。如果该greenlet(显式或隐式)产生,那么另一个greenlet可以自由地做一些工作(可能处理一些其他HTTP请求)。

当你调用monkeypatched time.sleep时,处理你的HTTP请求的greenlet被挂起,从而产生任何其他活动的greenlet(如果有的话)。当time.sleep返回(在指定的秒数之后)你的greenlet - 与之前为你的请求提供服务的那个 - 被唤醒并从sleep调用之后恢复运行。

希望有所帮助!

以上是关于使用Bottlepy-Gevent产生多个greenlets的主要内容,如果未能解决你的问题,请参考以下文章

list

vue项目之scoped

使用 __in=[somelist] 过滤模型的 ManyToMany 字段会产生零结果,而它应该产生多个

使用 tkinter 进行多处理不会产生多个 GUI

训练 Keras 模型会产生多个优化器错误

使用单个 FBO 将单个场景从多个视点绘制到多个纹理中(每个视点 1 个)仅产生一个有效纹理