前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Nginx - URL的微妙差异:Nginx斜杠魔法

Nginx - URL的微妙差异:Nginx斜杠魔法

作者头像
小小工匠
发布2024-05-26 13:47:45
690
发布2024-05-26 13:47:45
举报
文章被收录于专栏:小工匠聊架构小工匠聊架构

Nginx proxy_pass 指令

https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_pass

语境:在location, if in location, limit_except中使用

该指令设置代理服务器的协议和地址,以及可选的URI以映射到一个location。作为协议,可以指定“http”或“https”。地址可以是域名或IP地址,以及一个可选的端口:

代码语言:javascript
复制
proxy_pass http://localhost:8000/uri/;

或者作为UNIX域套接字路径,在“unix”后用冒号括起来:

代码语言:javascript
复制
proxy_pass http://unix:/tmp/backend.socket:/uri/;

如果一个域名解析到多个地址,所有地址将以轮询方式使用。此外,地址可以指定为服务器组。

参数值可以包含变量。在这种情况下,如果地址指定为域名,首先在描述的服务器组中查找该名称,如果未找到,则使用解析器确定。

请求的URI传递到服务器的方式如下:

如果proxy_pass指令带有URI,当请求传递到服务器时,匹配location的标准化请求URI部分将被指令中指定的URI替换:

代码语言:javascript
复制
location /name/ {
    proxy_pass http://127.0.0.1/remote/;
}

如果proxy_pass未带URI,原始请求URI将按客户端发送的形式传递到服务器,或者在处理更改的URI时传递完整的标准化请求URI:

代码语言:javascript
复制
location /some/path/ {
    proxy_pass http://127.0.0.1;
}

在1.1.12版本之前,如果proxy_pass未带URI,原始请求URI可能会在某些情况下被传递,而不是更改后的URI。

在某些情况下,无法确定要替换的请求URI部分:

当location使用正则表达式指定时,或者在命名location中。 在这些情况下,proxy_pass应不带URI指定。

当使用rewrite指令在代理location内更改URI时,并且同一配置将用于处理请求(break):

代码语言:javascript
复制
location /name/ {
    rewrite    /name/([^/]+) /users?name=$1 break;
    proxy_pass http://127.0.0.1;
}

在这种情况下,指令中指定的URI将被忽略,完整的更改请求URI将传递到服务器。

使用变量在proxy_pass中:

代码语言:javascript
复制
location /name/ {
    proxy_pass http://127.0.0.1$request_uri;
}

在这种情况下,如果指令中指定了URI,它将按原样传递到服务器,替换原始请求URI。

WebSocket代理需要特殊配置,并且从1.3.13版本开始支持。


  1. proxy_pass指令的基本用法:定义代理服务器的协议和地址,并可选择指定URI。当指定URI时,请求的匹配部分会被替换;未指定URI时,原始请求保持不变。
  2. 使用UNIX域套接字:可以通过unix:/path/to/socket格式指定UNIX域套接字路径,这在高性能场景中非常有用。
  3. 轮询方式使用多地址:当域名解析为多个IP地址时,Nginx会轮询这些地址,提升负载均衡能力。
  4. 处理正则表达式和命名location:对于正则表达式和命名location,proxy_pass应不带URI。
  5. rewrite指令的配合:在使用rewrite更改URI时,proxy_pass忽略指定的URI,使用修改后的完整URI。
  6. 使用变量:可以在proxy_pass中使用变量,提供更大的灵活性。
  7. WebSocket支持:从1.3.13版本开始,Nginx支持WebSocket代理,需要特殊配置。

尾加 / 和不加 / 的区别

在 Nginx 配置中,proxy_pass 指令用于将请求转发到后端服务器。结尾加 / 和不加 / 有以下区别:

不加 /

不改变请求的 URI 路径。

请求中的路径直接附加在 proxy_pass 后指定的 URL 后面。

示例:

代码语言:javascript
复制
location /api {
    proxy_pass http://backend;
}

如果客户端请求的是 /api/test,则请求会转发到 http://backend/api/test

/

移除匹配部分路径,再将剩余路径附加到 proxy_pass 后的 URL。

示例:

代码语言:javascript
复制
location /api/ {
    proxy_pass http://backend/;
}

如果客户端请求的是 /api/test,则请求会转发到 http://backend/test

详细解释

假设 Nginx 配置文件如下:

代码语言:javascript
复制
location /api {
    proxy_pass http://backend;
}

location /api/ {
    proxy_pass http://backend/;
}
  • 请求 http://example.com/api/test
    • 使用 location /api 匹配并使用 proxy_pass http://backend,最终转发到 http://backend/api/test
    • 使用 location /api/ 匹配并使用 proxy_pass http://backend/,最终转发到 http://backend/test
  • 请求 http://example.com/api/
    • 使用 location /api 匹配并使用 proxy_pass http://backend,最终转发到 http://backend/api/
    • 使用 location /api/ 匹配并使用 proxy_pass http://backend/,最终转发到 http://backend/

实际应用中的考虑

  1. 路径一致性:根据后端服务器的路径结构决定是否需要保留或修改请求路径。
  2. 避免路径混淆:确保转发后的路径和后端服务能够正确处理对应的 URI。
  3. 调试和测试:在设置完成后,通过实际请求测试确认路径转发是否符合预期。

小结

  • 不加 /:保留并直接附加请求路径。
  • /:移除匹配路径,附加剩余路径。

测试

Nginx 配置

根据需求,编写合适的 Nginx 配置文件。下面给出几个常见的配置示例:

示例 1:保留路径

如果需要将前端 /api 的请求路径直接转发到后端 http://backend/api

代码语言:javascript
复制
location /api {
    proxy_pass http://backend;
}
示例 2:移除路径前缀

如果需要将前端 /api 的请求路径移除 /api 前缀后转发到后端 http://backend

代码语言:javascript
复制
location /api/ {
    proxy_pass http://backend/;
}

测试方案

测试计划
  • 测试路径保留:发送请求到前端 /api/test,检查后端是否接收到 http://backend/api/test
  • 测试路径移除:发送请求到前端 /api/test,检查后端是否接收到 http://backend/test
测试工具

可以使用以下工具进行测试:

  • cURL:命令行工具,用于发送 HTTP 请求。
  • Postman:图形化工具,适合进行复杂的 HTTP 请求测试。
  • 浏览器:适合简单的 GET 请求测试。

实际测试

配置 Nginx

编辑 Nginx 配置文件

代码语言:javascript
复制
sudo nano /etc/nginx/nginx.conf

添加如下配置:

代码语言:javascript
复制
http {
    ...
    server {
        listen 80;
        server_name example.com;

        location /api {
            proxy_pass http://backend;
        }

        location /api/ {
            proxy_pass http://backend/;
        }
    }
}

重启 Nginx

代码语言:javascript
复制
sudo systemctl restart nginx
执行测试

路径保留测试

代码语言:javascript
复制
curl -i http://example.com/api/test
  • 检查后端日志或其他方式确认请求路径是否为 http://backend/api/test

路径移除测试

代码语言:javascript
复制
curl -i http://example.com/api/test
  • 检查后端日志或其他方式确认请求路径是否为 http://backend/test
调试和验证
  • 如果请求未按预期转发,请检查 Nginx 配置是否正确,重启 Nginx 服务,并重新执行测试。
  • 查看 Nginx 和后端服务器日志,确认请求路径和响应状态码是否正确。

安全性和优化

  1. 分析测试结果:检查测试中的任何错误或异常。
  2. 调试路径转发:调整 Nginx 配置以解决路径转发问题。
  3. 性能优化:优化 Nginx 配置以提升性能。
  4. 安全性优化:加强 Nginx 配置的安全性。
  5. 验证和确认:重新测试以确认配置的正确性和优化效果。

1. 分析测试结果

检查测试日志
  • Nginx 访问日志/var/log/nginx/access.log
  • Nginx 错误日志/var/log/nginx/error.log
  • 后端服务器日志:检查请求路径和响应状态码
常见问题
  • 请求路径不正确:可能是 proxy_pass 配置不当。
  • 404 错误:请求未找到,检查路径是否正确。
  • 502 错误:后端服务器未响应,检查后端服务器状态。

2. 调试路径转发

调整 Nginx 配置

根据测试结果,调整 Nginx 配置:

确保路径保留

代码语言:javascript
复制
location /api {
    proxy_pass http://backend;
}
  • 适用于希望保留请求路径的情况。

移除路径前缀

代码语言:javascript
复制
location /api/ {
    proxy_pass http://backend/;
}
  • 适用于希望移除请求路径前缀的情况。
重新加载 Nginx 配置

每次修改配置后,重新加载 Nginx:

代码语言:javascript
复制
sudo nginx -s reload

3. 性能优化

启用缓存

Nginx 可以缓存后端响应以提升性能:

代码语言:javascript
复制
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m inactive=60m;
server {
    ...
    location /api/ {
        proxy_cache my_cache;
        proxy_pass http://backend/;
    }
}
连接池和保持连接

保持后端连接以减少连接开销:

代码语言:javascript
复制
http {
    ...
    upstream backend {
        server backend1.example.com;
        keepalive 32;
    }
    server {
        ...
        location /api/ {
            proxy_http_version 1.1;
            proxy_set_header Connection "";
            proxy_pass http://backend;
        }
    }
}

4. 安全性优化

使用 SSL/TLS

启用 HTTPS 以确保传输安全:

代码语言:javascript
复制
server {
    listen 443 ssl;
    server_name example.com;

    ssl_certificate /etc/nginx/ssl/example.com.crt;
    ssl_certificate_key /etc/nginx/ssl/example.com.key;

    location /api/ {
        proxy_pass http://backend/;
    }
}
限制访问

限制某些路径的访问:

代码语言:javascript
复制
location /api/secret {
    allow 192.168.1.0/24;
    deny all;
    proxy_pass http://backend/;
}
防止请求伪造

设置适当的请求头:

代码语言:javascript
复制
location /api/ {
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_pass http://backend/;
}

5. 验证和确认

重新测试配置
  • 使用前述的测试工具(cURL、Postman、浏览器)重新测试路径转发。
  • 确认请求路径和响应均符合预期。
性能和安全测试
  • 使用工具如 ab(ApacheBench)进行压力测试。
  • 使用 sslscanQualys SSL Labs 测试 SSL 配置。
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-05-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Nginx proxy_pass 指令
  • 尾加 / 和不加 / 的区别
    • 详细解释
      • 实际应用中的考虑
        • 小结
        • 测试
          • Nginx 配置
            • 示例 1:保留路径
            • 示例 2:移除路径前缀
          • 测试方案
            • 测试计划
            • 测试工具
          • 实际测试
            • 配置 Nginx
            • 执行测试
            • 调试和验证
        • 安全性和优化
          • 1. 分析测试结果
            • 检查测试日志
            • 常见问题
          • 2. 调试路径转发
            • 调整 Nginx 配置
            • 重新加载 Nginx 配置
          • 3. 性能优化
            • 启用缓存
            • 连接池和保持连接
          • 4. 安全性优化
            • 使用 SSL/TLS
            • 限制访问
            • 防止请求伪造
          • 5. 验证和确认
            • 重新测试配置
            • 性能和安全测试
        相关产品与服务
        腾讯云服务器利旧
        云服务器(Cloud Virtual Machine,CVM)提供安全可靠的弹性计算服务。 您可以实时扩展或缩减计算资源,适应变化的业务需求,并只需按实际使用的资源计费。使用 CVM 可以极大降低您的软硬件采购成本,简化 IT 运维工作。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档