8 代理功能

felix.shao2025-02-18

8 代理功能

TIP

本小节主要介绍以下知识:

  • 正向代理与反向代理的基本概念。
  • Nginx 正向代理服务的配置指令。
  • Nginx 反向代理服务的配置指令。
  • Nginx 反向代理服务器的应用-负载均衡。

正向代理与反向代理的概念

 正向代理:一般说的代理即是正向代理服务。一个简单的例子是: 局域网内的客户端通过正向代理服务器访问局域网外的网站(服务器),这主要是为了增强局域网内部网络的安全性,使得网外的威胁因素不容易影响到网内,这里代理服务器起到了一部分防火墙的功能。同时利用代理服务器也可以对局域网对外网的访问进行必要的监控和管理。正向代理服务器不支持外部对内部网络的访问请求。
 反向代理:与正向代理相反。如果局域网内的客户端向 Internet (服务器)提供资源,让 Internet 上的其他用户可以访问局域网内的资源,也可以设置使用一个代理服务器。
 归纳起来就是:正向代理服务器用来让局域网客户机接入外网以访问外网资源,反向代理服务器用来让外网的客户端接入局域网中的站点以访问站点中的资源。

TIP

 以下也是一种说法:代理与反向代理open in new window
 两者的区别在于代理的对象不一样:正向代理代理的对象是客户端,反向代理代理的对象是服务端。

Nginx 服务器的正向代理服务

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

 在实际应用中,使用 Nginx 服务器代理服务功能的情况相对少一些,Nginx 代理服务本身也相对简单,涉及的主要指令不多。
 这些指令原则上可以出现在 Nginx 配置文件的 http 块、server 块或者 location 块中,但一般是在搭建的 Nginx 服务器中单独配置一个 server 块用来设置代理服务。

  1. resolver 指令
     该指令用于指定 DNS 服务器的 IP 地址。DNS 服务器的主要工作是进行域名解析,将域名映射为对应的 IP 地址。该指令的语法结构为:
    resolver address ... [valid=time];
  • address,DNS 服务器的 IP 地址。如果不指定端口号,默认使用 53 端口。
  • time,设置数据包在网络中的有效时间。

 使用该指令的一个例子如下:
resolver 127.0.0.1 [::1]:5353 valid=30s;
 在实际应用中,一般不需要设置为这么复杂,只要将 DNS 服务器的 IP 地址设置给该指令即可。

  1. resolver_timeout 指令
     该指令用于指定 DNS 服务器域名解析超时时间。其语法结构为:
    resolver_timeout time;

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

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 服务器接收到的所有请求都由第 5 行的 location 块进行过滤处理。

Nginx 服务器的反向代理服务

 Nginx 服务器的反向代理服务是其最常用的重要功能之一,在实际工作中应用广泛,涉及的配置指令也比较多,各类指令完成的功能也不尽相同。
 Nginx 服务器提供的反向代理服务也是比较高效的。它能够同时接收的客户端连接由 worker_processes 指令和 worker_connections 指令决定,计算方法为 worker_processes * worker_connections / 4。
 配置 Nginx 服务器反向代理用到的指令如果没有特别说明,原则上可以出现在 Nginx 配置文件的 http 块、server 块或者 location 块中,但同正向代理服务的设置一样,一般是在搭建的 Nginx 服务器中单独配置一个 server 块用来设置反向代理服务。这些指令主要由 ngx_http_proxy_module 模块进行解析和处理。该模块是 Nginx 服务器的标准模块。

反向代理的基本设置的 21 个指令

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

 其中,URL 为要设置的代理服务器协议和地址,包含传输协议、主机名称或 IP 地址加端口号、URI 等要素。传输协议通常是 http 或者 https。指令同时还接受以 unix 开始的 UNIX-domain 套接字路径。
 如果被代理服务器是一组服务器的话,可以使用 upstream 指令配置后端服务器组。

TIP

  1. 如果 upstream 指令的 server 里指明了 http 等协议,那么 proxy_pass 指令中就不需要指明了,如果未指明,则需要指明下协议,如:proxy_pass http://proxy_svrs,proxy_svrs 是 upstream proxy_svrs{...}的配置
  2. 还需注意,URL 中是否也有 URI,Nginx 的处理方式是不同的。如果 URL 中不包含 URI,Nginx 服务器不会改变原地址的 URI;但是如果包含了 URI,Nginx 服务器将会使用新的 URI 替代原来的 URI。以下举例来说明
server {
    ...
    listen 80;
    server www.myweb.name;
    location /server/{
        ...
        proxy http://192.168.1.1;
    }
}

 如果客户端使用"http://www.myweb.name/server"发起请求,该请求被配置中显示的 location 块进行处理,由于 proxy_pass 指令的 URL 变量不含有 URI,所以转向的地址为"http://192.168.1.1/server"。
 再看一个 Nginx 配置片段

server {
    ...
    listen 80;
    server www.myweb.name;
    location /server/{
        ...
        proxy http://192.168.1.1/loc/;
    }
}

在该配置实例中,proxy_pass 指令的URL包含了 URI "/loc/"。如果客户端仍然使用"http://www.myweb.name/server"发起请求,Nginx 服务器会把地址转向为"http://192.168.1.1/loc/"。  

TIP

理解了上面的问题后,再理解下 proxy_pass 指令的 URL 变量末尾是否加斜杠"/"的问题,如下:

#配置1 proxy_pass http://192.168.1.1;
#配置2 proxy_pass http://192.168.1.1/;
  1. 如果 location 配置为: location /,其配置是一样的。
  2. 如果 location 配置为:location /server/,比如客户端请求的 URL 为"http://www.myweb.name/server/index.htm",使用配置 1 的时候,转向的 URL 为"http://192.168.1.1/server/index.htm";使用配置 2 的时候,转向的 URL 为"http://192.168.1.1/index.htm"。
  1. proxy_hide_header 指令
     该指令用于设置 Nginx 服务器再发送 HTTP 响应时,隐藏一些头域信息。其语法结构为:
    proxy_hide_header field;
     其中,field 为需要因此的头域。该指令可以在 http 块、server 块或者 location 块中进行配置。

  2. proxy_pass_header 指令
     默认情况下,Nginx 服务器再发送 HTTP 响应时,报文头中不包含"Date"、"Server"、"X-Accel"等来自被代理服务器的头域信息。该指令可以设置这些头域信息以备发送。其语法结构为:
    proxy_pass_header field;
     其中,field 为需要因此的头域。该指令可以在 http 块、server 块或者 location 块中进行配置。

  3. proxy_pass_request_body 指令
     该指令用于配置是否将客户端请求的请求体发送给代理服务器。其语法结构为:
    proxy_pass_request_body on | off;
     默认设置为开启,开关可以在 http 块、server 块或者 location 块中进行配置。

  4. proxy_pass_request_headers 指令
     该指令用于配置是否将客户端请求的请求头发送给代理服务器。其语法结构为:
    proxy_pass_request_headers on | off;
     默认设置为开启,开关可以在 http 块、server 块或者 location 块中进行配置。

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

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

 默认情况,该指令的设置为:

proxy_set_header Host $proxy_host;
proxy_set_header Connection close;
  1. proxy_set_body 指令
     该指令可以更改 Nginx 服务器接收到的客户端请求的请求体信息,然后将新的请求体发送给被代理的服务器。其语法结构为:
    proxy_set_body value;
     其中,value 为更改的信息,支持使用文本、变量或者变量的组合。

  2. proxy_bind 指令
     官方文档中对该指令的解释是,强制将与代理主机的连接绑定到指定的 IP 地址。通俗来讲就是,在配置了多个基于名称或者基于 IP 的主机的情况下,如果我们希望代理连接由指定的主机处理,就可以使用该指令进行配置,其语法结构为:
    proxy_bind address;
     其中,address 为指定主机的IP地址。

  3. proxy_connect_timeout 指令
     该指令配置 Nginx 服务器与后端被代理服务器尝试建立连接的超时时间,其语法结构为:
    proxy_connect_timeout time;
     其中,time 为设置的超时时间,默认为 60s。

  4. proxy_read_timeout 指令
     该指令配置 Nginx 服务器与后端被代理服务器(组)发出 read 请求后,等待响应的超时时间,其语法结构为:
    proxy_read_timeout time;
     其中,time 为设置的超时时间,默认为 60s。

  5. proxy_send_timeout 指令
     该指令配置 Nginx 服务器与后端被代理服务器(组)发出 write 请求后,等待响应的超时时间,其语法结构为:
    proxy_send_timeout time;
     其中,time 为设置的超时时间,默认为 60s。

  6. proxy_http_version 指令
     该指令用于设置 Nginx 服务器提供代理服务的 HTTP 协议版本,其语法结构为:
    proxy_http_version 1.0 | 1.1;
     默认设置为 1.0 版本。1.1 版本支持 upstream 服务器组设置中的 keepalive 指令。

  7. proxy_method 指令
     该指令用于设置用于 Nginx 服务器请求被代理服务器时使用的请求方法,一般为 POST 或者 GET。设置了该指令,客户端的请求方法将被忽略。其语法结构为:
    proxy_method method;
     其中,method 的值可以设置为 POST 或者 GET,注意不加引号。

  8. proxy_ignore_client_abort 指令
     该指令用于设置在客户端中断网络请求时,Nginx 服务器是否中断对被代理服务器的请求,其语法结构为:
    proxy_ignore_client_abort on | off;
     默认设置为 off,当客户端中断网络请求时,Nginx 服务器中断对被代理服务器的请求。

  9. proxy_ignore_headers 指令
     该指令用于设置一些 HTTP 响应头中的头域,Nginx 服务器接收到被代理服务器的响应数据后,不会处理被设置的头域。其语法结构为:
    proxy_ignore_headers field ...;
     其中,field 为要设置的 HTTP 响应头的头域,例如"X-Accel-Redirect"、"X-Accel-Expires"、"Expires"、"Cache-Control"或"Set-Cookie"等。

  10. proxy_redirect 指令
     该指令用于修改被代理服务器返回的响应头中的 Location 头域和"Refresh"头域,与 proxy_pass 指令配合使用。比如,Nginx 服务器通过 proxy_pass 指令将客户端的请求地址重写为被代理服务器的地址,那么Nginx 服务器返回给客户端的响应头中"Location"头域显示的地址就应该和客户端发起的请求的地址相对应,而不是代理服务器直接返回的地址信息,否则就会出问题。该指令解决了这个问题,可以把代理服务器返回的地址信息更改为需要的地址信息。其语法结构为:

1. proxy_redirect redirect replacement;
2. proxy_redirect default;
3. proxy_redirect off;
  • 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/",这样,客户端收到的响应信息头部中的"Location"头域也就被更改了。

 结构 2 使用 default,代表使用 location 块中的 uri 变量作为 replacement,并使用 proxy_pass 变量作为 redirect。请看下面两段配置,它们的配置效果是等同的。

# 配置1
location /server/ {
    proxy_pass http://proxyserver/source/;
    proxy_redirect default;
}

# 配置 2
location /server/ {
    proxy_pass http://proxyserver/source/;
    proxy_redirect http://proxyserver/source/ /server/;
}

 使用结构 3可以将当前作用域下所有的 proxy_redirect 指令配置全部设置为无效。

  1. proxy_intercept_errors 指令
     该指令用于配置一个状态是开启还是关闭。在开启该状态时,如果被代理的服务器返回的 HTTP 状态码为 400 或者大于 400,则 Nginx 服务器使用自己定义的错误页(使用 error_page 指令);如果是关闭该状态,Nginx 服务器直接将被代理服务器返回的 HTTP 状态返回给客户端。其语法结构为:
    proxy_intercept_errors on | off;

  2. proxy_headers_hash_max_size 指令
     该指令用于配置存放 HTTP 报文头的哈希表的容量。其语法结构为:
    proxy_headers_hash_max_size size;
     其中 size 为 HTTP 报文头哈希表的容量上限,默认为 512 个字符。
     Nginx 服务器为了快速检索 HTTP 报文头中的各项信息,比如服务器名称、MIME 类型、请求头名称等,使用哈希表存储这些信息。Nginx 服务器在申请存放 HTTP 报文头的空间时,通常以固定大小为单位申请,该大小由 proxy_headers_hash_bucket_size 指令配置。
     在 Nginx 配置中,不仅能够配置整个哈希表的大小上限,对大部分的内容项,也可以配置其大小上限,比如 server_names_hash_max_szie 指令和 server_names_hash_bucket_size 指令用来设置服务器名称的字符数长度。

  3. proxy_headers_hash_bucket_size 指令
     该指令用于设置 Nginx 服务器申请存放 HTTP 报文头的哈希表容量的单位大小,其用户已在上面的指令中说明。其语法结构为:
    proxy_headers_hash_bucket_size size;
     其中,size 为设置的容量,默认为 64 个字符。

  4. proxy_next_upstream 指令
     在配置 Nginx 服务器反向代理功能时,如果使用 upstream 指令配置了一组服务器作为被代理服务器,服务器组中个服务器的访问规则遵循 upstream 指令配置的轮询规则,同时可以使用该指令配置在发生哪些异常情况时,将请求顺次交由下一个组内服务器处理。其语法结构为:
    proxy_next_upstream status ...;

 其中,status 为设置的服务器返回状态,可以是一个或者多个。这些状态包括:

  • error,在建立连接、向被代理的服务器发送请求或者读取响应头时服务器发生连接错误。
  • timeout,在建立连接、向被代理的服务器发送请求或者读取响应头时服务器发生连接超时。
  • invalid_header,被代理的服务器返回的响应头返回的响应头为空或者无效。
  • http_500|http_502|http_503|http_504|http_404,被代理的服务器返回 500、502、503、504、404 状态代码。
  • off,无法将请求发送给被代理的服务器。

TIP

 与被代理的服务器进行数据传输的过程中发送错误的请求,不包含在该指令支持的状态之内。

  1. proxy_ssl_session_reuse 指令
     该指令用于配置是否使用基于 SSL 安全协议的会话连接("http://")被代理的服务器。其语法结构为:
    proxy_ssl_session_reuse on | off;

 默认为开启状态。如果我们在错误日志中发现"SSL3_GET_FINISHED:digest check failed"的情况,可以将该指令配置为关闭状态。

proxy buffer 的配置的 7 个指令

 先简单的了解下 Proxy Buffer 的工作原理,这对理解和该功能相关的几个指令是有帮助的。
 它们的配置都是针对每一个请求起作用的,而不是全局概念,即每个请求都会按照这些指令的配置来配置各自的 Buffer,Nginx 服务器不会生成一个公共的 Proxy Buffer 供代理请求使用。
 Proxy Buffer启用以后,Nginx 服务器会异步地将被代理服务器的响应数据传递给客户端。
 Nginx 服务器首先尽可能地从被代理服务器那里接收响应数据,放置在 Proxy Buffer 中,Buffer 的大小由 proxy_buffer_size 指令和 proxy_buffers 指令决定。如果在接收过程中,发现 Buffer 没有足够大小来接收一次响应的数据,Nginx 服务器会将部分接收到的数据临时存放在磁盘的临时文件中,磁盘上的临时文件路径可以通过 proxy_temp_path 指令进行设置,临时文件的大小由 proxy_max_temp_file_size 指令和proxy_temp_file_write_size 指令决定。一次响应数据被接收完成或者 Buffer 以及装满后,Nginx 服务器开始向客户端传输数据。
 每个 Proxy Buffer 装满数据后,在从开始向客户端发送一直到 Proxy Buffer 中的数据全部传输给客户端的整个过程中,它都处于 BUSY 状态,期间对它进行的其他操作都会失败。同时处于 BUSY 状态的 Proxy Buffer 总大小由 proxy_busy_buffers_size 指令限制,不能超过该指令设置的大小。
 当 Proxy Buffer 关闭时,Nginx 服务器只要接收到响应数据就会同步地传递给客户端,它本身不会读取完整的响应数据。

  1. proxy_buffering 指令
     该指令用于配置是否启用或者关闭 Proxy Buffer。其语法结构为:
    proxy_buffering on | off;
     默认为开启状态。

  2. proxy_buffers 指令
     该指令用于配置接收一次被代理服务器响应数据的 Proxy Buffer 个数和每个 Buffer 的大小。其语法结构为:
    proxy_buffers number size;

  • number,Proxy Buffer 的个数
  • size,每个 Buffer 的大小,一般设置为内存页的大小。根据平台的不同,可能为 4KB 或者 8KB。

 由这个指令可以得到接收一次被代理服务器响应数据的 Proxy Buffer 总大小为 number * size。该指令的默认设置为:
proxy_buffers 8 4k|8k

  1. proxy_buffer_size 指令
     该指令用于配置从被代理服务器获取的第一部分响应数据的大小,该数据中一般包含了 HTTP 响应头,Nginx 服务器通过它来获取响应数据和被代理服务器的一些必要信息。其语法结构为:
    proxy_buffer_size size;

 其中,size 为设置的缓存大小,默认设置为 4KB 或者 8KB,保持与 proxy_buffers 指令中的变量相同,当然也可以设置得更小。

  1. proxy_busy_buffers_size 指令
     该指令用于限制同时处于 BUSY 状态的 Proxy Buffer 的总大小。其语法结构为:
    proxy_busy_buffers_size size;

 其中,size 为设置的处于 BUSY 状态的缓冲区总大小。默认设置为 8KB 或者 16KB。

  1. proxy_temp_path 指令
     该指令用于配置磁盘上的一个文件路径,该文件用于临时存放代理服务器的大体积响应数据。如果 Proxy Buffer 被装满后,响应数据仍然没有被 Nginx 服务器完全接收,响应数据就会被临时存放在该文件中。其语法结构为:
    proxy_temp_path path [level1 [level2 [level3]]];
  • path,设置磁盘上存放临时文件的路径
  • levelN,设置在 path 变量设置的路径下第几级 hash 目录中存放临时文件
  1. proxy_max_temp_file_size 指令
     该指令用于配置所有临时文件的总体积大小,存放在磁盘上的临时文件大小不能超过该配置值,这避免了响应数据过大造成磁盘空间不足的问题。其语法结构为:
    proxy_max_temp_file_size size;

 其中,size 为设置的临时文件总体积上限值。默认设置为 1024MB。

  1. proxy_temp_file_write_size 指令
     该指令用于配置同时写入临时文件的数据量的总大小,合理的设置可以避免磁盘 IO 负载过重导致系统性能下降的问题。其语法结构为:
    proxy_temp_file_write_size size;

 其中,size 为设置的数据量总大小的上限值,默认设置根据平台的不同,可以为 8KB 或 16KB,一般与平台的内存页大小相同。

Proxy Cache的配置的 12 个指令

 简单区别下 Proxy Buffer 和 Proxy Cache。

  • Buffer:缓冲。主要用于传输效率不同步或者优先级别不相同的设备之间传递数据,一般通过对一方数据进行临时存放,再统一发送的办法传递给另一方,以降低进程之间的等待时间,保证速度较快的进程不发生间断,临时存放的数据一旦传送给另一方,这些数据本身也就没有用处了。
  • Cache:缓存。主要用于将硬盘上已有的数据在内存中建立缓存数据,提高数据的访问效率,对于过期不用的缓存可以随时销毁,但不会销毁磁盘上的数据。

TIP

 Proxy Buffer 实现了被代理服务器响应数据的异步传输,Proxy Cache 则主要实现 Nginx 服务器对客户端数据请求的快速响应。Proxy Cache 机制依赖于 Proxy Buffer 机制,只有在 Proxy Buffer 机制开启的情况下 Proxy Cache 的配置才会发挥作用。

  1. proxy_cache 指令
     该指令用于配置一块公用的内存区域的名称,该区域可以存放缓存的索引数据。这些数据在 Nginx 服务器启动时由缓存索引重建进程负责建立,在 Nginx 服务器的整个运行过程由缓存管理进程负责定时检查过期数据、检索等管理工作。其语法结构为:
    proxy_cache zone | off;
  • zone,设置的用于存放缓存索引的内存区域的名称。
  • off,关闭 proxy_cache 功能,是默认的设置。

 从 Nginx0.7.66 开始,Proxy Cache 机制开启后会检查代理服务器响应数据 HTTP 头中的"Cache-Control"头域、"Expired"头域。当"Cache-Control"头域中的值为"no-cache"、"no-store"、"private"或者"max-age"赋值为 0 或无意义时,当"Expired"头域包含一个过期的时间时,该响应数据不被 Nginx 服务器缓存。这样做的主要目的是为了避免私有的数据被其他客户端得到。

  1. proxy_cache_bypass 指令
     该指令用于配置 Nginx 服务器向客户端发送响应庶几乎时,不从缓存中获取的条件。这些条件支持使用 Nginx 配置的常用变量。其语法结构为:
    proxy_cache_bypass string ...;

 其中,string 为条件变量,支持设置多个,当至少由一个字符串指令不为空或者不等于 0 时,响应数据不从缓存中获取。

  1. proxy_cache_key 指令
     该指令用于配置 Nginx 服务器在内存中为缓存数据建立索引时使用的关键字。其语法结构为:
    proxy_cache_key string;

 其中,string 为设置的关键字,支持变量。如果我们希望缓存数据包含服务器主机名称等关键字,则可以将该指令设置为: proxy_cache_key "$scheme$proxy_host$request_uri";
 在 Nginx0.7.48 之后的版本中,通常使用以下配置:
proxy_cache_key "$scheme$proxy_host$uri$is_args$args";

  1. proxy_cache_lock 指令
     该指令用于设置是否开启缓存的锁功能。在缓存中,某些数据项可以同时被多个请求返回响应数据填充。开启该功能后,Nginx 服务器同时只能由一个请求填充缓存中的某一项数据,这相当于给该数据项上锁,不允许其他请求操作。其他的请求如果也想填充该项,必须等待该数据项的锁被释放。这个等待时间由 proxy_cache_lock_timeout 指令配置。其语法结构为:
    proxy_cache_lock on | off;
     该指令在 Nginx1.1.2 及之后的版本中可以使用,默认情况下,设置为关闭状态。

  2. proxy_cache_lock_timeout 指令
     该指令用于设置缓存的锁功能开启以后锁的超时时间。其语法结构为:
    proxy_cache_lock_timeout time;

 其中,time 为设置的时间,默认为 5s。

  1. proxy_cache_min_uses 指令
     该指令用于设置客户端请求发送的次数,当客户端向被代理服务器发送相同请求达到该指令设定的次数后,Nginx 服务器才对该请求的响应数据做缓存。合理设置该值可以有效地降低磁盘上缓存数据的数量,并提高缓存的命中率。其语法结构为:
    proxy_cache_min_uses number;
     其中,number 为设置的次数,默认设置为 1。

  2. proxy_cache_path 指令
     该指令用于设置 Nginx 服务器存储缓存数据的路径以及和缓存索引相关的内容。其语法结构为:

proxy_cache_path path [levels=levels] keys_zone=name:size1 [inactive=time1] 
[max_size=size2] [loader_files=number] [loader_sleep=time2] [loader_threshold=time3];
  • path,设置缓存数据存放的根路径。
  • levels,设置在相对于 path 指定目录的第几级 hash 目录中缓存数据。目录的名称是基于请求 URL 通过哈希算法获取到的。
  • name:size1,Nginx 服务器的缓存索引重建进程在内存中为缓存数据建立索引,这一对变量用来设置存放缓存索引的内存区域的名称和大小。
  • time1,设置强制更新缓存数据的时间,即在设定的时间没有被访问时,删除缓存,默认是 10s。
  • size2,设置硬盘中缓存数据的大小限制。当缓存的大小超过该变量的设置时,缓存管理进程将根据最近最少被访问的策略删除缓存。
  • number,设置缓存索引重建进程每个加载的数据元素的数量上限。默认设置是 100。
  • time2,设置缓存索引重建进程在一次遍历结束、下次遍历开始之间的暂停时长。默认设置为 50ms。
  • tim3,设置遍历一次磁盘缓存源数据的时间上限。默认设置为 200ms。

 该指令设置比较复杂,一般需要设置前面三个指令的情形比较多,后面的几个遍历与 Nginx 服务器缓存索引重建进程及管理进程的性能相关,一般情况下保持默认设置就可以了。以下是几个配置实例:

proxy_cache /nginx/cache/a levels=1 key_zone=a:10m;
proxy_cache /nginx/cache/b levels=2:2 key_zone=b:100m;
proxy_cache /nginx/cache/c levels=1:1:2 key_zone=c:1000m;

 PS: 该指令和其他指令不同,只能放在 http 块中。

  1. proxy_cache_use_stale 指令
     如果 Nginx 在访问被代理服务器过程中出现被代理的服务器无法访问或者范文错误等现象时,Nginx 服务器可以使用历史缓存响应客户端的请求,这些数据不一定和被代理服务器上最新的数据相一致,但对于更新频率不高的后端来说,Nginx 服务器的该功能在一定程度上能够为客户端提供不间断访问。
     该指令用来设置一些状态,当后端被代理的服务器处于这些状态时,Nginx 服务器启用该功能。其语法结构为:
    proxy_cache_use_stale error | timeout | invalid_headers | updating | http_500 | http_502 | http_503 | http_504 | http_404 | off ...;

 该指令可以支持的状态如语法结构中所示。

  • 大部分状态我们在介绍 proxy_next_upstream 指令时详细说明
  • 需要注意其中的 updating 状态的含义。该状态并不是指被代理服务器在 updating 装,而是指客户端请求的数据在 Nginx 服务器中正好处于更新状态。
  1. proxy_cache_valid 指令
     该指令可以针对不通过的 HTTP 响应状态设置不同的缓存时间。其语法结构为:
    proxy_cache_valid [code ...] time;
  • code,设置 HTTP 响应的状态代码。该指令可选,如果不设置,Nginx 服务器只为 HTTP 状态代码为 200、301 和 302 的响应数据做缓存。可以使用"any"表示缓存所有该指令中未设置的其他响应数据。
  • time,设置缓存时间。

 如下几个例子:

proxy_cache_valid 200 302 10m;
proxy_cache_valid 301 1h;
proxy_cache_valid any 1m; #对返回状态为非 200、302 和 301 的响应数据缓存 1 分钟。
  1. proxy_no_cache 指令
     该指令用于配置在什么情况下不适用 cache 功能。其语法结构为:
    proxy_no_cache string ...;

 其中,string 可以是一个或者多个变量。当 string 的值不为空或者不为"0"时,不启用 cache 功能。

  1. proxy_store 指令
     该指令配置是否在本地磁盘缓存来自被代理服务器的响应数据。这是 Nginx 服务器提供的另一种缓存数据的方法,但是该功能相对 Proxy Cache 简单一些,它不提供缓存过期更新,内存索引建立等功能,不占用内存空间,对静态数据的效果比较好。其语法结构为:
    proxy_store no | off | string;
  • of | off,设置是否开启 Proxy Store 功能。如果使用变量 on,功能开启,缓存文件会存放到 alias 指令或 root 指令设置的本地路径下。
  • string,自定义缓存文件的存放路径。

 Proxy Store 方法多使用在被代理服务器端发生错误的情况下,用来缓存被代理服务器的响应数据。

  1. proxy_store_access 指令
     该指令用于设置用户或用户组对 Proxy Store 缓存的数据的访问权限。其语法结构为:
    proxy_store_access users:permissions;
  • users,可以设置为 user、group 或者 all。
  • permissions,设置权限。

 一个例子如下:

location /images/{
    root /data/www;
    error_page 404 = /fetch$uri;
}
location /fetch/{
    proxy_pass http://backend;
    proxy_store on; # 开启Proxy Store方法
    proxy_store_access user:rw group:rw all:r;
    root /data/www; #缓存数据的路径
}

Nginx 服务器的负载均衡

 网络负载均衡技术的大致原理是利用一定的分配策略将网络负载平衡地分摊到网络集群的各个操作单元中,使得单个重负载任务能够分担到多个单元上并行处理,或者使得大了并发访问或数据流量分担到多个单元上分别处理,从而减少用户的等待响应时间。
 在实际应用中,负载均衡会根据网络的不同层次(一般按照 OSI 的七层网络参考模型)进行划分。现代的负载均衡技术主要实现和作用于网络的第四层或第七层,完全独立于网络基础硬件设备,成为单独的技术设备。 Nginx 服务器实现的负载均衡一般认为是七层负载均衡。
 负载均衡主要通过专门的硬件设备实现或者通过软件算法实现。通过硬件设备实现的负载均衡效果好、效率高、性能稳定,但是成本比较高。通过软件实现的负载均衡主要依赖于均衡算法的选择和程序的健壮性。均衡算法也是多种多样的,常见的有两大类:即静态负载均衡算法和动态负载均衡算法。静态算法实现比较简单,在一般网络环境下也能达到比较好的效果,主要有一般轮询算法、基于比率的加权轮询算法以及基于优先级的加权轮询算法等。动态负载均衡算法在较为复杂的网络环境中适应性更强,效果更好,主要有基于任务量的最小连接优先算法、基于性能的最快响应优先算法、预测算法及动态性能分配算法等。

配置实例一:对所有请求实现一般轮询规则的负载均衡

upstream backend{ #配置后端服务器组
    server 192.168.1.2:80;
    server 192.168.1.3:80;
    server 192.168.1.4:80;
}
server { # 默认 weight
    listen 80;
    server_name www.myweb.name;
    index index.html index.htm;
    location / {
        proxy_pass http://backend;
        proxy_set_header Host $host;
    }
}

配置实例二:对所有请求实现加权轮询规则的负载均衡

upstream backend{ #配置后端服务器组
    server 192.168.1.2:80;
    server 192.168.1.3:80;
    server 192.168.1.4:80;
}
server { # 默认 weight
    listen 80;
    server_name www.myweb.name weight=5;
    index index.html index.htm weight=2;
    location / {
        proxy_pass http://backend;
        proxy_set_header Host $host;
    }
}

配置实例三:对特定资源实现负载均衡

 在该实例片段中,我们设置了两组被代理的服务器组,名为"videobackend"的一组用于对 viedo 资源的客户端请求进行负载均衡,另一组用于对 file 资源的客户端请求进行负载均衡。通过对 location 块的 uri 的不同配置,我们就很轻易地实现了对特定资源的负载均衡。  在location /file/ {...}块中,我们将客户端的真实信息分别填充到了请求头中的"Host"、"X-Real-IP"、"X-Forwarded-For"头域,这样后端服务器组收到的请求中就保留了客户端的真实信息,而不是 Nginx 服务器的信息。

upstream vidiobackend{ #配置后端服务器组 1
    server 192.168.1.2:80;
    server 192.168.1.3:80;
    server 192.168.1.4:80;
}
upstream filebackend{ #配置后端服务器组 2
    server 192.168.1.5:80;
    server 192.168.1.6:80;
    server 192.168.1.7:80;
}
server { # 默认 weight
    listen 80;
    server_name www.myweb.name;
    index index.html index.htm;
    location /vidio/ { 
        proxy_pass http://vidiobackend; #使用后端服务器组 1
        proxy_set_header Host $host;
        ...
    }
    location /file/ { 
        proxy_pass http://filebackend; #使用后端服务器组 2
        proxy_set_header Host $host;  #保留客户端的真实信息
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        ...
    }
}

配置实例四:对不同域名实现负载均衡

 在该实例片段中,我们设置了两个虚拟服务器和两组后端被代理的服务器组,分别用来接收不同的域名请求和对请求进行负载均衡处理。
 需要注意两组后端服务器中有一台服务器 server 192.168.1.4:80 是公用的。在该服务器上需要部署两个域名下的所有资源才能保证客户端请求不会出现问题。

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.5:80;
    server 192.168.1.6:80;
    server 192.168.1.7:80;
}
server { # 开始配置 server 1
    listen 80;
    server_name home.myweb.name;
    index index.html index.htm;
    location /vidio/ { 
        proxy_pass http://homebackend; 
        proxy_set_header Host $host;
        ...
    }
}
server { # 开始配置 server 2
    listen 80;
    server_name bbs.myweb.name;
    index index.html index.htm;
    location /vidio/ { 
        proxy_pass http://bbsbackend; 
        proxy_set_header Host $host;
        ...
    }
}

配置实例五:实现带有 URL 重写的负载均衡

 该实例片段与"配置实例一"相比,增加了对URI包含"/file/"的 URL 重写功能。

upstream backend{ 
    server 192.168.1.2:80;
    server 192.168.1.3:80;
    server 192.168.1.4:80;
}
server { 
    listen 80;
    server_name www.myweb.name;
    index index.html index.htm;
    location /file/ {
        rewrite ^(/file/.*)/media/(.*)\.*$ $1/mp3/$2.mp3 last;
    }
    location / {
        proxy_pass http://backend;
        proxy_set_header Host $host;
    }
}

 例如客户端的请求 URL 为"http://www.myweb.name/file/download/media/1.mp3"时,该虚拟服务器首先使用location /file/{......}块将该 URL 进行重写为"http://www.myweb.name/file/download/mp3/1.mp3",然后再由location / {......}块转发到后端的 backend 服务器组中实现负载均衡。这样,就实现了带有 URL 重写功能的负载均衡。

参考文献

  • [Nginx 高性能 Web 服务器详解]
Last Updated 2/18/2025, 5:05:12 PM