43

我已经看到了两种使用 gunicorn 和 nginx 托管 django 应用程序的策略。

一种策略是在网络端口上运行 gunicorn。例如(来自http://goodcode.io/blog/django-nginx-gunicorn/):

location / {
    proxy_pass_header Server;
    proxy_set_header Host $http_host;
    proxy_redirect off;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Scheme $scheme;
    proxy_connect_timeout 10;
    proxy_read_timeout 10;
    proxy_pass http://localhost:8000/;
}

另一种策略是在启动时将 gunicorn 绑定到 UNIX 套接字(例如http://michal.karzynski.pl/blog/2013/06/09/django-nginx-gunicorn-virtualenv-supervisor/

upstream hello_app_server {
    server unix:/tmp/gunicorn.sock fail_timeout=0;
}

...

location / {
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_redirect off;
    if (!-f $request_filename) {
        proxy_pass http://hello_app_server;
        break;
    }
}

关于哪种策略更好的想法?对每个操作的正确方法有任何评论吗?我倾向于使用套接字方法,因为我认为 TCP 会引入开销。我最关心的是我见过的实现示例之间关于标头、连接超时等方面的差异。

4

5 回答 5

33

除了小的 TCP/IP 开销外,没有太大的区别。每个listen() 套接字都有一个连接队列,而accept() 只是从该队列中弹出一个连接。在 gunicorn 中,每个工作人员只是从该队列中弹出一个新连接,因为它不会改变。区别在于性能(套接字快一点)和可移植性(端口:IP 更灵活)。Unix 域套接字将为您提供更好的性能,而连接到 localhost 的套接字为您提供更好的可移植性,如果您将服务器应用程序移动到不同的操作系统,您只需将 IP 地址从 localhost 更改为不同的主机名即可.

于 2013-12-11T15:54:10.613 回答
27

这是我通过 Unix 套接字测试 TCP 代理的结果:

设置:在 AWS 上的 4 个 m4.xlarge 节点上运行的 nginx + gunicorn + django。每个节点的设置是统一的(来自同一图像)。

在大约 30 分钟的窗口内发出 100 万次请求:

4 个运行 TCP 代理与 Unix 套接字的 m4.xlarge 实例

由于其中一台服务器上运行不相关的作业,一个实例处于 100% CPU。其他 3 个是 70% CPU,每个代表实际应用程序负载。

TCP 与套接字几乎相同

发出 1000000 个请求的时间

TCP 代理为 27 分钟

和 31 分钟的 unix 套接字。

在此特定设置中,没有 unix 套接字性能优势。

于 2019-01-02T22:16:59.743 回答
20

如果您的网络服务器和应用服务器(wsgi)都存在于同一台机器上,那么套接字流量将是一个简单的选择。但是,您将需要网络连接上的网络端口,因为套接字不能在网络上工作,所以..

  1. 如果 webserver 和 appserver 位于同一台机器上 - GO SOCKET
  2. 如果 webserver 和 appserver 在网络上 - GO PORTS
于 2016-03-31T06:56:37.733 回答
7

会更喜欢 TCP/IP 上的套接字流量,因为不需要打开额外的端口。打开的端口越少,系统就越坚固

正如这里所建议的“偏执” https://hynek.me/talks/python-deployments/

“具有限制性权限的 UNIX 文件套接字是您的朋友。您可以停止使用端口号”

于 2015-11-08T23:05:22.590 回答
5

我知道我参加这个聚会迟到了,如果你想让它在带有 SELinux 强制的 Red Hat 风格的 Linux 上工作,这可能会有用。

如果您尝试使用套接字,它会严重妨碍您。我放弃。

如果您尝试通过任意 TCP 端口绑定 Gunicorn,它也会妨碍您。默认情况下(在 Centos 1708 上)有一个 SELinux 很乐意使用的端口子集:80,81,443,488,8008,8009,8443,9000

我选择了 8009,但显然对于您可以使用的其他端口

semanage -a -t http_port_t -p tcp $PORTNUMBER

并查看端口列表

semanage port -l

于 2018-02-06T11:35:36.270 回答