Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/337.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python Gunicorn、Django、Gevent:生成的线程正在阻塞_Python_Django_Multithreading_Gunicorn_Gevent - Fatal编程技术网

Python Gunicorn、Django、Gevent:生成的线程正在阻塞

Python Gunicorn、Django、Gevent:生成的线程正在阻塞,python,django,multithreading,gunicorn,gevent,Python,Django,Multithreading,Gunicorn,Gevent,我们最近使用geventworker切换到了Gunicorn 在我们的网站上,我们有一些任务需要一段时间才能完成。超过30秒 序言 我们已经做了整个芹菜的事情,但是这些任务很少运行,所以让芹菜和redis一直运行是不可行的。我们只是不想那样。我们也不想按需启动芹菜和redis。我们想摆脱它。(对此我很抱歉,但我想避免这样的回答:“你为什么不用芹菜,它很棒!” 我们想要异步运行的任务 我说的是执行3000个SQL查询(插入)的任务,这些查询(插入)必须一个接一个地执行。这并不经常发生。我们还限制一

我们最近使用geventworker切换到了Gunicorn

在我们的网站上,我们有一些任务需要一段时间才能完成。超过30秒

序言 我们已经做了整个芹菜的事情,但是这些任务很少运行,所以让芹菜和redis一直运行是不可行的。我们只是不想那样。我们也不想按需启动芹菜和redis。我们想摆脱它。(对此我很抱歉,但我想避免这样的回答:“你为什么不用芹菜,它很棒!”

我们想要异步运行的任务 我说的是执行3000个SQL查询(插入)的任务,这些查询(插入)必须一个接一个地执行。这并不经常发生。我们还限制一次只运行其中的两个任务。它们应该需要2-3分钟

方法 现在,我们正在做的是利用gevent worker和
gevent.spawn
任务并返回响应

问题 我发现生成的线程实际上是阻塞的。一旦返回响应,任务就开始运行,在任务停止运行之前,不会处理任何其他请求。任务将在30秒后终止,gunicorn
超时。
为了防止这种情况,我在每次SQL查询之后都使用
time.sleep()
,这样服务器就有机会响应请求,但我觉得这不是重点

设置 我们运行gunicorn、django并使用gevent。所描述的行为发生在my dev环境中,并使用1个gevent worker。在生产中,我们也将只运行1名工人(目前)。此外,在任务阻塞时,运行2个worker似乎无助于服务更多的请求

太长,读不下去了
    我们认为在2分钟的任务中使用G事件线程是可行的。 (放在芹菜上)
  • 我们将gunicorn与gevent一起使用,不知道为什么要使用线程 使用gevent生成。生成被阻止
  • 是有意阻止还是我们的设置错误

谢谢大家!

在后台运行任务的一种方法是
fork
父进程。与Gevent不同,它不会阻塞--您正在运行两个完全独立的进程。这比启动另一个(非常便宜的)绿地要慢,但在这种情况下,这是一个很好的权衡

您的流程分为两部分,父级和子级。在父级中,
返回对Gunicorn的响应,就像在普通代码中一样

在子对象中,执行长时间运行的处理。最后,通过执行专门版本的
exit
进行清理。下面是一些处理和发送电子邮件的代码:

    if os.fork():
        return JsonResponse({}) # async parent: return HTTP 200
    # child: do stuff, exit quietly
    ret = do_tag_notify(
        event, emails=emails, photo_names=photo_names,
        )
    logging.info('do_tag_notify/async result={0}'.format(ret))
    os._exit(0)             # pylint: disable=W0212
    logging.error("async child didn't _exit correctly") # never happens
小心这个。如果在子对象中抛出异常,即使是语法错误或未使用的变量,您也永远不会知道!带有日志记录的父级已不存在。日志记录要详细,不要做太多


使用
fork
是一个很有用的工具——玩得开心

我已经决定使用一个
同步
(标准)工人,并使用
多处理
库。这似乎是目前最简单的解决方案


我还实现了一个全局池,滥用
memcached
缓存提供锁,因此只能运行两个任务。

这里似乎没有人对您的问题给出实际答案

是有意阻止还是我们的设置错误

您的设置有问题。SQL查询几乎完全是I/O绑定的,不应该阻止任何Greenlet。您使用的SQL/ORM库对gevent不友好,或者代码中的其他内容导致了阻塞。这种任务不需要使用多处理


除非您在greenlet上显式地执行
join
,否则服务器响应不应该被阻塞。

只是在greenlet中执行代码。实际上,您必须调用异步API才能使greenlet不阻塞。例如,您正在拨打的
time.sleep
电话仍会在绿色小房间内阻塞。您应该使用
gevent.sleep
执行非阻塞睡眠。您的数据库调用可能也被阻塞了,除非您使用的是gevent monkey修补程序。@dano因为我正在与gevent worker一起使用gunicorn,所以monkey修补程序由我负责<代码>时间。睡眠
允许线程更改,因此它是非阻塞的。也许是猴子补的。但是,我希望把任务交给一个工人,然后由他来处理。因此,只要它并行运行,它就可以阻止它想要的一切。但我猜Greenlet不能并行运行?Greenlet可以并发运行,但它们仍然是单线程的;一次只能使用其中一个CPU。因此,如果一个greenlet处于阻塞I/O调用或
gevent.sleep
,另一个greenlet可以运行。但是,如果一个greenlet正在处理数字或解析XML(或任何其他基于CPU的操作),那么其他greenlet将不会运行。如果要执行非异步的I/O操作,greenlet也会阻止其他greenlet,这意味着它不是由gevent修补的monkey,也不是插入gevent的事件循环。你说你在做插入,但后来说你在使用django ORMs。因此,您可能要做的不仅仅是插入(否则您可以在一个sql调用中完成3000次插入)。因为它使用的是CPU,所以会阻塞,就这么简单。停止抱怨不想经营芹菜和redis。Redis是轻量级的,您可以在0到1之间自动缩放芹菜。很有可能你会使用redis做更多的事情。@dalore,有时你不是这些决定的主人,你不得不做一些其他的事情。另外,没有人说我会使用Django ORM。我下面的解决方案已经运行了好几个月了,但是感谢您的时间尽管我觉得这不起作用,但我尝试了,它确实不起作用。当执行的代码