为什么我需要 Nginx 和 Gunicorn 之类的东西?

a.m*_*.m. 268 nginx django

我正在寻找对以下问题的过于简化的答案。我试图建立对 Nginx 如何与 Gunicorn 之类的东西一起工作的基本理解。

我是否需要 Nginx 和 Gunicorn 之类的东西才能在 Nginx 上部署 Django 应用程序?

如果是这样,实际处理 HTTP 请求的是什么?

附言。我不想使用 Apache 和 mod_wsgi!

小智 387

过度简化:您需要一些可以执行 Python 的东西,但 Python 并不是处理所有类型请求的最佳选择。

[免责声明:我是 Gunicorn 开发人员]

不那么简单:不管你使用什么应用服务器(Gunicorn、mod_wsgi、mod_uwsgi、cherrypy),任何类型的非平凡部署都会有一些上游的东西来处理你的 Django 应用程序不应该处理的请求。此类请求的简单示例是提供静态资产 (images/css/js)。

这导致经典“三层架构”的两个第一层。即,网络服务器(在您的情况下为 Nginx)将处理许多对图像和静态资源的请求。然后需要动态生成的请求将传递到应用程序服务器(在您的示例中为 Gunicorn)。(顺便说一句,三层中的第三层是数据库)

从历史上看,这些层中的每一层都将托管在不同的机器上(并且很可能在前两层中有多台机器,即:5 个 Web 服务器将请求分派给两个应用服务器,后者又查询单个数据库)。

在现代时代,我们现在拥有各种形状和大小的应用程序。并非每个周末项目或小型企业站点实际上都需要多台机器的马力,并且可以在单个机器上愉快地运行。这催生了一系列托管解决方案的新条目。一些解决方案会将应用程序服务器与 Web 服务器(Apache httpd + mod_wsgi、Nginx + mod_uwsgi 等)结合起来。将数据库与这些 Web/应用程序服务器组合之一托管在同一台机器上并不少见。

现在在 Gunicorn 的情况下,我们做出了一个特定的决定(从 Ruby 的 Unicorn 复制),在依赖 Nginx 的代理行为的同时,将事情与 Nginx 分开。具体来说,如果我们可以假设 Gunicorn 永远不会直接从 Internet 读取连接,那么我们就不必担心客户端速度很慢。这意味着 Gunicorn 的处理模型非常简单。

分离还允许 Gunicorn 用纯 Python 编写,从而最大限度地降低开发成本,同时不会显着影响性能。它还允许用户使用其他代理(假设它们正确缓冲)。

至于您关于实际处理 HTTP 请求的第二个问题,简单的答案是 Gunicorn。完整的答案是 Nginx 和 Gunicorn 都处理请求。基本上,Nginx 将接收请求,如果它是一个动态请求(通常基于 URL 模式),那么它将将该请求提供给 Gunicorn,Gunicorn 将处理它,然后将响应返回给 Nginx,然后将响应转发回原始请求客户。

所以最后,是的。您需要 Nginx 和 Gunicorn(或类似的东西)才能正确部署 Django。如果您特别希望使用 Nginx 托管 Django,那么我会调查 Gunicorn、mod_uwsgi 和 CherryPy 作为 Django 方面的候选者。

  • 感谢您花时间写出如此详细的答案!关于这个“三层架构”的任何推荐阅读? (16认同)
  • 我的 django 应用程序只提供 json 没有静态内容我可以只使用 gunicorn 而没有 nginx (10认同)
  • 很好的答案,但是我不明白慢客户端的问题。 (8认同)
  • @MadsSkjern 我在这里猜测,但是如果您假设所有客户端都很快,那么您可以使用固定的工作进程池,而不必为其中许多或全部被阻塞等待客户端的情况编写代码。 (5认同)
  • @am https://en.wikipedia.org/wiki/Multitier_architecture (3认同)
  • `你需要一些可以执行 Python 的东西,但 Python 并不是处理所有类型请求的最佳选择。` - 我同意这句话,因为我有一些经验证明这是正确的。但是,有没有人有任何其他文件可以证明分析,显示“为什么 Python 不是最擅长处理所有类型的请求?”。另外,非常感谢#Paul,提供如此详细而丰富的答案。 (3认同)
  • 很好的答案,但非常具有讽刺意味的是(考虑到您作为 Gunicorn 的开发人员的角色)如果 NGINX 处理请求管理器的繁重工作,则忽略了 Gunicorn _does_ 所做的事情。这导致没有人真正能够解决@ShadowDoom 在下面声称 Gunicorn 根本没有必要的说法。 (3认同)
  • @Paul J. Davis,所以当 GUNICORN 托管在另一台与 nginx 托管的机器不同的机器上时。两人如何沟通?nginx 如何将请求转发到 GUNICORN?也通过http?那么 GUNICORN 还必须有一个 Web 服务器来接收请求吗?我对吗 ?如果它们托管在同一台机器上,那么 IPC(进程间通信)就足够了吗? (2认同)
  • @Stallman 他们在服务网络请求方面没有发挥任何作用。celery(使用 rabbitMQ)专门用于与 Web 请求无关的事情,例如调整图像文件大小或发送电子邮件。 (2认同)

小智 45

我喜欢这个简单的解释:

Nginx 将面对外界。它将直接从文件系统提供媒体文件(图像、CSS 等)。但是,它不能直接与 Django 应用程序对话;它需要一些东西来运行应用程序,从网络向它提供请求,并返回响应。

那是 Gunicorn 的工作。Gunicorn 将创建一个 Unix 套接字,并通过 wsgi 协议向 nginx 提供响应 - 套接字双向传递数据:

The outside world <-> Nginx <-> The socket <-> Gunicorn
Run Code Online (Sandbox Code Playgroud)

https://gist.github.com/Atem18/4696071

  • 它不一定是套接字,以防其他人想知道。 (4认同)
  • 换句话说,一个 wsgi 服务器就像一个 python 应用程序执行器,它接收一个动态内容请求并调用 python 应用程序来生成输出。这样对吗? (2认同)