我应该为 Flask、uWSGI 和 nginx 提供单独的容器吗?

Posted

技术标签:

【中文标题】我应该为 Flask、uWSGI 和 nginx 提供单独的容器吗?【英文标题】:Should I have separate containers for Flask, uWSGI, and nginx? 【发布时间】:2017-11-15 21:47:12 【问题描述】:

我打算使用 Kubernetes 和 Ingress 进行负载平衡。我正在尝试学习如何设置 Flask、uWSGI 和 nginx。 我看到本教程将所有三个都安装在同一个容器中,我想知道是否应该使用它。 https://ianlondon.github.io/blog/deploy-flask-docker-nginx/

我猜将它们作为单独的容器和单独的 pod 的好处是它们都可以单独扩展?

而且,Flask 和 uwsgi 是否应该放在单独的容器中? (或 Flask 和 Gunicorn,因为 uwsgi 似乎与 Gunicorn 非常相似)

【问题讨论】:

你的烧瓶应用程序和 uwsgi / gunicorn 必须在同一个容器中,nginx 在一个单独的容器中。 【参考方案1】:

Flask 是一个 Web 框架,任何用它编写的应用程序都需要一个 WSGI 服务器来托管它。尽管您可以使用 Flask 内置的开发人员服务器,但您不应该这样做,因为它不适合生产系统。因此,您需要使用 WSGI 服务器,例如 uWSGI、gunicorn 或 mod_wsgi (mod_wsgi-express)。由于web应用是由WSGI服务器托管的,所以只能在同一个容器中,而Flask没有单独的进程,它运行在web服务器进程中。

您是否需要单独的 Web 服务器(例如 nginx)取决于您。在 mod_wsgi 的情况下,您不需要,因为它使用 Apache Web 服务器,因此可以直接从中受益。使用 mod_wsgi-express 时,它也已经设置为在最佳基本配置下运行,以及它如何避免需要像人们在使用 uWSGI 或 gunicorn 时经常使用 nginx 那样有一个单独的前端 Web 服务器。

对于容器化系统,平台已经提供了用于负载平衡的路由层,就像 Kubernetes 中的入口一样,混合使用 nginx 只会增加您不需要的额外复杂性,并且可能会降低性能。这是因为您要么必须在同一个容器中运行 nginx,要么在同一个 pod 中创建一个单独的容器并使用共享的emptyDir 卷类型以允许它们仍然通过 UNIX 套接字进行通信。如果您不使用 UNIX 套接字,而是使用 INET 套接字,或者在完全不同的 pod 中运行 nginx,那么这是没有意义的,因为您正在为流量引入一个额外的跃点,这将比密切使用它更昂贵使用 UNIX 套接字绑定。 uWSGI 服务器在与 nginx 耦合时通过 INET 接受请求时性能不佳,并且将 nginx 放在一个单独的 pod 中,可能位于不同的主机上,这会使情况变得更糟。

在前面使用 nginx 的部分原因是它可以保护您免受由于请求缓冲以及其他潜在问题而导致的慢速客户端的影响。但是,在使用 ingress 时,您已经拥有一个 haproxy 或 nginx 前端负载均衡器,可以在一定程度上保护您免受这种情况的影响。所以这真的取决于你在做什么,是否有必要在混合中引入一个额外的 nginx 代理。将 gunicorn 或 uWSGI 直接放在负载均衡器后面会更简单。

建议如下。

还可以查看 mod_wsgi-express。它是专门为容器化系统而开发的,以使其更容易,并且可能是比 uWSGI 和 gunicorn 更好的选择。

使用您的实际应用程序测试不同的 WSGI 服务器和配置,并使用真实世界的流量配置文件,而不是只会使其过载的基准测试。这一点很重要,因为基于 Kubernetes 的系统的动态特性以及其路由的实现方式,意味着它的行为可能与您可能习惯的更传统的系统有很大不同。

【讨论】:

感谢 Graham 的彻底回复。我也不想使用 nginx,因为看起来 Ingress 已经可以进行负载平衡了。但我一直只看到 Ingress + nginx 的教程。我的理解是,这里使用 nginx 只是为了正确地提供静态文件,而不是用于其负载平衡功能,因为 Ingress 已经在这样做了,对吗?退后一步 - 我的理解正确吗 nginx 是一个可以处理多个传入连接并将它们全部定向到 WSGI 的网络服务器(这将是多个 python 运行的应用服务器?) 使用 uWSGI 时,nginx 的主要目的是处理静态文件并将 uWSGI 与慢速客户端隔离。由于 uWSGI 通常位于同一主机上并使用 UNIX 套接字来传递请求,因此它并没有严格执行负载平衡,因为这将落入内核以及哪个进程唤醒并通过 UNIX 套接字接受下一个请求。由于 uWSGI 无论如何都有办法提供静态文件,这就是为什么 nginx 在这种情况下可能毫无意义。 优秀的答案格雷厄姆!我刚刚偶然发现了基于 Docker swarm 的部署的类似问题,您的回答也很好地解决了这个问题。非常感谢,非常感谢! 阅读@GrahamDumpleton 的回答后,我恢复了对人性的信心

以上是关于我应该为 Flask、uWSGI 和 nginx 提供单独的容器吗?的主要内容,如果未能解决你的问题,请参考以下文章

使用 uwsgi 和 nginx 运行 Flask 应用程序

flask uwsgi nginx

Flaskflask+uwsgi+nginx环境部署

使用 nginx、uwsgi、flask 轻松进行应用程序日志记录/调试?

python服务器环境搭建Flask,uwsgi和nginx

使用flask和flask-socketio配置nginx、uwsgi