Skip to content

反向代理

使用proxy_pass指令,在ngx_http_proxy_module模块下,其中有具体用法和相关文档

首先给出小结:

情形A和情形B进行对比,可以知道proxy_pass后带一个URI,可以是斜杠(/)也可以是其他uri,对后端request_uri变量的影响。 情形D说明,当location为正则表达式时,proxy_pass不能包含URI部分。 情形E通过变量($request_uri, 也可以是其他变量),对后端的request_uri进行改写。 情形F和情形G通过rewrite配合break标志,对url进行改写,并改写后端的request_uri。需要注意,proxy_pass地址的URI部分在情形G中无效,不管如何设置,都会被忽略。

nginx
server {
    listen      80;
    server_name www.test.com;
 
    # 情形A
    # 访问 http://www.test.com/testa/aaaa
    # 后端的request_uri为: /testa/aaaa
    location ^~ /testa/ {
        proxy_pass http://127.0.0.1:8801;
    }
    
    # 情形B
    # 访问 http://www.test.com/testb/bbbb
    # 后端的request_uri为: /bbbb
    location ^~ /testb/ {
        proxy_pass http://127.0.0.1:8801/;
    }
 
    # 情形C
    # 下面这段location是正确的
    location ~ /testc {
        proxy_pass http://127.0.0.1:8801;
    }
 
    # 情形D
    # 下面这段location是错误的
    #
    # nginx -t 时,会报如下错误: 
    #
    # nginx: [emerg] "proxy_pass" cannot have URI part in location given by regular 
    # expression, or inside named location, or inside "if" statement, or inside 
    # "limit_except" block in /opt/app/nginx/conf/vhost/test.conf:17
    # 
    # 当location为正则表达式时,proxy_pass 不能包含URI部分。本例中包含了"/"
    location ~ /testd {
        proxy_pass http://127.0.0.1:8801/;   # 记住,location为正则表达式时,不能这样写!!!
    }
 
    # 情形E
    # 访问 http://www.test.com/ccc/bbbb
    # 后端的request_uri为: /aaa/ccc/bbbb
    location /ccc/ {
        proxy_pass http://127.0.0.1:8801/aaa$request_uri;
    }
 
    # 情形F
    # 访问 http://www.test.com/namea/ddd
    # 后端的request_uri为: /yongfu?namea=ddd
    location /namea/ {
        rewrite    /namea/([^/]+) /yongfu?namea=$1 break;
        proxy_pass http://127.0.0.1:8801;
    }
 
    # 情形G
    # 访问 http://www.test.com/nameb/eee
    # 后端的request_uri为: /yongfu?nameb=eee
    location /nameb/ {
        rewrite    /nameb/([^/]+) /yongfu?nameb=$1 break;
        proxy_pass http://127.0.0.1:8801/;
    }
 
    access_log /data/logs/www/www.test.com.log;
}
 
server {
    listen      8801;
    server_name www.test.com;
    
    root        /data/www/test;
    index       index.php index.html;
 
    rewrite ^(.*)$ /test.php?u=$1 last;
 
    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_pass unix:/tmp/php-cgi.sock;
        fastcgi_index index.php;
        include fastcgi.conf;
    }
 
    access_log /data/logs/www/www.test.com.8801.log;
}

负载均衡

相关的指令在ngx_http_upstream_module中,详情请查看文档

其中定义upstream的语句需要写到http模块下

示例一

nginx
http {
  # 不设置负载均衡策略默认为轮训,每个server的weight为1
  upstream backend {
    server backend1.example.com;
    server backend2.example.com;
    server backend3.example.com;
  }
  server {
    listen 80;

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

该示例将所有到80端口的请求全部转发到backend中去

示例二

nginx
http {
  upstream backend {
    server backend1.example.com weight=5;
    server backend2.example.com weight=3;
    server backend3.example.com weight=2;
  }

  server {
    listen 80;

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

以上将设置权重,将请求按照5:3:1的比例来进行分配

示例三

nginx
http {
  upstream backend {
    server backend1.example.com fail_timeout=30s max_fails=3 ;
    server backend2.example.com backup;
    server backend3.example.com backup;
  }

  server {
    listen 80;

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

使用了fail_timeout参数为后端服务器配置故障超时时间,使用max_fails设置最大失败次数为3。如果某个后端服务器在出现3次故障,Nginx将会将其标记为不可用,并将不再向其转发请求,过了30秒后再向其转发请求。此外,还使用了backup参数来指定一个备用服务器,当所有主服务器都不可用时,Nginx会将请求转发到备用服务器。这种方式可以提高服务的可用性,防止因为某个服务器故障而导致整个服务不可用的情况发生。

示例四

nginx
http {
  upstream backend {
    hash $request_uri;
    server backend1.example.com;
    server backend2.example.com;
    server backend3.example.com;
  }

  server {
    listen 80;

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

在这个例子中,upstream指令使用了hash方法,并使用**$request_uri**变量作为哈希键值。当客户端发送请求时,Nginx会根据请求的URI计算哈希值,并将该请求转发到哈希值对应的后端服务器上。这样做可以确保相同的请求总是被转发到同一个后端服务器上,从而实现会话一致性。

需要注意的是,使用hash方法进行负载均衡可能会导致负载不均衡的情况。例如,如果某个URI的请求量非常大,那么对应的后端服务器可能会承担更大的负载。因此,在使用hash方法进行负载均衡时,需要仔细选择哈希键值,以避免出现负载不均衡的情况。