耗尽线程:使用GeventHTTPClient的UWSGI +多线程Python应用程序

时间:2014-12-11 21:52:42

标签: python multithreading uwsgi gevent

我目前正在运行一个非多线程的python Web API,在uWSGI + NGINX堆栈上取得了很大的成功。由于新的操作需求,我实现了一个包含对外部数据源的多线程请求的新构建。但是,当我使用--enable-threads在uWSGI下部署这个新的多线程版本时,几分钟后,机器用完了可用的线程。

通过使用ps -eLf | grep <process id>| wc -l监控线程数,我能够将问题与我对外部HTTP请求的geventhttpclient的使用隔离开来。我在我的应用程序中当前有2个工作线程(两个外部请求),所以我注意到,每次我从我的API命中/发出请求时,应用程序线程使用次数增加2.如果我交换使用geventhttpclient与标准python Requests模块只在其中一个工作线程中,线程数只增加1.

注意:我正在使用HTTPClient.close()关闭每个线程内的连接。

这让我怀疑geventhttpclient会创建在多线程uWSGI应用程序中使用时不会终止的新线程。

这个阻塞点有一个简单的方法吗? geventhttpclient的性能在非多线程uWSGI应用程序中非常出色,所以我很乐意继续使用它。

谢谢,如果我能提供更多信息,请告诉我。

1 个答案:

答案 0 :(得分:1)

将非阻塞编程(geventhttpclient)与阻塞编程(uWSGI线程/进程)混合是完全错误的。这是一般规则:即使您的应用程序99%无阻塞,它仍然是阻止的。这一事实被gevent利用堆栈切换来模拟阻塞编程范例这一事实所放大。

这就像合作多任务,它由所谓的'gevent-hub'管理。不幸的是,虽然您的greenlets将能够发出http请求,但它们永远不会被终止,因为一旦请求结束,gevent hub将永远不再运行。

如果你想维护geventhttpclient方法,你必须在gevent模式下设置uWSGI,但你需要确保你的应用程序使用的所有模块和技术都是gevent友好的。