nginx教程第八篇:用HTTP proxy module配置一个反向代理服务器

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u013068377/article/details/82821671

反向代理( reverse proxy) 方式是指用代理服务器来接受Internet上的连接请求, 然后将
请求转发给内部网络中的上游服务器, 并将从上游服务器上得到的结果返回给Internet上请求
连接的客户端, 此时代理服务器对外的表现就是一个Web服务器。 充当反向代理服务器也是
Nginx的一种常见用法( 反向代理服务器必须能够处理大量并发请求) , 本文将介绍Nginx作
为HTTP反向代理服务器的基本用法。
由于Nginx具有“强悍”的高并发高负载能力, 因此一般会作为前端的服务器直接向客户
端提供静态文件服务。 但也有一些复杂、 多变的业务不适合放到Nginx服务器上, 这时会用
Apache、 Tomcat等服务器来处理。 于是, Nginx通常会被配置为既是静态Web服务器也是反向
代理服务器
( 如 下图 所示) , 不适合Nginx处理的请求就会直接转发到上游服务器中处理。
这里写图片描述

与Squid等其他反向代理服务器相比, Nginx的反向代理功能有自己的特点, 如 下图 所
示:
这里写图片描述
当客户端发来HTTP请求时, Nginx并不会立刻转发到上游服务器, 而是先把用户的请求
( 包括HTTP包体) 完整地接收到Nginx所在服务器的硬盘或者内存中, 然后再向上游服务器
发起连接, 把缓存的客户端请求转发到上游服务器。 而Squid等代理服务器则采用一边接收
客户端请求, 一边转发到上游服务器的方式。
Nginx的这种工作方式有什么优缺点呢? 很明显, 缺点是延长了一个请求的处理时间,
并增加了用于缓存请求内容的内存和磁盘空间。 而优点则是降低了上游服务器的负载, 尽量
把压力放在Nginx服务器上。

Nginx的这种工作方式为什么会降低上游服务器的负载呢? 通常, 客户端与代理服务器
之间的网络环境会比较复杂, 多半是“走”公网, 网速平均下来可能较慢, 因此, 一个请求可
能要持续很久才能完成。 而代理服务器与上游服务器之间一般是“走”内网, 或者有专线连
接, 传输速度较快。 Squid等反向代理服务器在与客户端建立连接且还没有开始接收HTTP包
体时, 就已经向上游服务器建立了连接。 例如, 某个请求要上传一个1GB的文件, 那么每次
Squid在收到一个TCP分包( 如2KB) 时, 就会即时地向上游服务器转发。 在接收客户端完整
HTTP包体的漫长过程中, 上游服务器始终要维持这个连接, 这直接对上游服务器的并发处
理能力提出了挑战。
Nginx则不然, 它在接收到完整的客户端请求( 如1GB的文件) 后, 才会与上游服务器
建立连接转发请求, 由于是内网, 所以这个转发过程会执行得很快。 这样, 一个客户端请求
占用上游服务器的连接时间就会非常短, 也就是说, Nginx的这种反向代理方案主要是为了
降低上游服务器的并发压力。
Nginx将上游服务器的响应转发到客户端有许多种方法。

负载均衡的基本配置

作为代理服务器, 一般都需要向上游服务器的集群转发请求。 这里的负载均衡是指选择
一种策略, 尽量把请求平均地分布到每一台上游服务器上。 下面介绍负载均衡的配置项:

1. upstream块
语法: upstream name{...}
配置块: http

upstream块定义了一个上游服务器的集群, 便于反向代理中的proxy_pass使用。 例如:

upstream backend {
    server backend1.example.com;
    server backend2.example.com;
    server backend3.example.com;
} 

server {
    location / {
        proxy_pass http://backend;
    }
}
2. server
语法: server name[parameters];
配置块: upstream

server配置项指定了一台上游服务器的名字, 这个名字可以是域名、 IP地址端口、 UNIX
句柄等, 在其后还可以跟下列参数:

· weight=number: 设置向这台上游服务器转发的权重, 默认为1。
· max_fails=number: 该选项与fail_timeout配合使用, 指在fail_timeout时间段内, 如果向
当前的上游服务器转发失败次数超过number, 则认为在当前的fail_timeout时间段内这台上游
服务器不可用。 max_fails默认为1, 如果设置为0, 则表示不检查失败次数。
· fail_timeout=time: fail_timeout表示该时间段内转发失败多少次后就认为上游服务器暂
时不可用, 用于优化反向代理功能。 它与向上游服务器建立连接的超时时间、 读取上游服务
器的响应超时时间等完全无关。 fail_timeout默认为10秒。
· down: 表示所在的上游服务器永久下线, 只在使用ip_hash配置项时才有用。
· backup: 在使用ip_hash配置项时它是无效的。 它表示所在的上游服务器只是备份服务
器, 只有在所有的非备份上游服务器都失效后, 才会向所在的上游服务器转发请求。
例如:
upstream backend {
    server backend1.example.com weight=5;
    server 127.0.0.1:8080 max_fails=3 fail_timeout=30s;
    server unix:/tmp/backend3;
}
3. ip_hash
语法: ip_hash;
配置块: upstream

在有些场景下, 我们可能会希望来自某一个用户的请求始终落到固定的一台上游服务器
中。 例如, 假设上游服务器会缓存一些信息, 如果同一个用户的请求任意地转发到集群中的
任一台上游服务器中, 那么每一台上游服务器都有可能会缓存同一份信息, 这既会造成资源
的浪费, 也会难以有效地管理缓存信息。 ip_hash就是用以解决上述问题的, 它首先根据客户
端的IP地址计算出一个key, 将key按照upstream集群里的上游服务器数量进行取模, 然后以取
模后的结果把请求转发到相应的上游服务器中。 这样就确保了同一个客户端的请求只会转发
到指定的上游服务器中。

注意:

  1. ip_hash与weight(权重) 配置不可同时使用;
  2. 如果upstream集群中有一台上游服务器暂时不可用, 不能直接删除该配置, 而是要down参数标识, 确保转发策略的一贯性;
  3. backup: 在使用ip_hash配置项时它是无效的。 它表示所在的上游服务器只是备份服务
    器, 只有在所有的非备份上游服务器都失效后, 才会向所在的上游服务器转发请求。

例如:

upstream backend {
    ip_hash;
    server backend1.example.com;
    server backend2.example.com;
    server backend3.example.com down;
    server backend4.example.com;
}
4. 记录日志时支持的变量

如果需要将负载均衡时的一些信息记录到access_log日志中, 那么在定义日志格式时可
以使用负载均衡功能提供的变量, 如下表 ( 访问上游服务器时可以使用的变量 ):

变量名 意义
$upstream_addr 处理请求的上游服务器地址
$upstream_cache_status 标识是否命中缓存,取值范围:MISS、EXPIRED、UPDATEING、STALE、HIT
$upstream_status 上游服务器返回相应的HTTP响应吗
$upstream_response_time 上游服务器的响应时间,精度到毫秒
$upstream_http_$HEADER HTTP的头部,如 upstream_http_host

例如:

可以在定义access_log访问日志格式时使用上表中的变量。
log_format timing '$remote_addr - $remote_user [$time_local] $request '
'upstream_response_time $upstream_response_time '
'msec $msec request_time $request_time';

log_format up_head '$remote_addr - $remote_user [$time_local] $request '
'upstream_http_content_type $upstream_http_content_type';

反向代理的基本配置

下面介绍反向代理的基本配置项:

1. proxy_pass
语法: proxy_pass URL;
配置块: location、 if

此配置项将当前请求反向代理到URL参数指定的服务器上, URL可以是主机名或IP地址
加端口的形式, 例如:

proxy_pass http://localhost:8000/uri/;

也可以是UNIX句柄:

proxy_pass http://unix:/path/to/backend.socket:/uri/;

还可以如上节负载均衡中所示, 直接使用upstream块, 例如:

upstream backend {
    …
} 

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

用户可以把HTTP转换成更安全的HTTPS, 例如:

proxy_pass https://192.168.0.1;

默认情况下反向代理是不会转发请求中的Host头部的。 如果需要转发, 那么必须加上配
置:

proxy_set_header Host $host;
2. proxy_method
语法: proxy_method method;
配置块: http、 server、 location

此配置项表示转发时的协议方法名。 例如设置为:
proxy_method POST;

那么客户端发来的GET请求在转发时方法名也会改为POST。

3. proxy_hide_header
语法: proxy_hide_header the_header;
配置块: http、 server、 location

Nginx会将上游服务器的响应转发给客户端, 但默认不会转发以下HTTP头部字段:
Date、 Server、 X-Pad和X-Accel-*。 使用proxy_hide_header后可以任意地指定哪些HTTP头部
字段不能被转发。 例如:

proxy_hide_header Cache-Control;
proxy_hide_header MicrosoftOfficeWebServer;
4. proxy_pass_header
语法: proxy_pass_header the_header;
配置块: http、 server、 location

与proxy_hide_header功能相反, proxy_pass_header会将原来禁止转发的header设置为允许
转发。

5. proxy_pass_request_body
语法: proxy_pass_request_body on|off;
默认: proxy_pass_request_body on;
配置块: http、 server、 location

作用为确定是否向上游服务器发送HTTP包体部分。

6. proxy_pass_request_headers
语法: proxy_pass_request_headers on|off;
默认: proxy_pass_request_headers on;
配置块: http、 server、 location

作用为确定是否转发HTTP头部。

7. proxy_redirect
语法: proxy_redirect [default|off|redirect replacement];
默认: proxy_redirect default;
配置块: http、 server、 location

当上游服务器返回的响应是重定向或刷新请求(如HTTP响应码是301或者302)时,
proxy_redirect可以重设HTTP头部的location或refresh字段。 例如, 
如果上游服务器发出的响应是302重定向请求, location字段的URI是http://localhost:8000/two/some/uri/ ,
那么在下面的配置情况下, 实际转发给客户端的location是http://frontendone/some/uri/ 。
    proxy_redirect http://localhost:8000/two/
    http://frontendone;
    
这里还可以使用ngx-http-core-module提供的变量来设置新的location字段。 例如:
    proxy_redirect http://localhost:8000/
    http://$host:$server_port/;
    
也可以省略replacement参数中的主机名部分, 这时会用虚拟主机名称来填充。 例如:
    proxy_redirect http://localhost:8000/two/one;
    
使用off参数时, 将使location或者refresh字段维持不变。 例如:
    proxy_redirect off;
    
使用默认的default参数时, 会按照proxy_pass配置项和所属的location配置项重组发往客
户端的location头部。 例如, 下面两种配置效果是一样的:
location one {
    proxy_pass http://upstream:port/two/;
    proxy_redirect default;
}

location one {
    proxy_pass http://upstream:port/two/;
    proxy_redirect http://upstream:port/two/one;
}
8. proxy_next_upstream
语法:proxy_next_upstream [error|timeout|invalid_header|http_500|http_502|http_503|http_504|http_404|off];
默认: proxy_next_upstream error timeout;
配置块: http、 server、 location

此配置项表示当向一台上游服务器转发请求出现错误时, 继续换一台上游服务器处理这
个请求。 前面已经说过, 上游服务器一旦开始发送应答, Nginx反向代理服务器会立刻把应
答包转发给客户端。 因此, 一旦Nginx开始向客户端发送响应包, 之后的过程中若出现错误
也是不允许换下一台上游服务器继续处理的。 这很好理解, 这样才可以更好地保证客户端只
收到来自一个上游服务器的应答。 proxy_next_upstream的参数用来说明在哪些情况下会继续
选择下一台上游服务器转发请求。
·error: 当向上游服务器发起连接、 发送请求、 读取响应时出错。
·timeout: 发送请求或读取响应时发生超时。
·invalid_header: 上游服务器发送的响应是不合法的。
·http_500: 上游服务器返回的HTTP响应码是500。
·http_502: 上游服务器返回的HTTP响应码是502。
·http_503: 上游服务器返回的HTTP响应码是503。
·http_504: 上游服务器返回的HTTP响应码是504。
·http_404: 上游服务器返回的HTTP响应码是404。
·off: 关闭proxy_next_upstream功能—出错就选择另一台上游服务器再次转发。
Nginx的反向代理模块还提供了很多种配置, 如设置连接的超时时间、 临时文件如何存
储, 以及最重要的如何缓存上游服务器响应等功能。 这些配置可以通过阅读
ngx_http_proxy_module模块的说明了解, 只有深入地理解, 才能实现一个高性能的反向代理
服务器。

猜你喜欢

转载自blog.csdn.net/u013068377/article/details/82821671