Nginx 不再为 HAProxy 后面的 uwsgi 应用程序提供服务 - 而是寻找静态文件

Nginx 不再为 HAProxy 后面的 uwsgi 应用程序提供服务 - 而是寻找静态文件

我们使用 web2py 实现了我们的 Web 应用程序。它由多个模块组成,为各种资源(例如 /dids、/replicas 等)提供 REST API。该 API 由实现 request.py 的客户端使用。

我的问题是,如果我们的 Web 应用位于 HAProxy 后面并且由 Apache 使用 mod_wsgi 托管,它就可以正常工作。如果客户端直接与 nginx 交互,它也可以正常工作。但是,当在 nginx 前面使用 HAProxy 时,它就不起作用了。我猜是 HAProxy 以某种方式修改了请求,因此 nginx 的行为有所不同,即查找静态文件而不是调用 WSGI 容器。不幸的是,我无法弄清楚到底发生了什么。

以下是这三个组件的配置文件的相关配置部分。至少我猜它们很有趣。如果您遗漏了任何内容,请告诉我。

1)haproxy.conf

frontend app-lb
 bind loadbalancer:443 ssl crt /etc/grid-security/hostcertkey.pem
 default_backend nginx-servers
 mode http
backend nginx-servers
 balance leastconn
 option forwardfor
 server nginx-01 nginx-server-int-01.domain.com:80 check

2)nginx.conf:

    sendfile        off;
    #tcp_nopush     on;
    keepalive_timeout  65;
    include /etc/nginx/conf.d/*.conf;
    server {
            server_name nginx-server-int-01.domain.com;
            root /path/to/app/;
            location / {
                    uwsgi_pass unix:///tmp/app.sock;
                    include uwsgi_params;
                    uwsgi_read_timeout 600;  # Requests can run for a serious long time
            }

3)uwsgi.ini

[uwsgi]
chdir = /path/to/app/
chmod-socket = 777
no-default-app = True
socket = /tmp/app.sock

manage-script-name = True
mount = /dids=did.py
mount = /replicas=replica.py
callable = application

现在,当我让客户端访问 nginx-server-int-01.domain.com 时,一切都正常。在 nginx 的 access.log 中,出现了如下行:

128.142.XXX.XX0 - - [23/Aug/2014:01:29:20 +0200] "POST /dids/attachments HTTP/1.1" 201 17 "-" "python-requests/2.3.0 CPython/2.6.6 Linux/2.6.32-358.23.2.el6.x86_64" "-"
128.142.XXX.XX0 - - [23/Aug/2014:01:29:20 +0200] "POST /dids/attachments HTTP/1.1" 201 17 "-" "python-requests/2.3.0 CPython/2.6.6 Linux/2.6.32-358.23.2.el6.x86_64" "-"
128.142.XXX.XX0 - - [23/Aug/2014:01:29:20 +0200] "POST /dids/user.ogueta/cnt_mc12_8TeV.16304.stream_name_too_long.other.notype.004202218365415e990b9997ea859f20.user/dids HTTP/1.1" 201 17 "-" "python-requests/2.3.0 CPython/2.6.6 Linux/2.6.32-358.23.2.el6.x86_64" "-"
128.142.XXX.XX0 - - [23/Aug/2014:01:29:20 +0200] "POST /replicas/list HTTP/1.1" 200 5282 "-" "python-requests/2.3.0 CPython/2.6.6 Linux/2.6.32-358.23.2.el6.x86_64" "-"
128.142.XXX.XX0 - - [23/Aug/2014:01:29:20 +0200] "POST /replicas/list HTTP/1.1" 200 5094 "-" "python-requests/2.3.0 CPython/2.6.6 Linux/2.6.32-358.23.2.el6.x86_64" "-"
128.142.XXX.XX0 - - [23/Aug/2014:01:29:20 +0200] "POST /replicas/list HTTP/1.1" 200 528 "-" "python-requests/2.3.0 CPython/2.6.6 Linux/2.6.32-358.23.2.el6.x86_64" "-"
128.142.XXX.XX0 - - [23/Aug/2014:01:29:21 +0200] "GET /dids/mc13_14TeV/dids/search?project=mc13_14TeV&stream_name=%2Adummy&type=dataset&datatype=NTUP_SMDYMUMU HTTP/1.1" 401 73 "-" "python-requests/2.3.0 CPython/2.6.6 Linux/2.6.32-358.23.2.el6.x86_64" "-"
128.142.XXX.XX0 - - [23/Aug/2014:01:29:21 +0200] "POST /replicas/list HTTP/1.1" 200 713 "-" "python-requests/2.3.0 CPython/2.6.6 Linux/2.6.32-358.23.2.el6.x86_64" "-"
128.142.XXX.XX0 - - [23/Aug/2014:01:29:21 +0200] "POST /dids/attachments HTTP/1.1" 201 17 "-" "python-requests/2.3.0 CPython/2.6.6 Linux/2.6.32-358.23.2.el6.x86_64" "-"

但是当我切换客户端以对抗 HAProxy(loadbalancer.domain.com:443)时,nginx 的 error.log 显示如下行:

2014/08/23 01:26:01 [error] 1705#0: *21231 open() "/usr/share/nginx/html/dids/attachments" failed (2: No such file or directory), client: 128.142.XXX.XX1, server: localhost, request: "POST /dids/attachments HTTP/1.1", host: "loadbalancer.domain.com"
2014/08/23 01:26:02 [error] 1705#0: *21232 open() "/usr/share/nginx/html/replicas/list" failed (2: No such file or directory), client: 128.142.XXX.XX1, server: localhost, request: "POST /replicas/list HTTP/1.1", host: "loadbalancer.domain.com"
2014/08/23 01:26:02 [error] 1705#0: *21233 open() "/usr/share/nginx/html/dids/attachments" failed (2: No such file or directory), client: 128.142.XXX.XX1, server: localhost, request: "POST /dids/attachments HTTP/1.1", host: "loadbalancer.domain.com"
2014/08/23 01:26:02 [error] 1705#0: *21234 open() "/usr/share/nginx/html/replicas/list" failed (2: No such file or directory), client: 128.142.XXX.XX1, server: localhost, request: "POST /replicas/list HTTP/1.1", host: "loadbalancer.domain.com"
2014/08/23 01:26:02 [error] 1705#0: *21235 open() "/usr/share/nginx/html/dids/attachments" failed (2: No such file or directory), client: 128.142.XXX.XXX, server: localhost, request: "POST /dids/attachments HTTP/1.1", host: "loadbalancer"
2014/08/23 01:26:02 [error] 1705#0: *21238 open() "/usr/share/nginx/html/replicas/list" failed (2: No such file or directory), client: 128.142.XXX.XXX, server: localhost, request: "POST /replicas/list HTTP/1.1", host: "loadbalancer.domain.com"
2014/08/23 01:26:02 [error] 1705#0: *21239 open() "/usr/share/nginx/html/dids/attachments" failed (2: No such file or directory), client: 128.142.XXX.XXX, server: localhost, request: "POST /dids/attachments HTTP/1.1", host: "loadbalancer.domain.com"
2014/08/23 01:26:02 [error] 1705#0: *21242 open() "/usr/share/nginx/html/replicas/list" failed (2: No such file or directory), client: 128.142.XXX.XXX, server: localhost, request: "POST /replicas/list HTTP/1.1", host: "loadbalancer.domain.com"
2014/08/23 01:26:02 [error] 1705#0: *21244 open() "/usr/share/nginx/html/dids/attachments" failed (2: No such file or directory), client: 128.142.XXX.XXX, server: localhost, request: "POST /dids/attachments HTTP/1.1", host: "loadbalancer.domain.com"

如您所见,该请求看起来相同,只有客户端 IP 发生了变化,从客户端主机变为来自 loadbalancer.domain.com 的主机。但无论出于何种原因,ngxin 似乎都认为要提供的是静态文件,最终导致文件未找到消息。

我已经在网上搜索了好几个小时,但到目前为止没有什么收获。任何帮助都非常感谢。

干杯,拉尔夫

答案1

我弄清楚了我的设置中存在什么问题。

正如问题所述,一旦请求从 HAProxy 重定向,nginx 就不会将它们映射到定义的 WSGI 容器,而是尝试提供静态文件。事实证明,这种行为是由于

server_name nginx-server-int-01.domain.com;

我的 nginx - config 中的指令。此指令表示此服务器块仅适用于指向 nginx-server-int-01.domain.com 的请求,通过检查 HTTP 标头字段“host”是否匹配来强制执行。

但发送到 HAProxy 的请求会将“loadbalancer.domain.com”设置为主机字段,而 HAProxy 尽可能透明,在转发 HTTP 请求时不会更新此字段。因此,nginx 收到的带有“loadbalancer.domain.com”的请求与任何定义的服务器指令都不匹配。最终,nginx 决定谨慎行事,并检查静态文件(默认设置),由于这些文件都不存在,因此解析为 404 Not found 响应。

因此,在将我的 nginx.conf 更新为将 WSGI 指令定义为默认值的服务器块后,如果 URI 匹配,它会将每个请求(与主机值无关)视为 WSGI 请求。为此,只需将 server_name 指令替换为以下两行

listen 80 default_server;
server_name _;

希望这对任何人都有帮助。

干杯,拉尔夫

相关内容