V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
NGINX
NGINX Trac
3rd Party Modules
Security Advisories
CHANGES
OpenResty
ngx_lua
Tengine
在线学习资源
NGINX 开发从入门到精通
NGINX Modules
ngx_echo
luxu
V2EX  ›  NGINX

为什么 NGINX 使用自定义变量代理 ws 会异常?

  •  
  •   luxu · 8 天前 · 702 次点击

    之前一直用同样的方式连接后端服务, 是正常使用的。 如

    location ^~/prod-api/ {
    	    proxy_pass http://$api_host:$api_port;
    	    ......
    	}
    

    异常情况:

    连接 http://$api_host:8877/ws/ 就会异常

    server {
            listen    443 ssl;
            set $api_host api;
            ..........
    
    location  /ws/ {
                proxy_pass http://$api_host:8877/ws/;
                proxy_http_version 1.1;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection "Upgrade";
                proxy_connect_timeout 90s;
                proxy_send_timeout 120s;
                proxy_read_timeout 120s;
                send_timeout 120s;
            }
    }
    

    正常情况:

    设置 http://api:8877/ws/ 正常

    server {
            listen    443 ssl;
            set $api_host api;
            ..........
    
    location  /ws/ {
                proxy_pass http://api:8877/ws/;
                proxy_http_version 1.1;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection "Upgrade";
                proxy_connect_timeout 90s;
                proxy_send_timeout 120s;
                proxy_read_timeout 120s;
                send_timeout 120s;
            }
    }
    

    在 nginx 容器内两种设置的抓包截图: https://imgur.com/a/XzyNFQ6

    搞不清楚是什么原因导致这种情况,为什么不能这样配。想请教下大家

    第 1 条附言  ·  7 天前

    贴上完整配置

      server {
           listen    443 ssl;
           client_max_body_size 20M;
           index index.html;
           ssl_certificate /etc/nginx/templates/1.pem;
           ssl_certificate_key /etc/nginx/templates/1-key.pem;
           ssl_session_timeout 5m;
           ssl_protocols TLSv1.2;
           ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
           ssl_prefer_server_ciphers on;
    
           server_name  ${NGINX_HOST};
           index index.html;
           set $api_port 8877;
           set $api_host api;
           #add_header Access-Control-Allow-Origin *;
           #add_header Access-Control-Allow-Credentials true;
           #add_header Access-Control-Allow-Methods GET,POST;
           location / {
             expires off;
             add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0";
         	  #try_files $uri $uri/ /index.html;
             index index.html;
             root   /www/dist/;
             server_tokens off;
    	}
    
           location  /ws/ {
               proxy_pass http://$api_host:8877/ws/;
               proxy_http_version 1.1;
               proxy_set_header Upgrade $http_upgrade;
               proxy_set_header Connection "Upgrade";
               proxy_connect_timeout 90s;
               proxy_send_timeout 120s;
               proxy_read_timeout 120s;
               send_timeout 120s;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded $proxy_add_x_forwarded_for;
           }
    
           location ^~/prod-api/ {
        rewrite ^/prod-api/(.*)$ /$1 break;
        proxy_set_header X-Forwarded-Proto $scheme;
    #	    proxy_redirect off;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded $proxy_add_x_forwarded_for;
        proxy_pass http://$api_host:$api_port;
           字数超了。。。。。。。。
               }
       }
    }
    
    5 条回复    2024-06-28 11:00:35 +08:00
    msg7086
        1
    msg7086  
       7 天前
    set 指令可能是在 proxy_pass 之后执行的。
    纯粹猜测,你可以做做实验或者查一下资料。

    Nginx 的配置文件,归根结底是配置而不是程序,不要总是期望写在上面的会比写在下面的早执行。
    msg7086
        2
    msg7086  
       7 天前
    另外你可以看看能不能用 upstream 代替 set 来设置变量。upstream 应该是在很靠前的阶段执行的。
    rrfeng
        3
    rrfeng  
       7 天前
    完整配置贴出来看看
    Hanada
        4
    Hanada  
       1 天前   ❤️ 1
    proxy_pass 的值有变量的话 nginx 的处理逻辑是不一样的。如果有接变量的话,nginx 不会再帮你附加原始请求 uri 进去,所以你异常那个就变成固定使用/ws/回上层了。如果你一定要用变量,可以考虑这样写
    proxy_pass http://$api_host:8877$request_uri;
    另外不建议无脑给 Connection 头写死设置 Upgrade ,可以参考 nginx 官方第二种写法,用 map 来指定
    https://nginx.org/en/docs/http/websocket.html
    luxu
        5
    luxu  
    OP
       2 小时 42 分钟前
    @Hanada 非常感谢, 解决了我的问题。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   4648 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 05:43 · PVG 13:43 · LAX 22:43 · JFK 01:43
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.