F5社区-F5技术交流中心

理解Nginx之反向代理

2020-03-03 11:57:14

李煜峰

理解Nginx之反向代理

 

 概述


反向代理是指使用代理服务器来接受客户端的请求,然后转发给内网上游web服务器集群,之后再将上游web服务器的响应转发给客户端。在这个过程中,代理服务器对于客户端来说就相当于 web 服务器,上游web服务器对客户端来说是透明的。具体处理流程如图 1 所示。

 

1 Nginx反向代理服务器处理客户端请求流程

 

Nginx 虽然本身支持高并发,而且性能很强劲,但是处理复杂的业务逻辑并不是它的强项。这时会将 Nginx 用作反向代理服务器去接收高并发的请求,然后将请求转发给 Apache  Web 服务器去处理。那么如何使用 Nginx 反向代理这一功能呢,下面我们将介绍一些基本的配置方法。

 


 proxy_pass


首先是 Nginx 反向代理的最基本的配置项proxy_pass

语法:proxy_pass URL;

默认值:无

配置块:location, if in location, limit_except

proxy_pass配置项可以将用户的请求转发给 URL 指定的服务器,其形式有以下几种:

1.          IP或主机名+端口号

proxy_pass http://localhost:8001/uri/;

2.          https

proxy_pass https://localhost:8001/uri/;

3.          UNIX 句柄

proxy_pass http://unix:/tmp/backend.socket:/uri/;(官方写法,尚待验证)

4.          upstream

upstream 和前几个用法都不相同,它是定义一个服务器组,然后Nginx 代理服务器根据默认或指定的负载均衡算法来选择其中之一进行转发。

用法:

upstream my_upstream {

         server localhost:8001;

         server localhost:8002;

}

server {

         location / {

                   proxy_pass http://my_upstream;

         }

}

如果要指定 URI,则可写成如下格式:

proxy_pass http://my_upstream/uri/;

upstream默认负载均衡算法是轮询,除此之外还有根据权重进行轮询的weight,根据用户 IP 哈希选择服务器的 ip_hash等算法。

更加详细的用法可以参考官方文档 http://nginx.org/en/docs/http/ngx_http_upstream_module.html#upstream

 

 proxy_pass 地址末尾斜杠的影响


 Nginx 的配置过程中,地址末尾的斜杠的有时会让人摸不着头脑,但实际上真正造成 proxy_pass代理规则不同的是末尾有无 uri,而不是有无斜杠。也就是说 proxy_pass可以分为两种情况:一种是只有ip+port,比如http://localhost:8080;另一种是除了 ip+port外,还有资源标识符uri,包括单一的一个斜杠,比如 localhost:8000/ localhost:8000/test 都属于这种情况。

 


 2 proxy_pass的两种形式

 

下面我们将通过 8 个小例子详细分析一下 proxy_pass 的这两种形式。

在看例子之前,要明确的一点是location 默认的匹配规则是前缀匹配,和^~类似,但是它的优先级在正则表达式之后。

 

1. proxy_pass url只有ip+port,此时将保留 location 中的 uri

比如:

location /proxy1 {

         proxy_pass http://localhost:8001;

}

当访问http://localhost/proxy1/my_web/ ,将被代理为 http://localhost:8001/proxy1/my_web/。其最终代理url 生成规则为:proxy_passurl + 访问地址的 uri,也就是 http://localhost:8001 + /proxy1/my_web/ 

 

location /proxy2/ {

         proxy_pass http://localhost:8001;

}

http://localhost/proxy2/my_web/ ->  http://localhost:8001/proxy2/my_web/,这种情况最终代理url是由http://localhost:8001 + /proxy2/my_web/ 组装而成,效果和上一个例子相同。

 

2. proxy_pass url末尾带 uri匹配到的location中的uri会被去除掉

location /proxy3 {

         proxy_pass http://localhost:8001/;

}

http://localhost/proxy3/my_web/ ->  http://localhost:8001//my_web/http://localhost:8001/ + /my_web/,根据构造规则,端口号后产生两个斜杠,但此时是依然能正确访问的。

 

location /proxy4/ {

         proxy_pass http://localhost:8001/;

}

http://localhost/proxy4/my_web/ ->  http://localhost:8001/my_web/http://localhost:8001/ + my_web/ 。

 

location /proxy5 {

         proxy_pass http://localhost:8001/test;

}

http://localhost/proxy5/my_web/ ->  http://localhost:8001/test/my_web/http://localhost:8001/test + /my_web/ 。

 

location /proxy6/ {

         proxy_pass http://localhost:8001/test;

}

http://localhost/proxy6/my_web/ ->  http://localhost:8001/testmy_web/http://localhost:8001/test + my_web/,此情况容易产生 404错误,需要注意。

 

location /proxy7 {

         proxy_pass http://localhost:8001/test/;

}

http://localhost/proxy7/my_web/ ->  http://localhost:8001/test//my_web/http://localhost:8001/test/ + /my_web/,此时类似例产生了两个斜杠。

 

location /proxy8/ {

         proxy_pass http://localhost:8001/test/;

}

http://localhost/proxy8/my_web/ ->  http://localhost:8001/test/my_web/http://localhost:8001/test/ + my_web/

 

总的来说,当 proxy_pass 的url末尾带 uri 时,会先将访问网址的uri去掉 location 匹配的部分,然后拼装在 proxy_pass的 url 后面;当proxy_pass的 url 末尾不带uri时,会将访问网址的 uri 直接拼装在 proxy_pass的 url 后面。

刚开始在配置 proxy_pass时,被斜杠搞的晕头转向,一度觉得这是个玄学配置项。后来查看了一些资料和文档,反复做了一些实验之后,发现还是有迹可循的,这样一下子就清晰了。

 


 重定向和proxy_redirect


当上游 web服务器返回的是重定向(HTTP 状态码为 301  302)或刷新请求时,proxy_redirect可以修改其 HTTP 头部的location 或者 refresh 字段来满足我们的需要。

语法:proxy_redirect default;

            proxy_redirect off;

            proxy_redirect redirect replacement;

默认:proxy_redirect default;

配置块:http, server, location

 


 3 Nginx配置项proxy_redirect处理过程

 

比如proxy_redirect配置为 proxy_redirect http://localhost:8000/two/ http://frontend/one/;

Location: http://localhost:8000/two/some/uri/ 将被修改为 Location: http://frontend/one/some/uri/”

 

当使用默认配置时,会根据当前location配置项和 proxy_pass 的配置重组来修改 location 的值。以下两种形式是等效的。

location /one/ {

    proxy_pass     http://upstream:port/two/;

    proxy_redirect default;

}


location /one/ {

    proxy_pass     http://upstream:port/two/;

    proxy_redirect http://upstream:port/two/ /one/; 

}


Nginx 资源缺失时的重定向:

Nginx 服务器接收到的url  http://ip:port/my_web时,会先在html目录下寻找my_web文件,如果没有 my_web文件但是有名为my_web的目录,则会返回 301 重定向状态码,并且设置响应头字段 location 的值为 host_ip:server_port/my_web/ 。如果此时我们在 nginx 和服务器之间做了端口映射,那么 location 中的端口号对客户端来说是无效的,就会造成客户端无法访问重定向后的网址。此时则可以使用 proxy_redirect来修改 location 的内容。

下面我们来实验一下这个过程。

实验环境是centos容器,宿主机的 ip 10.250.16.146,端口映射关系为 8080:80

配置代码:

server {

        listen       80;

        server_name  localhost;

        location /proxy/ {

                proxy_pass http://localhost:8001/;

                    proxy_redirect off;

                    #proxy_redirect default;

                    #proxy_redirect http://localhost:8001/ /proxy/;

                    #proxy_redirect http://localhost:8001/ http://$http_port/proxy/; #使用 nginx 变量$http_port来获取请求HTTPip 和端口号

        }

        location / { 

         }

}

server {

        listen       8001;

        server_name  10.250.16.146:8080;

        location / {

        }

}

如代码所示,我们实验了四种 proxy_redirect配置,其实验结果如下:

1. proxy_redirect off;



2. proxy_redirect default;



3. proxy_redirect http://localhost:8001/ /proxy/;



4. proxy_redirect http://localhost:8001/ http://$http_port/proxy/;



其中第四种能够达到我们的效果,第二和第三种效果是相同的。

 

 其他反向代理相关命令

 

除了上述命令外,proxy 模块还有其他一些命令可以使用。如修改协议名的proxy_method,隐藏 HTTP头部字段的proxy_hide_deader,显示 HTTP 头部字段的 proxy_pass_header等命令。更加详细的内容可以在官方文档 http://nginx.org/en/docs/http/ngx_http_proxy_module.html 中查看。

 

 参考

《深入理解 Nginx:模块开发与架构解析》

http://nginx.org/en/docs/






发布评论 加入社群

发布评论

秦溱 2020-03-05 15:48:33 0

李煜峰 回复 秦溱 : 回复评论

相关文章

国内环境下ubuntu22.04+kubeadm搭建v1.27.2多节点k8s集群

宗兆伟

2023-06-16 07:12:11 277

更改 kibana 中图表的 index-pattern

李煜峰

2020-05-18 09:41:35 2046

Nginx内存池现实机制

皮皮鲁

2020-05-17 19:32:13 720

Login

手机号
验证码
© 2019 F5 Networks, Inc. 版权所有。京ICP备16013763号-1