我目前正在运行一个非多线程的 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 应用程序中的性能非常出色,因此我很乐意继续使用它。
谢谢,如果我可以提供更多信息,请告诉我。
最佳答案
将非阻塞编程(geventhttpclient)与阻塞编程(uWSGI 线程/进程)混合在一起是完全错误的。这是一条一般规则:即使您的应用程序 99% 不阻塞,它仍然会阻塞。 gevent 利用堆栈切换来模拟阻塞编程范例这一事实进一步放大了这一点。
这就像协作多任务处理,由所谓的“gevent-hub”管理。不幸的是,尽管您的 greenlet 能够发出 http 请求,但它们永远不会终止,因为一旦请求结束,gevent hub 将永远不会再次运行。
如果你想维护 geventhttpclient 方法,你必须将 uWSGI 设置为 gevent 模式,但你需要确保你的应用程序使用的所有模块和技术都是 gevent 友好的。
关于python - 线程不足 : UWSGI + Multithreaded Python Application with GeventHTTPClient,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27433087/