Nginx服务器的正向代理服务

Nginx服务器正向代理服务的配置的3个指令

 resolver指令

该指令用于指定DNS服务器的IP地址。DNS服务器的主要工作是进行域名解析,将域名映射为对应的IP地址

resolver address ... [valid=time];

■ address,DNS服务器的IP地址。如果不指定端口号,默认使用53端口。
■ time,设置数据包在网络中的有效时间。
出现该指令的主要原因是,在访问站点时,有很多情况使得数据包在一定时间内不能被传递到目的地,但是又不能让该数据包无期限地存在,于是就需要设定一段时间,当数据包**在这段时间内没有到达目的地,就会被丢弃**,然后发送者会接收到一个消息,并决定是否要重发该数据包。

使用该指令的一个例子如下:


resolver 127.0.0.1 [::1]:5353 valid=30s;

resolver_timeout指令

该指令用于设置DNS服务器域名解析超时时间,语法结构为:

resolver_timeout time;

proxy_pass指令

该指令用于设置代理服务器的协议和地址,它不仅仅用于Nginx服务器的代理服务,更主要的是应用于反向代理服务。该指令的语法结构为:

proxy_pass URL;

其中,URL即为设置的代理服务器协议和地址。在代理服务配置中,该指令配置为

proxy_pass http://$http_host$request_uri;

其中,代理服务器协议设置为HTTP,$http_host 和 $request_uri两个变量是Nginx配置支持的用于自动获取主机和URI的变量。

Nginx服务器正向代理服务的使用

…
    server
    {
      resolver 8.8.8.8;
      listen 82;
      location /
      {
          proxy_pass http://$http_host$request_uri;
        }
    }
    …
  • 设置DNS服务器地址为8.8.8.8,使用默认的53端口作为DNS服务器的服务端口
  • 代理服务的监听端口设置为82端口,Nginx服务器接收到的所有请求都由location块进行过滤处理。
  • resolver指令是必需的,如果没有该指令,Nginx服务器无法处理接收到的域名。
  • 注意:Nginx服务器的代理服务器不支持正向代理HTTPS站点。

Nginx服务器的反向代理服务

Nginx服务器提供的反向代理服务能够同时接收的客户端连接的计算方法为:

worker_processes * worker_connections / 4

配置Nginx服务器反向代理用到的指令配置在Nginx配置文件的http块、server块或者location块中,一般是单独配置一个server块用来设置反向代理服务。这些指令主要由ngx_http_proxy_module模块进行解析和处理。该模块是Nginx服务器的标准HTTP模块。

反向代理的基本指令

proxy_pass指令

指令用来设置被代理服务器的地址,可以是主机名称、IP地址加端口号等形式。其语法结构为:

proxy_pass URL;

其中,URL为要设置的被代理服务器的地址:

  • 包含传输协议、主机名称/IP地址加端口号、URI等要素。
  • 传输协议通常是“http”或者“https://”。
  • 指令同时还接受以“unix”开始的UNIX-domain套接字路径。
proxy_pass http://www.myweb.name/uri; 
proxy_pass http://localhost:8000/uri/; 
proxy_pass http://unix:8000/uri/;

配置一组服务器

如果被代理服务器是一组服务器的话,可以使用upstream指令配置后端服务器组

…
     #配置后端服务器组
    upstream proxy_svrs     
    {
      server http://192.168.1.1:8001/uri/;
      server http://192.168.1.2:8001/uri/;
      server http://192.168.1.3:8001/uri/;
    }
    server
    {
      …
      listen 80;
      server_name  www.myweb.name;
      location /
      {
        proxy_pass  proxy_svrs;                                       #使用服务器组的名称
      }
    }

在组内的各个服务器中都指明了传输协议“http://”,而在proxy_pass指令中就不需要指明了

 URI问题

如果URL中不包含URI,Nginx服务器不会改变原地址的URI;但是如果包含了URI,Nginx服务器将会使用新的URI替代原来的URI

  • proxy_pass中不含有URI
#如果客户端使用http://www.myweb.name:80/server发起请求,该请求
#被配置中显示的location块进行处理,由于proxy_pass指令的URL变量不
#含有URI,所以转向的地址为“http://192.168.1.1:80/server。
    …
    server
    {
      …
      listen 80;
      server_name  www.myweb.name;
      location  /server/
      {
        …
        proxy_pass  http://192.168.1.1;
      }
    }
  • proxy_pass中含有URI
#如果客户端仍然使用“http://www. myweb.name/server/”发起请求,#Nginx服务器将会把地址转向“http://192.168.1.1/loc/”。
    …
    server
    {
      …
      listen 80;
      server_name  www.myweb.name;
      location  /server/
      {
        …
        proxy_pass  http://192.168.1.1/loc/;
      }
    }

小结:在使用proxy_pass指令时,如果不想改变原地址中的URI,就不要在URL变量中配置URI

proxy_pass的URL末尾是否加斜杠“/”

#配置1: proxy_pass http://192.168.1.1; #不包含uri
#配置2: proxy_pass http://192.168.1.1/; #包含了uri:/

在该配置中,location块使用“/”作为uri的值来匹配不包含URI的客户端请求。

# 由于请求URL中不包含URI,因此配置1和配置2的效果是一样的。
# 配置2:
# 因为根据替换逻辑:http://www.myweb.name/index.htm 请求的/,会被替换为/,相当于没有替换。

    …
    server
    {
      …
      listen 80;
      server_name  www.myweb.name;
      #注意location的uri变量
      location  /                                            
      {
        …
        #配置1:  proxy_pass  http://192.168.1.1;
        #配置2:  proxy_pass  http://192.168.1.1/;
      }
    }
# 请求:http://www.myweb.name/server/index.htm

#使用配置1:因为proxy_pass没有uri,所以客户端请求uri不会被替换
#使用配置2:proxy_pass有uri,客户端请求的uri会将(被location中)/server/替换为(proxy_pass的uri)/,转向的URL为“http://192.168.1.1/index.htm。

    …
    server
    {
      …
      listen 80;
      server_name  www.myweb.name;
      location  /server/                                      #注意location的uri变量
      {
        …
        #配置1:  proxy_pass  http://192.168.1.1;
        #配置2:  proxy_pass  http://192.168.1.1/;
      }
    }

proxy_set_header指令

该指令可以更改(ing) Nginx服务器接收到的客户端请求的请求头信息,然后将新的请求头发送给被代理的服务器。其语法结构为:

proxy_set_header field value;

■ field,要更改的信息所在的头域。
■ value,更改的值,支持使用文本、变量或者变量的组合。

什么情况下会导致:ing

通过httpclient请求到nginx时,请求的header出现了丢失的情况?

proxy_ignore_headers指令

通过使用这个指令,可以控制哪些响应头部不会被传递给客户端,从而影响到客户端接收到的响应信息。

proxy_ignore_headers field ...;

# 其中,field为要设置的HTTP响应头的头域,例如“X-Accel-Redirect”、
#“X-Accel-Expires”、“Expires”、“Cache-Control”或“Set-Cookie”等。

例如,想要代理服务器转发请求时忽略掉 Set-Cookie 和 Cache-Control 这两个响应头部,可以这样配置:

location / {
    proxy_pass http://backend_server;
    proxy_ignore_headers Set-Cookie Cache-Control;
}

proxy_timeout

(在客户端或代理服务器)两个成功连续的读(或写)操作之间如果超过timeout时间没有数据传输,链接将关闭

 proxy_timeout 的基本语法

proxy_timeout timeout;

#1.timeout: 指定的超时时间,以秒为单位。可以是整数或者带有小数点的浮点数。

设置代理请求的超时时间为 5 秒:

location / {
    proxy_pass http://backend_server;
    proxy_timeout 5s;
}

proxy_connect_timeout

用于设置代理与后端服务器建立连接时允许的最大时间。

如果在指定的时间内未能成功建立连接,Nginx 将终止连接并返回适当的错误。

设置代理连接建立的超时时间为 3 秒:

location / {     
	proxy_pass http://backend_server;             
    proxy_connect_timeout 3s; 
}

Nginx服务器的负载均衡

Nginx服务器实现负载均衡,主要使用的配置是proxy_pass指令和upsteam指令。

nginx的upstream负载均衡方式

方式

解释

轮询

默认方式

weight

权重方式

ip_hash

依据ip分配方式

least_conn

最少连接方式

 轮询(默认)

每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除

  • 在轮询中,如果服务器down掉了,会自动剔除该服务器。
  • 缺省配置就是轮询策略。
  • 此策略适合服务器配置相当,无状态且短平快的服务使用。

weight

weight 代表权重,默认为1,weight和访问比率成正比,用于后端服务器性能不均的情况。

upstream backServer {
server localhost:8080   weight=2;  #tomcat 7.0
server localhost:8081;  #tomcat 8.0
server localhost:8082   backup;  #tomcat 8.5
server localhost:8083   max_fails=3 fail_timeout=20s;  #tomcat 9.0
}
  1. weight参数用于指定轮询几率,weight的默认值为1
  2. weight的数值与访问比率成正比,比如Tomcat 7.0被访问的几率为其他服务器的两倍。
  • 权重越高分配到需要处理的请求越多。
  • 此策略可以与least_conn和ip_hash结合使用。
  • 此策略比较适合服务器的硬件配置差别比较大的情况。

ip_hash

每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决session的问题。

不管刷新多少遍,始终访问的是同一台tomcat服务器,但当ip_hash到的机器挂掉时,会在剩余的机器中会重新ip_hash选定机器。

upstream backServer{
ip_hash;
server 192.168.203.14:88;
server 192.168.203.15:80;
}
  • 在nginx版本1.3.1之前,不能在ip_hash中使用权重(weight)。
  • ip_hash不能与backup同时使用。
  • 此策略适合有状态服务,比如session。
  • 当有服务器需要剔除,必须手动down掉(这样不利于更新和故障时候的响应)

最少连接least_conn

把请求转发给连接数较少的后端服务器。轮询算法是把请求平均的转发给各个后端,使它们的负载大致相同;但是,有些请求占用的时间很长,会导致其所在的后端负载较高。这种情况下,least_conn这种方式就可以达到更好的负载均衡效果。

upstream backServer{ 
least_conn;
server 127.0.0.1:8080; 
server 127.0.0.1:9090; 
}        

负载均衡常见参数

参数

说明

fail_timeout

与max_fails结合使用。

max_fails

设置在fail_timeout参数设置的时间内最大失败次数,如果在这个时间内,所有针对该服务器的请求都失败了,那么认为该服务器会被认为是停机了。

fail_time

服务器会被认为停机的时间长度,默认为10s。

backup

标记该服务器为备用服务器。当主服务器停止时,请求会被发送到它这里。

down

标记服务器永久停机了。

实现例子

轮询
  • backend服务器组中所有服务器访问优先级由weight设置。
  • 所有访问www.myweb.name(由server_name配置进行匹配)的请求都会在backend服务器组中实现负载均衡。
    …
    #配置后端服务器组
    upstream backend                                         
    {
      server 192.168.1.2:80  weight=5;
      server 192.168.1.3:80  weight=2;
      #默认weight=1
      server 192.168.1.4:80;                                 
    }
    server
    {
      listen 80;
      server_name  www.myweb.name;
      index  index.html  index.htm;
      location  /  {
        proxy_pass  http://backend;
        proxy_set_header  Host  $host;
        …
      }
      …
    }

当有访问(server_name设置的)www.myweb.name的请求时,nginx会将请求转发到backend(通过upstream设置的server列表,根据轮询+权重选出一台)服务器来处理,处理后返回给客户端response。

对特定资源实现负载均衡

根据相同域名的不同URI的请求前缀请求特定资源,实现负载均衡。

    …  #其他配置
     #配置后端服务器组1
    upstream videobackend                                       
    {
      server 192.168.1.2:80;
      server 192.168.1.3:80;
      server 192.168.1.4:80;
    }
    #配置后端服务器组2
    upstream filebackend                                         
    {
      server 192.168.1.5:80;
      server 192.168.1.6:80;
      server 192.168.1.7:80;
    }
    server
    {
      listen 80;
      server_name  www.myweb.name;
      index  index.html  index.htm;
      # location用于接收来自server:www.myweb.name的请求,并根据不同的uri前缀,将请求转发到不同的后端中
      #使用后端服务器组1
      location  /video/  {
        proxy_pass  http://videobackend;                         
        proxy_set_header  Host  $host;
        …
      }
      #使用后端服务器组2
      location  /file/  {
        proxy_pass  http://filebackend;                           
        # 设置header 保留客户端的真实信息                                                  
        proxy_set_header  Host  $host;
        proxy_set_header  X-Real-IP  $remote_addr;
        proxy_set_header  X-Forwarded-For  $proxy_add_x_forwarded_for;
        …
      }
      …
    }

对不同域名实现负载均衡

根据不同的域名+端口定位到请求的资源

    …
    upstream bbsbackend
    {
      server 192.168.1.2:80  weight=2;
      server 192.168.1.3:80  weight=2;
      server 192.168.1.4:80;
    }
    upstream homebackend
    {
      server 192.168.1.4:80;
      server 192.168.1.5:80;
      server 192.168.1.6:80;
    }
     # 开始配置server 1                                                    
    server
    {
      listen 80;
      server_name  home.myweb.name;
      index  index.html  index.htm;
      location  /  {
        proxy_pass  http://homebackend;
        proxy_set_header  Host  $host;
        …
      }
      …
    }
      # 开始配置server 2                                                      
    server
    {
      listen 81;
      server_name  bbs.myweb.name;
      index  index.html  index.htm;
      location  /  {
        proxy_pass  http://bbsbackend;
        proxy_set_header  Host  $host;
        …
      }
      …
    }