《深入理解Nginx:模块开发与架构解析》一2.5 用HTTP proxy module配置一个反向代理服务器

本文涉及的产品
传统型负载均衡 CLB,每月750个小时 15LCU
应用型负载均衡 ALB,每月750个小时 15LCU
云解析 DNS,旗舰版 1个月
简介: 本节书摘来自华章出版社《深入理解Nginx:模块开发与架构解析》一书中的第2章,第2.5节,作者 陶辉,更多章节内容可以访问云栖社区“华章计算机”公众号查看

2.5 用HTTP proxy module配置一个反向代理服务器

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

image

与Squid等其他反向代理服务器相比,Nginx的反向代理功能有自己的特点,如图2-4所示。

image

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

2.5.1 负载均衡的基本配置

作为代理服务器,一般都需要向上游服务器的集群转发请求。这里的负载均衡是指选择一种策略,尽量把请求平均地分布到每一台上游服务器上。下面介绍负载均衡的配置项。
(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集群里的上游服务器数量进行取模,然后以取模后的结果把请求转发到相应的上游服务器中。这样就确保了同一个客户端的请求只会转发到指定的上游服务器中。
ip_hash与weight(权重)配置不可同时使用。如果upstream集群中有一台上游服务器暂时不可用,不能直接删除该配置,而是要down参数标识,确保转发策略的一贯性。例如:

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

(4)记录日志时支持的变量
如果需要将负载均衡时的一些信息记录到access_log日志中,那么在定义日志格式时可以使用负载均衡功能提供的变量,见表2-2。
image

例如,可以在定义access_log访问日志格式时使用表2-2中的变量。
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';

2.5.2 反向代理的基本配置

下面介绍反向代理的基本配置项。
(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设置为允许转发。例如:

proxy_pass_header X-Accel-Redirect;

(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://frontend/one/some/uri/

proxy_redirect http://localhost:8000/two/ http://frontend/one/;

这里还可以使用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模块的说明了解,只有深入地理解,才能实现一个高性能的反向代理服务器。本节只是介绍反向代理服务器的基本功能,在第12章中我们将会深入地探索upstream机制,到那时,读者也许会发现ngx_http_proxy_module模块只是使用upstream机制实现了反向代理功能而已。

相关文章
|
25天前
|
安全 网络协议 应用服务中间件
AJP Connector:深入解析及在Apache HTTP Server中的应用
【9月更文挑战第6天】在Java Web应用开发中,Tomcat作为广泛使用的Servlet容器,经常与Apache HTTP Server结合使用,以提供高效、稳定的Web服务。而AJP Connector(Apache JServ Protocol Connector)作为连接Tomcat和Apache HTTP Server的重要桥梁,扮演着至关重要的角色
43 2
|
1月前
|
Shell
HTTP状态码解析:在Haskell中判断响应成功与否
HTTP状态码解析:在Haskell中判断响应成功与否
|
1天前
使用Netty实现文件传输的HTTP服务器和客户端
本文通过详细的代码示例,展示了如何使用Netty框架实现一个文件传输的HTTP服务器和客户端,包括服务端的文件处理和客户端的文件请求与接收。
6 1
使用Netty实现文件传输的HTTP服务器和客户端
|
18天前
|
存储 弹性计算 缓存
阿里云服务器ECS通用型实例规格族特点、适用场景、指标数据解析
阿里云服务器ECS提供了多种通用型实例规格族,每种规格族都针对不同的计算需求、存储性能、网络吞吐量和安全特性进行了优化。以下是对存储增强通用型实例规格族g8ise、通用型实例规格族g8a、通用型实例规格族g8y、存储增强通用型实例规格族g7se、通用型实例规格族g7等所有通用型实例规格族的详细解析,包括它们的核心特点、适用场景、实例规格及具体指标数据,以供参考。
阿里云服务器ECS通用型实例规格族特点、适用场景、指标数据解析
|
22天前
阿里云服务器带宽价格参考:选择1M、3M、5M、10M宽带价格解析
阿里云服务器1M、3M、5M、10M宽带需要多少钱?单说阿里云服务器宽带多少钱,而不确定云服务器实例规格及cpu和内存配置的话,是没办法具体说多少钱的,因为云服务器的价格受很多因素影响。本文将详细解析阿里云服务器在选择1M、3M、5M、10M不同带宽下的价格差异,以供大家参考。
阿里云服务器带宽价格参考:选择1M、3M、5M、10M宽带价格解析
ly~
|
1天前
|
网络协议 应用服务中间件 Apache
如何在 DNS 记录中设置反向代理服务器?
要设置反向代理服务器,首先需安装配置软件(如 Nginx 或 Apache),并确保域名正确指向服务器 IP。接着,在 DNS 中设置 A 或 CNAME 记录,将域名指向反向代理服务器。然后编辑 Nginx 或 Apache 的配置文件,将请求转发至后端服务器。最后,通过浏览器访问域名测试配置是否成功,并使用工具检查请求流向和响应情况。
ly~
13 3
ly~
|
1天前
|
域名解析 网络协议 Linux
如何测试 DNS 记录中的反向代理服务器是否生效?
本文介绍了三种测试反向代理服务器配置的方法。首先,通过命令行工具如 `ping`、`nslookup` 和 `dig` 检查域名解析是否指向正确的 IP 地址。其次,利用 Web 浏览器访问域名,验证页面加载正常且请求头信息无误。最后,借助网络抓包工具如 `Wireshark` 和 `tcpdump` 分析数据包,确保请求正确转发并返回预期响应。
ly~
12 2
|
11天前
http数据包抓包解析
http数据包抓包解析
|
1月前
HAProxy的高级配置选项-配置haproxy支持https协议及服务器动态上下线
文章介绍了如何配置HAProxy以支持HTTPS协议和实现服务器的动态上下线。
90 8
HAProxy的高级配置选项-配置haproxy支持https协议及服务器动态上下线
|
13天前
|
前端开发 JavaScript 安全
深入解析 http 协议
HTTP(超文本传输协议)不仅用于传输文本,还支持图片、音频和视频等多种类型的数据。当前广泛使用的版本为 HTTP/1.1。HTTPS 可视为 HTTP 的安全增强版,主要区别在于添加了加密层。HTTP 请求和响应均遵循固定格式,包括请求行/状态行、请求/响应头、空行及消息主体。URL(统一资源定位符)用于标识网络上的资源,其格式包含协议、域名、路径等信息。此外,HTTP 报头提供了附加信息,帮助客户端和服务端更好地处理请求与响应。状态码则用于指示请求结果,如 200 表示成功,404 表示未找到,500 表示服务器内部错误等。
16 0
深入解析 http 协议

推荐镜像

更多