nginx 之 Module ngx_http_proxy_module 深入研究

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了nginx 之 Module ngx_http_proxy_module 深入研究相关的知识,希望对你有一定的参考价值。

# 以下只是自己总结,加深记忆


背景前提介绍:


    工作需要,实现对二级nginx反向代理的备份请求;由于国内外网络不稳定原因。


    拓扑:主站(北京BGP) 前端nginx,后端tomcat

          自制CDN(nginx反向代理)

               节点1: HK 香港

               节点2:BM 北美


    问题:BM nginx反向代理 到 北京BGP,由电信骨干网不稳定,时不时丢包与中断。


    解决方案:在广州BGP 增加一个二级nginx反向代理,实现BM nginx反向代理故障,切换备份请求;从而变成了 三级nginx反向代理。


    中间碰到问题:由于广州BGP节点,利用别的业务的资源。80端口被占用的情况,实现三级nginx不同端口之间的反向代理。如果使用同样的端口,部署没有什么问题与难度。


    深入理解nginx server_name,proxy模块,nginx处理请求过程;变量:$hostname,$host,$http_host,$server_name,$server_port,$proxy_host,$proxy_port。


    测试验证,增加nginx log配置信息,增加以上变量,用于观察:


    log_format  main  ‘$remote_addr - $remote_user [$time_local] "$request" ‘

                      ‘$status $body_bytes_sent "$http_referer" ‘

                      ‘"$http_user_agent" "$http_x_forwarded_for" "[$hostname $host $http_host $server_name $server_port $proxy_host $proxy_port]"‘;


    配置命令:server_name

        三种类型的server_name: 精确命名,通配符命名,正则表达式命名

            通配符命名:只能以*开头或结尾,并在.的前面或后面

            正则表达式命令:以~开头标记

        匹配顺序:精确命名 -> *开头通配符命令 -> *结尾通配符命名 —> 正则表达式命名

      

    默认匹配server,当没有以上三种类型匹配到后;第一个定义的server为默认匹配或定义的listen 80 default;为默认匹配。


    基于域名与基于IP的虚拟服务:

        基于IP的虚拟服务:处理请求时,是要根据HTTP包的进入IP(网卡)+ 端口进行 匹配,然后再根据 server_name进行匹配,否则使用默认匹配server。

        基于域名与IP的虚拟服务,都是根据 HTTP包头中的 "host"字段进行区别



    三级(多级)nginx 反向代理的原理,及实现不同端口反向代理。


    BM nginx 80 端口:

    upstrean testweb {

        server test1.test.com:82;

    }


    server {

        listen 80;

        server_name test2.test.com;


        location / {

            proxy_redirect   off;

            proxy_read_timeout 300;

            proxy_set_header Host $host;

            proxy_set_header X-Real-IP $remote_addr;

            proxy_set_header X-Forwarded-For $remote_addr;

            proxy_buffers    32 64k;

            proxy_pass http://testweb;

            expires epoch;

        }

    }

    

    广州 nginx 82 端口:

    

    upstrean testweb {

        server www.test.com;

    }


    server {

        listen 82;

        server_name test1.test.com test2.test.com; 此处需要添加最前面反向代理的访问域名或者IP地址。


        location / {

            proxy_redirect   off;

            proxy_read_timeout 300;

            proxy_set_header Host $host;

            proxy_set_header X-Real-IP $remote_addr;

            proxy_set_header X-Forwarded-For $remote_addr;

            proxy_buffers    32 64k;

            proxy_pass http://testweb;

            expires epoch;

        }

    }


    北京BGP nginx 80 端口:

    

    upstrean testweb {

        server 127.0.0.1:8080;

    }


    server {

        listen 80;

        server_name *.test.com;


        location / {

            proxy_redirect   off;

            proxy_read_timeout 300;

            proxy_set_header Host $host;

            proxy_set_header X-Real-IP $remote_addr;

            proxy_set_header X-Forwarded-For $remote_addr;

            proxy_buffers    32 64k;

            proxy_pass http://testweb;

            expires epoch;

        }

    }


    nginx test2.test.com -> nginx test1.test.com:82 -> nginx www.test.com

    如果 test1.test.com:82,不需要实现访问www.test.com,只需要中转代理的话,由于test2.test.com 与 www.test.com都是80端口, proxy_set_header Host $host;就可以了。否则应该设为:proxy_set_header Host $http_host;

    非默认端口时,nginx 反向代理应该 传送给 tomcat服务 Host有端口,像这样:proxy_set_header Host $http_host;或 proxy_set_header Host $host:$server_port,还可以手动指定:proxy_set_header Host $host:82

   


    变量:$hostname,$host,$http_host,$server_name,$server_port,$proxy_host,$proxy_port

        $hostname: 本机的hostname的值

        $host: http包头中的host值,默认不带端口;可以设置附加端口:proxy_set_header Host $http_host;

        $http_host: client客户端请示地址+端口,一般为:域名:端口

        $server_name:server中定义server_name的值

        $server_port:server中定义listen的值

        $proxy_host: proxy_pass(proxy_pass http://testweb;)中testweb值

        $proxy_port:proxy_pass(proxy_pass http://testweb;)中端口值,默认端口为80;如果把端口定义在upstearm中,$proxy_port的值也是80。$proxy_port取值只取值proxy_pass指令后的端口值,不取upstream中的端口值。


    nginx反向代理请求原理与过程:

      示意:test2.test.com -(nginx反向代理)-> test1.test.com:82 -(nginx反向代理)-> www.test.com -(nginx反向代理)-> tomcat:8080

     

      请求包头处理过程:    

      用户通过浏览器,访问test2.test.com;通过nginx匹配(通$host test2.test.com 匹配server段)后,通过反向代理模块,请求test1.test.com:82,并把用户的请求HTTP包转发给test1.test.com:82的nginx。

      test1.test.com:82的nginx(通$host test2.test.com 匹配server段),进行处理。 接着test1.test.com:82对应的server段,通过反向代理模块,请求www.test.com,并把用户的请求HTTP包转发给www.test.com的nginx。

      www.test.com的nginx,通过nginx匹配(通$host test2.test.com 匹配server段) 后,通过反向代理模块,请求tomcat:8080,并把用户的请求HTTP包转发给tomcat:8080处理。

      tomcat:8080的网站程序,通过$host进行URL地址端口的取值,并构建对应资源URL地址(无端口值时,默认设置80)。由于test2.test.com与www.test.com使用的是默认80端口;proxy_set_header Host $host;用户http请求包头,可以不传送端口值;否则,一定要传送端口值(proxy_set_header Host $http_host;或 proxy_set_header Host $host:$server_por)。

      响应包头处理过程:

      tomcat:8080处理用户HTTP请求包后,返回HTTP响应包,给www.test.com的nginx;它们之间通过tcp链接通讯。

      然后,www.test.com的nginx,把HTTP响应包,返回给test1.test.com的nginx;它们之间通过tcp链接通讯(先前请求时,建立的TCP链接通道)。

      然后,test1.test.com的nginx,把HTTP响应包,返回给test2.test.com的nginx;它们之间通过tcp链接通讯(先前请求时,建立的TCP链接通道)。

      最后,test2.test.com的nginx,把HTTP响应包,返回给用户请求HTTP的客户端;它们之间通过tcp链接通讯(先前请求时,建立的TCP链接通道)。



     How nginx processes a request

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


本文出自 “秋枫鹤泣” 博客,请务必保留此出处http://52python.blog.51cto.com/281874/1793515

以上是关于nginx 之 Module ngx_http_proxy_module 深入研究的主要内容,如果未能解决你的问题,请参考以下文章

[原创]nginx添加module之threads

Nginx模块之Nginx-Ts-Module学习笔记抢险体验

OpenResty之replace-filter-nginx-module

Nginx事件管理之概念描述

Nginx之负载均衡模块 ngx_http_upstream_module

nginx官方模块之http_random_index_module