gunicorn + nginx:服务器通过socket还是代理?

时间:2013-11-11 21:10:25

标签: django nginx gunicorn

我已经看到了使用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引入的。我最关心的是标题,连接超时等差异,以及我见过的实现示例之间的差异。

5 个答案:

答案 0 :(得分:25)

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

答案 1 :(得分:14)

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

  1. 如果网络服务器和应用服务器位于同一台机器上 - GO SOCKET
  2. 如果网络服务器和应用服务器在网络上 - GO PORTS

答案 2 :(得分:4)

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

这里建议“偏执狂” https://hynek.me/talks/python-deployments/

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

答案 3 :(得分:3)

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

设置: 在AWS的4个m4.xlarge节点上运行的nginx + gunicorn + django。

大约30分钟内发出了100万个请求:

4 m4.xlarge ninstances running TCP PRoxy vs. Unix socket

一个实例的CPU使用率为100%,另外3个实例的CPU使用率为70%。

TCP与套接字几乎相同 发出1000000个请求的时间

TCP代理是27分钟

unix套接字需要31分钟。

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

答案 4 :(得分:0)

我知道我已经迟到了这个派对,如果你想在SELinux强制执行的Red Hat flavor 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