Nginx的代理服务以及负载均衡

881 阅读12分钟
原文链接: click.aliyun.com

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

  • 正向代理服务器用来让局域网的客户机接入外网访问外网资源的
  • 反向代理服务器用来让外网的客户接入局域网中的站点以访问站点中的资源
  • 正向代理和反向代理两个概念主要是明白自己的角色和目的,在正向代理服务器中,我们是客户端目的是访问外网的资源,在反向代理中,我们是站点,目的是把站点的资源发布出去让其他客户端能够访问.

Nginx的正向代理服务

下面是配置指令,主要是用在http,server,location中

resolver

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

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

      • address:DNS的IP.不指定端口的话默认53
      • time:设置数据包在网络中的有效时间.在访问站点时,有很多情况使得数据包在一定时间内不能被传递到目的地,但又不能让数据包无限期的存在,所以设置时长,到达指定时间还没到目的地.就会被丢弃,然后发送者就会接受到一个消息,并决定是否重新发送该数据包.
    • 例子:resolver 127.0.01 [::1]:5353 valid=30s;

resolver_timeout

  • 设置DNS解析超时时间

    • 语法:resolver_timeout time;

proxy_pass

  • 设置代理服务器的协议和地址,不仅仅用于代理服务,更主要的是应用于反向代理服务

    • 语法: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 $scheme://$http_host$request_uri;
    }
  }
  #设置DNS地址为8.8.8.8,使用默认的53端口作为DNS服务器的服务端口,代理服务
  的监听端口为82,Nginx接收的所有请求都由location块进行过滤处理
  • 需要注意的是server_name不可以写,但是resolver必须写,因为没有他Nginx服务器无法处理接收到的域名

Nignx的反向代理服务

  • 反向代理的客户端连接数由worker_process和worker_connections决定,计算方法是:worker_process*worker_connections/4;
  • 可以出现在http,server,location中
  • 下面涉及的指令主要由ngx_http_proxy_module模块进行解析处理,是标准HTTP模块

proxy_pass

  • 设置被代理服务器的地址,可以是主机名称,IP和地址加端口号等方式

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

        upstream proxy_svrs{
          server http://192.168.1.1:80/uri/;
          server http://192.168.1.2:80/uri/;
          server http://192.168.1.3:80/uri/;
        }
        server {
          listen 80;
          server_name www.web.name;
          location /{
            proxy_pass proxy_svrs;
          }
        }
      #需要注意的是,如果上面的proxy_pass proxy_svrs;改为proxy_pass http://proxy_svrs;
      那么upstream里面的server 后将改为server 192.168.1.1:80/uri/;
    • 另一个需要注意的是:如果URL中不包含URI,Nginx服务器不会改变原来地址的URI,但是如果包含了URI,Nginx服务器将会用新的URI替代原来的URI

      server {
        listen 80;
        server_name www.myweb.name;
        location / {
          proxy_pass http://192.168.101.1;
        }
      }
      #如果时候用http://www.myweb.name/server/发起请求.该请求被配置中显示的
      location块进行处理,由于proxy_pass指令的URL指令不含有URI,所以转向的地
      址为http://192.168.101.1/server
      server {
        listen 80;
        server_name www.myweb.name;
        location / {
          proxy_pass http://192.168.101.1/loc/;
        }
      }
      #如果时候用http://www.myweb.name/server/发起请求.该请求被配置中显示的
      location块进行处理,由于proxy_pass指令的URL指令含有URI,所以转向的地
      址为http://192.168.101.1/loc/;
      server{
        listen 80;
        server_name www.myweb.name;
        location / {
           proxy_pass http://192.168.43.202;
           #proxy_pass http://192.168.43.202/;
        }
      }
       #区别:
       访问:http://www.myweb.name/inedx.html; 时.无区别
      server{
        listen 80;
        server_name www.myweb.name;
        location /server/ {
           proxy_pass http://192.168.43.202;
           #proxy_pass http://192.168.43.202/;
        }
      }
       #区别:
       访问:http://www.myweb.name/server/inedx.html; 时.
       前面跳转到:http://192.168.43.202/server/index.html
       后面跳转到:http://192.168.43.20/index.html
      
       #自己理解:在proxy_pass有匹配时,就是截取location后的name后的字符串作为跳转路径
       比如上面的location /server/{...},访问路径是:http://www.myweb.name/server/index.html; 就是直截取server后的index.html出来

proxy_hide_header

  • 作用域:http,server,location
  • 用于设置Nginx在发送HTTP响应时,隐藏一些头域信息

    • 语法:proxy_hide_header fileld;

proxy_pass_header

  • 作用域:http,server,location
  • 设置Nginx在发送响应报文时,报文头中不包含来自代理服务器的头域信息,该指令可以设置这些头域信息以被发送

    • 语法: proxy_pass_header fileld

      • fileld:需要发送的头域

proxy_pass_request_body

  • 作用域:http,server,location
  • 设置是否将客户端请求的请求体发送给代理服务器

    • 语法:proxy_pass_request_body on | off; 默认on

proxy_pass_request_body

  • 作用域:http,server,location
  • 设置是否将客户端请求的请求头发送给代理服务器

    • 语法:proxy_pass_request_body on|off,默认on

proxy_set_header

  • 可以更改Nginx服务器接收到的客户端请求的请求头信息,然后将新的请求头发送给被代理的服务器

    • 语法:proxy_set_header fileld value;

      • value:所对应的头域的更改的值
    • 默认

      proxy_set_header Host $proxy_host;   #将目前HOst头域的值填充成客户端的地址
      proxy_set_header Connection close;
    • 实例

      proxy_set_header Host $http_host;
      #将当前location块的server_name指令值填充到Host头域
      proxy_set_header Host $host;   
      #将当前的location块的server_name指令值和listener指令值一起填充到Host头域
      proxy_set_header Host $host:$proxy_port;

proxy_set_body

  • 可以更改Nginx接收到的客户端请求的请求体信息,然后将新的请求体发送给被代理的服务器

    • 语法:proxy_set_body value

      • value:为更改的信息,支持使用文本,变量或者变量的组合

proxy_bind

  • 配置了多个基于名称或IP的主机的情况下,如果我们希望代理连接由指定的主机代理,就可以使用该指令进行配置(强制将与代理主机的链接绑定到指定的IP)

    • 语法:proxy_bind address

proxy_connection_timeout

  • 配置nginx与后端被代理服务器尝试建立连接的超时时间

    • 语法:proxy_connection_timeout time,默认60s

proxy_read_timeout

  • 配置nginx服务器向后端被代理服务器发出read请求后,等待响应的超时时间

    • 语法:proxy_read_timeout time默认60s

proxy_send_timeout

  • 配置Nginx服务器向后端被代理服务器发出write请求后等待响应的超时时间

    • 语法:proxy_send_timeout time默认 60s

proxy_method

  • 设置nginx请求被代理服务器时使用的请求方法.一般为POST和GET,设置之后客户端的请求方法被忽略

    • 语法:proxy_method method

proxy_ignore_client_abort

  • 设置在客户端中断网络请求时,nginx是否中断对被代理服务器的请求

    • 语法:proxy_ignore_client_abort on|off默认off

proxy_ignore_headers

  • 设置一些HTTP响应头中的头域,nginx接收到被代理服务器的响应数据后,不会处理被设置的头域

    • 语法:proxy_ignore_headers fileld ...;

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 : http://localhost:8080/proxy/some/uri/
      指令:proxy_redirect http://localhost:8080/proxy/ http://myweb/
        这样就更改了Location.返回的消息头也被更改了
      2.使用defalut,代表使用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指令配置全部设置为无效,也就是不开启

proxy_intercept_errors

  • 配置一个状态是开启还是关闭,开启时如果被代理服务器返回的HTTP状态码>=400,nginx就是用自己定义的错误页面error_page指令,如果关闭状态.nginx直接返回被代理服务器的HTTP状态返回客户端.

    • 语法:proxy_intercept_errors on|off

proxy_headers_hash_max_size

  • 用于配置存放HTTP报文头哈希表的容量

    • 语法:proxy_headers_hash_max_size 512默认512
    • nginx为了能快速检索HTTP报文头中的各项信息,比如MIME类型,请求头信息等,使用hash表存储这些信息
    • 配置HTTP报文头空间:proxy_headers_hash_bucket_size
    • 配置服务器名称的字符数长度:server_names_hash_max_size`server_names_hash_bucket_size`

proxy_headers_hash_bucket_size

  • 用于设置nginx申请存放HTTP报文头的哈希表容量的单位大小,默认64个字符

    • 语法:proxy_headers_hash_bucket_size size

proxy_next_upstream

  • 配置nginx反向代理时,如果使用upstream指令配置了一组服务器作为被代理服务器,服务器组中各项服务器的访问规则遵循upstream指令配置的轮询规则,同时可以使用可以配置在发送那些异常时,将请求顺次交由下一个组内服务器处理

    • 语法:proxy_next_upstream status ...

      • status:为服务器返回状态,可以是多个,状态包括

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

proxy_ssl_session_reuse

  • 用于配置是否使用基于ssl安全协议的会话连接(https)代理的服务器

    • 语法:proxy_ssl_session_reuse on|off,默认on

Proxy Buffer的配置

  • 启用后,nginx会异步的将被代理服务器的响应数据传递给客户端
  • Pory Buffer相关的指令的配置都是针对每一个请求起作用的,而不是全局概念,即每个请求都会按照这些指令的配置来配置各自的Buffer,Nginx不会生成一个公共的proxy buffer供代理请求使用
  • nginx首先尽可能从被代理服务器那接收相应数据,放置在proxy buffer中,如果接收过程中发现buffer没有足够大小来接收一次响应的数据,nginx会将部分接收到的数据临时存放在磁盘的临时文件中.一次响应数据被接收到完成或者buffer已经装满以后,nginx开始向客户端传输数据
  • 每个proxy buffer装满数据后,再从开始向客户端发送一直到proxy buffer中的数据全部传输给客户端的整个过程中,他处于BUSY状态,期间对他进行的其他操作都会失败.
  • 当proxy buffer关闭时,nginx只要接收到响应数据就会同步的传递给客户端,它本身不会读取完整的响应数据

proxy_buffering

  • 配置是否开启proxy buffer

    • 语法:proxy_buffering on|off;默认on
  • 开启和关闭proxy buffer还可以通过在HTTP响应头部的X-Accel-Buffering头域设置yesno来实现

proxy_buffers

  • 配置接收一次被代理服务器相应数据的proxy buffer个数和每个buffer 的大小

    • 语法:proxy_buffers numver size
    • 默认为:proxy_buffers 8 4k|8k

proxy_buffer_size

  • 配置从被代理服务器获取的第一部分响应数据的大小,该数据中农一般包含了HTTP响应头,Nginx服务器通过它来获取相应数据和被代理服务器的一些必要信息

    • 语法:proxy_buffer_size size

proxy_busy_buffers_size

  • 用于限制同时处于BUSY状态的proxy buffer的总大小.

    • 语法:proxy_busy_buffers_size size

proxy_temp_path

  • 配置磁盘上的一个文件路径.该文件用于临时存放代理服务器的大体积响应数据,就是buffer满了之后,剩余的相应数据临时存放在该文件中

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

      • level:设置在path变量设置的路径下第几级hash目录中存放临时文件
    • 案例:proxy_temp_path /nginx/proxy_web/spool/proxy_temp 1 2;

      • 临时文件路径可能像这样:/nginx/proxy_web/spool/proxy_temp/s/r/00001212
      • 这里的level1,2,3如果有值就代表存在一级,二级,三级子目录。

proxy_max_temp_file_size

  • 设置所有临时文件的总体积大小

    • 语法:proxy_max_temp_file_size size默认1024MB

proxy_temp_file_write_size

  • 用于配置同时写入临时文件的数据量的总大小,合理的设置可以避免IO负载过重导致系统性能下降的问题

    • 语法: proxy_temp_file_write_size size;

Proxy Cache的配置

  • Proxy Cache机制与缓存数据的产生和使用有很大关系
  • Buffer与Cache

    • 虽然都是用于提供IO吞吐效率的,但是还是不一样的概念,Buffer:缓冲,Cache缓存.
    • BUffer主要用于传输效率不同步或者优先级别不相同的设备之间传递数据,一般通过对一方数据进行临时存放,在统一发送的办法传递给另一方,以降低进程之间的等待时间,保证速度较快的进程不发生间断,临时存放的数据一旦传给对方,这些数据本身也就没有用处了
    • Cache:主要用于将硬盘上已有的数据在内存中建立缓存数据,提高数据的访问效率,对于过期不用的花奴才能可以随时销毁,但不会销毁硬盘上的数据
    • Buffer实现了代理服务器响应数据的异步传输
    • Cache实现nginx对客户端数据请求的快速响应
    • Cache依赖于Buffer,只有Buffer开启,Cache才会发挥作用
  • Proxy Store 也提供了 被代理服务器缓存到本地的方法

    • Proxy Store与Cache区别是:他对来自被代理服务器的相应数据,尤其是静态数据只进行简单的缓存,不支持缓存过期更新,内存索引建立等功能

proxy_cache

  • 配置一块公用的内存区域的名称,该区域可以存放缓存的索引数据,索引数据由nginx启动时缓存索引重建进程负责建立,在nginx服务器的整个运行过程中由缓存管理进程负责定时检查过期数据

    • 语法:proxy_cache zone |off

      • zone:设置的用于存放缓存索引的内存区域的名称
      • off默认

proxy_cache_bypass

  • 用于配置nginx向客户端发送响应数据时.不从缓存中获取的条件

    • 语法:proxy_cache_bypass string ...

      • string:当至少有一个字符串不为空或者不等于0,响应数据不从缓存中获取

proxy_cache_key

  • 设置nginx在内存中为缓存数据建立索引时使用的关键字

    • 语法:proxy_cache_key string
  • 如果希望缓存数据包含服务器主机名称等关键字可以是:proxy_cache_key "$scheme$host$request_uri"

proxy_cache_lock

  • 设置是否开启缓存的锁功能,开启后,nginx同时只能有一个请求填充缓存中的某一数据项.如果其他请求也想填充该项,必须等待锁释放

    • 语法:proxy_cache_lock on|off默认off

proxy_cache_lock_timeout

  • 设置缓存的锁功能开启后锁的超时时间

    • 语法:proxy_cache_lock_timeout time 默认5s

proxy_cache_min_uses

  • 设置客户端请求发送的次数,当客户端向被代理服务器发送相同请求达到该指令设定的次数后,nginx才对该请求的响应数据做缓存

    • 语法:proxy_cache_min_uses numver默认1

proxy_cache_path

  • 设置nginx存储缓存数据的路径以及和缓存索引相关的内容,只能http

    • 语法

      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目录中缓存数据,levels=1,表示一级hash目录,levels=1:2表示二级
      • name:size1:nginx的缓存索引重建进程在内存中为缓存数据建立索引,这一对用来设置存放缓存索引的内存区域的名称和大小
      • time1:设置强制更新缓存数据的时间,如果在设定时间内没有被访问,就从硬盘上删除,下次重新缓存.默认10s
      • size2:设置硬盘中缓存数据的大小限制
      • number:设置缓存索引重建进程每次加载的数据元素的数量上限,默认100
      • time2:设置缓存索引重建进程在一次遍历结束,下次遍历开始之间的暂停时长,默认50ms
      • times3:设置遍历一边磁盘缓存元数据的时间上限,默认200ms
    • 案例:proxy_cache_path /nginx/cache/a levels=1:1:2 keys_zone=c:1000m;

;proxy_cache_use_stale

  • 用来设置一些状态,当后端被代理的服务器处于这些状态时,nginx启用该功能
  • nginx在访问被代理服务器时出现错误时,nginx可以使用历史缓存响应客户端的请求,这些数据不一定和被代理服务器上最新的数据相一致,但对于更新频率不高的后端服务器来说,nginx服务器的该功能就能在一定程度上能够为客户提供不间断访问

    • 语法

      proxy_cache_use_stale error|timeout|invalid_header|updating|http_500|http_502|http_503
      |http_504|http_404|off ...;
      • updating:并不是指代理服务器在updating状态,而是指客户端请求的数据在nginx服务器中正好处于更新状态,默认off

proxy_cache_valid

  • 针对不同HTTP响应状态设置不同的缓存时间

    • 语法:proxy_cache_valid [code....] time

      • code如果不设置,nginx只为200,301,302做缓存,可以使用any表示缓存所有该指令中未设置的其他响应数据
      • proxy_cache_valid any 1m:对返回非200,302,301的相应数据缓存1分钟

proxy_no_cache

  • 配置在什么情况下不使用cache

    • 语法:proxy_no_cache string ....

      • string:当不为空或者不为0时,不启用cache

proxy_store

  • 配置是否在本地磁盘缓存来自被代理服务器的响应数据,也是一种缓存数据的方法,但是比Cache简单一些,它不提供缓存过期更新,内存索引建立等功能,对静态数据的效果比较好

    • 语法:proxy_store on | off | string默认off

      • string:自定义缓存文件的存放地址

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;                    #配置404的请求
      }
      location /fetch/{                                  #匹配404错误时的请求
        proxy_pass http://backend;
        proxy_store on;                                 #开启方法
        proxy_store_access user:rw group:rw all:r;
        root /data/www;                                #缓存数据的路径
      }

负载均衡

  • 大致原理是利用一定的分配策略将网络负载平衡的分摊到网络集群的各个操作单元上,使得单个重负载任务能够分担到多个单元上并行处理,或者使得大量并发访问或数据流量分担到多个单元上分别处理,从而减少用户的等待响应时间
  • 静态负载均衡算法

    • 在一般网络环境下也能达到较好的效果,主要有一般轮询算法,基于比率的加权轮询算法以及基于优先级的加权轮询算法
  • 动态负载均衡算法

    • 在较为负载的网络环境中适应性更强,效果更好,主要有基于任务量的最少连接优先算法,基于性能的最快响应优先算法,预测算法以及动态性能分配算法等

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

upstream backend{
  server 192.168.33.20:80;
  server 192.168.33.21:80;
  server 192.168.33.22:80;
}
server{
  listen 80;
  server_name www.myweb.name;
  index index.html;
  location / {
    proxy_pass http://backend;
    proxy_set_header Host $host;
  }
}
#backend中优先级全部为默认1,这样就会按照轮询制度来接收请求任务
#所有访问www.myweb.name的请求都会负载均衡到backend组

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

upstream backend {
  server 192.168.33.20:80 weight=5;
  server 192.168.33.21:80 weight=2;
  server 192.168.33.22:80;
}
server{
  listen 80;
  server_name www.myweb.name;
  index index.html;
  location / {
    proxy_pass http://backend;
    proxy_set_header Host $host;
  }
}
#权重高的优先接受和处理客户端请求

实例3:对特定资源实现负载均衡

upstream backendvide {
  server 192.168.33.20:80;
  server 192.168.33.21:80;
  server 192.168.33.22:80;
}
upstream backendfile {
  server 192.168.33.20:80;
  server 192.168.33.21:80;
  server 192.168.33.22:80;
}
server{
  listen 80;
  server_name www.myweb.name;
  index index.html;
  location /video/{
    proxy_pass htp://backendvide;
    proxy_set_header Host $host;
  }
  location /file/{
    proxy_pass htp://backendfile;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  }
}
#通过对location的uri不同的配置,实现对特定资源的负载均衡

实例4:对不同域名实现负载均衡

upstream backend1 {
  server 192.168.33.20:80 weight=5;
  server 192.168.33.21:80 weight=2;
  server 192.168.33.22:80;
}
upstream backend2 {
  server 192.168.33.23:80 weight=5;
  server 192.168.33.24:80 weight=2;
  server 192.168.33.25:80;
}
server{
  listen 80;
  server_name www.myweb.name;
  index index.html;
  location / {
    proxy_pass http://backend1;
    proxy_set_header Host $host;
  }
}  
server{
  listen 81;
  server_name www.other.name;
  index index.html;
  location / {
    proxy_pass http://backend2;
    proxy_set_header Host $host;
  }
}  
#对于server块中的server_name配置和对应的proxy_pass配置机器组实现不同域名的负载均衡

实例5:实现带有URL重写的负载均衡

upstream backend{
  server 192.168.33.20:80;
  server 192.168.33.21:80;
  server 192.168.33.22:80;
}
server{
  listen 80;
  server_name www.myweb.name;
  index index.html;
  location /file/ {
    rewrite ^(/file/.*)/media/(.*)\.*$ $1/mp3/$2.mp3 last;
  }
  location / {
    proxy_pass http://backend;
    proxy_set_header Host $host;
  }
}
#访问:http://www.myweb.name/file/download/media/1.mp3
该虚拟服务器首先会使用location /file/{...}进行匹配.然后将URL重写为
http://www.myweb.name/file/download/mp3/1.mp3
然后将向新的URL在由location /{}转发到机器群中实现负载均衡