7.Nginx代理服务

239 阅读4分钟

7.1 正/反向代理概念

1.网关

网关一般用于广域网、局域网等的互联,是连通外网的通道。网关可以理解成我们上网的路由器(wifi)一般,我们想要上网就要连接wifi,然后wifi去对接外部的网络。

2.代理服务器

image.png

nginx代理服务器与网关类似,也是作为网络传输的中转站。

正向代理 / 反向代理 都是为了让用户能够实现上网,只是实现的方式不同而已。

  • 正向代理:服务用户为主,将局域网中的用户通过代理服务器进入外网中想要访问的站点,实现上网;
  • 反向代理:服务站点为主,将站点放到代理服务器中,用户访问站点时直接接入服务器,服务器将用户转到对应站点的资源让用户访问。(此时对代理服务器来说,站点是在局域网内,用户是外网)

image.png

简单理解:出门买菜

正向代理: 出门 —》 菜市场 —》找到想买的菜

反向代理: 出门 —》 外卖小哥直接送菜到家门口给你 (此处省略了外卖小哥去菜市场买菜)

7.2 正向代理服务

7.2.1 配置指令

1. resolver指令
  • 说明:用于指定DNS服务器的IP地址。

    DNS服务器:进行域名解析,将域名映射为对应IP地址

  • 语法:resolver address ... [valid=time];

    address:DNS服务器IP地址,端口号默认为53

    time:设置数据包在网络中的有效时间

2. resolver_timeout 指令
  • 说明:用于设置DNS服务器域名解析超时时间。
  • 语法:resolver_timeout time;
3. proxy_pass 指令
  • 说明:用于设置代理服务器协议、地址

  • 语法:proxy_pass URL;(URL为代理服务器协议和地址)

    eg: proxy_pass http://$http_host$request_ruri;

    协议设置为 HTTP

    httphosthttp_host 和 request_uri 是nginx用于自动获取主机和URI的变量

7.2.2 正向代理使用

代理服务功能一般配置到一个server中,并且不能出现server_name指令(虚拟主机的名称/IP),resolve指令是必要的,用来处理接收到的域名。

server
{
    resolver 8.8.8.8;  #设置DNS服务地址
    listen 82;         #代理服务器的监听端口
    location / {       #服务器接收到的请求通过 location块进行过滤处理
        proxy_pass http://$http_host$request_uri;
    }
}

7.3 反向代理服务

7.3.1 基本指令

1. proxy_pass指令

用来设置被代理服务器地址(主机名/IP加端口)

  • 语法:proxy_pass URL;

  • 常用方式

    1. 被代理的服务器是一组服务器:使用 upstream指令

      ...
      upstream proxy_svrs        #配置后端服务组
      {
          server http://192.168.1.1:8080/uri;
          server http://192.168.1.1:800/uri;
          server http://192.168.1.1:80/uri;
      }
      server{
          ...
          listen 80;
          server_name www.gjh.name;
          location /{
          proxy_pass proxy_svrs;          ## 使用服务组的名称
          }
      }
      
    2. 对于服务组的协议部分若是相同,可以抽取出来:

      ...
      upstream proxy_svrs   
      {
          server 192.168.1.1:8080/uri;
          server 192.168.1.1:800/uri;
          server 192.168.1.1:80/uri;
      }
      server{
          ...... #与1.的配置相同
              proxy_pass http://proxy_svrs;    #此处将http协议抽取出来
      }
      
    3. 若是代理的URL中含有URI的,nginx会将代理中的URI替换原来的URI

      server{
      ...
              location /server/{   #原本的URI: server/
              ....
                  #访问地址:http://192.168.1.1/loc/
                  proxy_pass http://192.168.1.1/loc/;  
              
                  #访问地址:http://192.168.1.1/server/
                  proxy_pass http://192.168.1.1;
                  
                  #访问地址:http://192.168.1.1/
                   proxy_pass http://192.168.1.1/;
          }
      }
      
2. proxy_hide_header指令
  • 说明:用于设置服务器在发送HTTP响应时,隐藏一些头域信息

  • 语法:proxy_hide_header field;

    field:需要隐藏的头域

  • 使用区域:http、server、location

3.proxy_pass_header指令
  • 说明:默认情况下,nginx在发送响应报文时,报文头不包含Date、Server、X-Accel等被代理服务器的头域信息,该指令可以设置这些头域信息被发送。
  • 语法:proxy_pass_header field; (field:需要发送的头域)
  • 使用区域:http、server、location
4.proxy_pass_request_body指令
  • 说明:配置是否将客户端请求的请求体发送给代理服务器

  • 语法:proxy_pass_request_body on|off;

    默认是 on 开启

  • 使用区域:http、server、location

5.proxy_pass_request_headers指令
  • 说明:配置是否将客户端请求的请求头发给代理服务器
  • 语法:proxy_pass_body on|off;(默认为 on开启)
  • 使用区域:http、server、location
6.proxy_set_header指令
  • 说明:更改nginx接收到客户端请求的请求头信息,将新的请求头发给被代理服务器

  • 语法:proxy_set_header field value

    field:要更改的信息所在的头域

    value:更改的值,支持用文本、变量及其组合

  • 该指令的设置:

    # 默认的设置
    proxy_set_header Host $proxy_host;
    proxy_set_header Connection close;
    ​
    #一些设置的例子
    proxy_set_header Host $http_host; #将目前Host 头域的值填充成客户端的地址
    proxy_set_header Host $host;      #..................填充成当前location的server_name
    proxy_set_header Host $host:$proxy_port; # location的server_name以及listener指令填充Host
    
7.proxy_set_body指令
  • 说明:更改nginx收到客户端请求的请求体信息,将新的请求体发送给被代理服务器
  • 语法:proxy_set_body value;
8.proxy_bind指令
  • 说明:强制与代理主机绑定

  • 语法:proxy_bind address;

    address:主机IP

9.proxy_connect_timeout指令
  • 说明:nginx与后端被代理服务器建立连接的超时时间
  • 语法:proxy_connect_timeout time;(默认time 为 60s)
10.proxy_read_timeout指令
  • 说明:nginx向后端被代理服务器发送read请求后等待的响应时间
  • 语法:proxy_read_timeout time;(time默认为60s)
11.proxy_send_timeout指令
  • 说明:nginx向后端被代理服务器发送write请求后等待的响应时间
  • 语法:proxy_send_timeout time;
12.proxy_http_version指令
  • 说明:设置nginx提供代理服务的HTTP协议版本

  • 语法:proxy_http_version 1.0|1.1;

    默认为1.0, 1.1支持upsteam服务组设置中的keepalive指令

13.proxy_method指令
  • 说明:设置nginx请求被代理服务器的请求方法,一般为POST / GET,设置了后,客户端的请求方法会被忽略
  • 语法:proxy_method [POST|GET];
  1. proxy_ignore_client_abort指令
  • 说明:设置客户端中断网络请求时,nginx是否中断对代理服务器的请求
  • 语法:proxy_ignore_client_abort on|off(默认为 off 关闭)
15.proxy_ignore_headers指令
  • 说明:设置一些HTTP响应头中的头域,nginx接收到被代理服务器的响应数据后不处理这些头域。

  • 语法:proxy_ignore_headers field ...;

    field:头域 (“X-Accel-Redirect” 等)

16.proxy_redirect指令
  • 说明

    1. 与proxy_pass指令配合使用,用于修改被代理服务器返回的响应头中location头域 和Refresh头域。

      当使用proxy_pass 将客户端请求的地址修改为被代理服务器的地址,nginx返回给客户端的响应头中location头域显示的地址应该是客户端请求的地址,而不能是被代理服务器的地址

    2. 语法

      1.proxy_redirect redirect replacement; 
      #redirect:   匹配location头域的字符串,可用变量/正则
      #replacement:替换redirect变量的字符串内容#案例1:
      假设被代理服务器返回的响应头中Location头域为:
      Location: http://localhost:8081/proxy/some/uri/
      该指令的使用: 
      proxy_redirect http://localhost:8081/proxy/ http://myweb/frontend/;
      则nginx服务器会将Location头域信息更变,并且客户端接收到的信息为:
      Location:http://myweb/frontend//some/uri/
      ##
      ​
      ​
      2.proxy_redirect default;
      #default: 代表使用location的uri作为replacement,并用proxy_pass变量作为redirect#案例2
      #配置1
      location /server/{
          proxy_pass http://proxyserver/source/;
          proxy_redirect default;  #等价1 
          proxy_redirect http://proxyserver/source/  /server/; #等价2
          # redirect: proxy_pass  replacement: location的uri
      }
      ​
      ##
      ​
      ​
      3.proxy_redirect off; #设置当前作用域下的所有proxy_redirect 无效
      
17.proxy_intercept_errors指令
  • 说明:配置是否使用自定义错误页面,on:大于400的状态码时使用 error_page指令指向的页面;off:返回被代理服务器的HTTP给客户端。
  • 语法:proxy_intercept_errors on|off
18.proxy_headers_hash_max_size指令
  • 说明:配置存放HTTP报文头的哈希容量
  • 语法:proxy_headers_hash_max_size size; (size默认为512)
19.proxy_headers_hash_bucket_size指令
  • 说明:设置nginx申请存放http报文头的哈希表容量单位大小
  • 语法:proxy_headers_hash_bucket_size size (默认size 为64个字符)
20.proxy_next_upstream指令
  • 说明:配置代理服务器组中轮询触发的状态码

  • 语法:proxy_next_upstream [error|timeout|invalid_header|http_500|http_xxx |off]

    可以填写多个状态,其中一些状态解释:

    invalid_header:被代理服务器无效/空的响应头

    timeout:建立连接/发送请求/读取响应头时 连接超时

    off:无法将请求发送给被代理服务器

21.proxy_ssl_session_reuse指令
  • 说明:配置是否使用基于SSL安全协议的会话连接(https://)
  • 语法:proxy_ssl_session_reuse on|off;(默认为on)

7.3.2 Proxy Buffer

1.工作原理

Proxy Buffer是非全局的,可存在多个。

proxy buffer启用后,nginx会异步地将被代理服务器的数据传递给客户端。nginx先将被代理服务器接收到的响应数据放置在Proxy Buffer中,在接收过程中若是Buffer不够接收一次响应数据,nginx会将部分数据临时存放在磁盘中,一次响应数据接收完成或是Buffer被装满后,nginx开始向客户端传输数据。nginx向客户端传输数据过程中,Porxy Buffer处于BUSY状态,期间对它进行任何操作都会失败。

关闭Proxy Buffer时,nginx接收到响应数据就会同步传递到客户端,本身不会读取完整的响应数据。

2.相关指令

1.proxy_buffering指令
  • 说明:配置Proxy Buffer 开关,同时可通过HTTP响应头部的“X-Accel-Buffering”头域设置“yes”/“no”实现。
  • 语法proxy_buffering on|off;(默认为 on)
2.proxy_buffers指令
  • 说明:配置接收一次被代理服务器响应数据的Proxy Buffer个数和每个Buffer大小

  • 语法:proxy_buffers number size;

    number:个数(默认为8)

    size:每个大小,一般设置为内存页大小(默认为4KB / 8KB)

3.proxy_buffer_size指令
  • 说明:配置从被代理服务器获取第一部分响应数据的大小,一般包含了HTTP响应头,nginx通过它来获取响应数据和被代理服务器的一些必要信息。

  • 语法:proxy_buffer size;

    size:缓存大小(默认为 4KB 或 8KB)

4.proxy_busy_buffers_size指令
  • 说明:用于限制同处于BUSY状态的Proxy Buffer总大小
  • 语法:proxy_busy_size size;(默认为8/16 KB)
5.proxy_temp_path指令
  • 说明:配置磁盘路径,用于临时存放响应数据。

  • 语法:proxy_temp_path path [level1 [level2 [level3]]];

    path:磁盘路径

    level:path变量设置的路径下第几级hash目录中存放

    eg:proxy_temp_path /nginx/web/spool/temp 1 2;

    :配置在该路径下第二级目录中

6.proxy_max_temp_file_size指令
  • 说明:配置所有临时文件的总体积
  • 语法:proxy_max_temp_file_size size; (默认为1024MB)
7.proxy_temp_file_write_size指令
  • 说明:配置同时写入临时文件的数据量总大小,避免IO负载过大。
  • 语法:proxy_temp_file_write_size size;(默认为8/16 KB,一般与平台的内存页大小相同)

7.3.3 Proxy Cache

1.工作原理

Proxy Cache机制是nginx的一种缓存机制。Proxy Buffer 是一种缓冲机制,Buffer和Cache两者都是用于提供IO吞吐效率的。

  • Buffer(“缓冲”):将一方的数据缓存到Buffer中再传到另一方中;
  • Cache(“缓存”):给硬盘中已有数据在内存中建立缓存,提高数据访问效率,对于不再用的缓存数据可直接销毁,不影响硬盘上的数据。

两者都是用来提供客户端和被代理端传输数据用的,Buffer实现了异步传输,Cache实现请求的快速响应。nginx在使用Buffer传输数据的过程中并使用Cache机制将数据缓存到nginx本机上,减少与被代理端的交互,提高下次访问的效率。

Proxy Cache需要依赖于Proxy Buffer,只有开启了Buffer,启用Cache才有用。

2.相关指令

1.proxy_cache指令
  • 说明:配置缓存区域

  • 语法:proxy_cache zone|off;

    zone:设置存放缓存索引的内存区域名称

    off:关闭cache功能(默认)

2.proxy_cache_bypass指令
  • 说明:配置不从缓存中获取的条件
  • 语法:proxy_cache_bypass string...;
3.proxy_cache_key sting;

设置缓存数据索引的关键字

缓存锁

缓存锁功能:多个请求返回填充同一个数据,启用锁时,排队一个个填充。(默认为关闭)

4.proxy_cache_lock on | off; :开关

5.proxy_cache_lock_timeout time:缓存锁的超时时间(默认为5s)

6.proxy_cache_min_users number:客户端发送同个请求到达 number 次后做缓存(默认为1)

7.proxy_cache_path ......:缓存路径、索引相关内容。(只能在http块中)

8.proxy_cache_use_stale error|timeout|updating|http_xxx|off...; (默认为off)

当无法访问/访问错误等情况时,使用历史缓存响应客户端请求。(状态后面详解)

updating:nginx正好处于更新状态。

9.proxy_cache_valid [code...] time; :针对不同的状态码设置不同的缓存时间

code:200、302 ......

10.proxy_no_cache string...;:不使用cache的情况

11.proxy_store on|off|sring(路径);:是否在本地磁盘缓存被代理服务器的响应数据(静态数据较为适用)

12.proxy_store_access users:permissions ...:设置用户对Proxy Cache缓存数据的访问权限。

users:可设置为user、group、all

permissions:权限设置

3.小案例

location /fetch/{
    proxy_pass http://backend;
    proxy_store on; #开启 Proxy Store
    proxy_store_access user:rw group:rw all:r;
    root  /data/www;  #缓存数据路径
}
  1. Proxy Cache一般配置

    ...
    http{
        ...
         #配置缓存数据存放路径 和 proxy Cache使用的内存空间
        proxy_cache_path /myweb/server/proxycache levels=1:2 maxsize=2m inactive=5m
                        loader_sleep=1m; keys_zone=MYPROXYCACHE:10m 
        proxy_temp_path /myweb/server/temp; #临时存放的目录
        server{
            ....
        }
        location / {
            ...
            proxy_pass http://www.myweb.name/;
            proxy_cache MYPROXYCACHE; #配置keys_zone
            proxy_cache_vaild 200 302 1h; # 200 302状态缓存1小时
            proxy_cache_valid 301 1d;
            proxy_cache_valid any 1m; 
        }
    }
    

7.4 负载均衡

1.原理

利用一定的分配策略将网络负载均摊到集群的各个单位上,使得并发大量时不过大影响效率。常见的负载均衡分为两类:静态负载均衡动态负载均衡

  • 静态负载均衡:一般网络环境下就能达到很好的效果,一般有:轮询算法、基于比率的加权轮询算法、基于优先级的加权轮询算法等。
  • 动态负载均衡:运用在较为复杂的网络环境中,一般有:基于任务量的较少连接优先算法、基于性能的最快响应优先算法、预测算法、动态性能分配算法等。

2.基础算法

轮询算法(常用方式)

  • 缺点: 无法保存会话,在第一台服务器进行登录等相关信息后,nginx可能将你重新转发到第二台服务器,此时无法读取到之前的信息,造成信息丢失
  • 解决方案: 将信息放到SpirngSession中 / 下发token进行加密

不常用的三种方式:

image.png

3.集群化(水平扩展)

无论是 request_URI 还是cookie_isessionid 都是给用户分配一个独一的值来区别用户

  • 配置

不同的负载方式:修改 hash $cookie_jsessionid

  • request_uri

    访问相同的URI(/后面开始) 跳转到相同的服务器(不支持Cookie情况下适用,可用于保持会话的保持)

  • cookie_isessionid

eg: image.png

4.使用sticky

安装教程:网上找

  • 作用

    对静态服务器的会话保持(基于cookie)

  • 配置

image.png