阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

Nginx常用代理配置

155次阅读
没有评论

共计 4037 个字符,预计需要花费 11 分钟才能阅读完成。

因为业务系统需求,需要对 web 服务作 nginx 代理,在不断的尝试过程中,简单总结了一下常见的 nginx 代理配置。

1. 最简反向代理配置

在 http 节点下,使用 upstream 配置服务地址,使用 server 的 location 配置代理映射。

upstream my_server {server 10.0.0.2:8080;                                                
    keepalive 2000;
}
server {listen       80;                                                         
    server_name  10.0.0.1;                                               
    client_max_body_size 1024M;

    location /my/ {proxy_pass http://my_server/;
        proxy_set_header Host $host:$server_port;
    }
}

通过该配置,访问 nginx 地址 http://10.0.0.1:80/my 的请求会被转发到 my_server 服务地址 http://10.0.0.2:8080/。

需要注意的是,如果按照如下配置:

upstream my_server {server 10.0.0.2:8080;                                                
    keepalive 2000;
}
server {listen       80;                                                         
    server_name  10.0.0.1;                                               
    client_max_body_size 1024M;

    location /my/ {proxy_pass http://my_server;
        proxy_set_header Host $host:$server_port;
    }
}

那么,访问 nginx 地址 http://10.0.0.1:80/my 的请求会被转发到 my_server 服务地址 http://10.0.0.2:8080/my。这是因为 proxy_pass 参数中如果不包含 url 的路径,则会将 location 的 pattern 识别的路径作为绝对路径。

2. 重定向报文代理

即便配置了 nginx 代理,当服务返回重定向报文时(http code 为 301 或 302),会将重定向的目标 url 地址放入 http response 报文的 header 的 location 字段内。用户浏览器收到重定向报文时,会解析出该字段并作跳转。此时新的请求报文将直接发送给服务地址,而非 nginx 地址。为了能让 nginx 拦截此类请求,必须修改重定向报文的 location 信息。

location /my/ {proxy_pass http://my_server;
    proxy_set_header Host $host:$server_port;

    proxy_redirect / /my/;
}

使用 proxy_redirect 可以修改重定向报文的 location 字段,例子中会将所有的根路径下的 url 代理到 nginx 的 /my/ 路径下返回给用户。比如服务返回的重定向报文的 location 原始值为 /login,那么经过 nginx 代理后,用户收到的报文的 location 字段为 /my/login。此时,浏览器将会跳转到 nginx 的 /my/login 地址进行访问。

需要注意的是,服务返回的重定向报文的 location 字段有时会填写绝对路径(包含服务的 ip/ 域名和端口),有时候会填写相对路径,此时需要根据实际情况进行甄别。

location /my/ {proxy_pass http://my_server;
    proxy_set_header Host $host:$server_port;

    proxy_redirect http://my_server/ http://$host:$server_port/my/;
}

上述配置便是将 my_server 服务的根路径下的所有路径代理到 nginx 地址的 /my/ 路径下。当 nginx 配置只有一个 server 时,http://$host:$server_port前缀可以省略。

3. 报文数据替换

使用 nginx 代理最牛(dan)逼(sui)的情况就是 http 响应报文内写死了服务地址或 web 绝对路径。写死服务地址的情况比较少见,但也偶尔存在。最棘手的是写死了 web 绝对路径,尤其是绝对路径都没有公共前缀。举个例子来说:

一般的 web 页面会包含如下类似路径:

  • /public:用于静态页面资源,如 js 脚本 /public/js,样式表 /public/css,图片 /public/img 等。
  • /static:和 /public 类似。
  • /api:用于后台服务 API 接口。
  • /login:用于登录验证。
  • 其他。

对于这样的服务,可能的代理配置如下:

location /my/ {proxy_pass http://my_server/;
    proxy_set_header Host $host:$server_port;

    proxy_redirect / /my/;
}
location /login/ {proxy_pass http://my_server/public;
    proxy_set_header Host $host:$server_port;
}
location /public/ {proxy_pass http://my_server/public;
    proxy_set_header Host $host:$server_port;
}
location /api/ {proxy_pass http://my_server/api;
    proxy_set_header Host $host:$server_port;
}

由于 web 页面或静态资源内写死了类似的绝对路径,那么对于用户来说,通过页面内的链接进行跳转时,都会请求到 nginx 服务对应的路径上。一旦存在另一个服务也包含类似的路径,也需要 nginx 进行代理,那么矛盾就出现了:访问 nginx 的同一个路径下的请求究竟转发给哪一个服务?

要解决这个问题,必须在用户收到报文前,将报文的数据中包含的绝对路径都添加统一的前缀,如 /my/public,/my/api,/my/login,这样 nginx 代理配置则可以简化为:

location /my/ {proxy_pass http://my_server/;
    proxy_set_header Host $host:$server_port;

    proxy_redirect / /my/;
}
location /other/ {proxy_pass http://other_server/;
    proxy_set_header Host $host:$server_port;

    proxy_redirect / /other/;
}

nginx 的 ngx_http_sub_module 模块提供了类似的报文数据替换功能,该模块默认不会安装,需要在编译 nginx 时添加 –with-http_sub_module 参数,或者直接下载 nginx 的 rpm 包。

使用 sub_filter 对数据包进行替换的语法如下:

location /my/ {proxy_pass http://my_server/;
    proxy_set_header Host $host:$server_port;
    
    sub_filter 'href="https://www.linuxidc.com/' 'href="https://www.linuxidc.com/my/';
    sub_filter 'src="https://www.linuxidc.com/' 'src="https://www.linuxidc.com/my/';
    sub_filter_types text/html;
    sub_filter_once  off;
}

上述配置会将 /my/ 下的所有响应报文内容的 href=”https://www.linuxidc.com/ 替换为 href=”/my,以及 src=”https://www.linuxidc.com/ 替换为 src=”/my,即为所有的绝对路径添加公共前缀。

注意,如果需要配置多个 sub_filter,必须保证 nginx 是 1.9.4 版本之上的。

4. 总结

即便如此,sub_filter 也不能解决所有问题。目前流行的 js 框架都会有自动渲染 url 的功能,也就是说,很多绝对路径并非写死在静态页面内,也是由 js 代码框架动态生成的,面对这样的情况,sub_filter 也是无能为力了。对于这样的情况,笔者只能由衷地奉劝,还是安静的改代码吧!

更多 Nginx 相关教程见以下内容

CentOS 6.2 实战部署 Nginx+MySQL+PHP http://www.linuxidc.com/Linux/2013-09/90020.htm

使用 Nginx 搭建 WEB 服务器 http://www.linuxidc.com/Linux/2013-09/89768.htm

搭建基于 Linux6.3+Nginx1.2+PHP5+MySQL5.5 的 Web 服务器全过程 http://www.linuxidc.com/Linux/2013-09/89692.htm

CentOS 6.3 下 Nginx 性能调优 http://www.linuxidc.com/Linux/2013-09/89656.htm

CentOS 6.3 下配置 Nginx 加载 ngx_pagespeed 模块 http://www.linuxidc.com/Linux/2013-09/89657.htm

CentOS 6.4 安装配置 Nginx+Pcre+php-fpm http://www.linuxidc.com/Linux/2013-08/88984.htm

Nginx 安装配置使用详细笔记 http://www.linuxidc.com/Linux/2014-07/104499.htm

Nginx 日志过滤 使��ngx_log_if 不记录特定日志 http://www.linuxidc.com/Linux/2014-07/104686.htm

Nginx 的详细介绍:请点这里
Nginx 的下载地址:请点这里

本文永久更新链接地址:http://www.linuxidc.com/Linux/2016-07/133119.htm

正文完
星哥说事-微信公众号
post-qrcode
 0
星锅
版权声明:本站原创文章,由 星锅 于2022-01-21发表,共计4037字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中