nignx反向代理和负载均衡
Nginx 作为反向代理服务器和负载均衡器在网络架构中扮演了重要角色。它能够分发客户端请求到多台后端服务器,从而提高应用的可用性和性能,还可隐藏后端服务器,提高安全性。
可代理到http服务器,或其他协议的服务,如FastCGI、uwsgi、SCGI、memcaced。
使用proxy_pass指令,指定域名或ip地址,还可能包括端口 URI。代理到非http服务,使用相应**_pass指令:
如fastcgi_pass, uwsgi_pass …
1 | location /some/path/ { |
1 | server { |
使用https
1 | server { |
在 Nginx 反向代理配置中,以下几个关键的指令用于控制请求的转发和响应的处理。
代理常用指令
proxy_pass
功能:将请求转发到指定的后端服务器。
语法:
proxy_pass URL;
用法:
proxy_pass
指令指定了请求将被转发到的目标服务器,可以是一个协议(如http
或https
)加地址,也可以是一个upstream
定义的服务器组。1
2
3location / {
proxy_pass http://backend_server;
}如果路径后面带有 URI,Nginx 会将该 URI 与请求 URI 的匹配部分一起转发。
代理服务器,通常需要将客户端请求头部信息或自定义头部信息传递给后端服务器,使用proxy_set_header指令。
proxy_set_header
功能:设置在转发到后端服务器时需要附加或修改的请求头。
语法:
proxy_set_header FIELD VALUE;
常见用法:
Host
:保持客户端请求中的主机头,方便后端根据域名处理请求。1
proxy_set_header Host $host;
X-Real-IP
:将客户端的真实 IP 地址发送给后端。1
proxy_set_header X-Real-IP $remote_addr;
X-Forwarded-For
:用于记录代理链中的客户端 IP 地址。1
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
X-Forwarded-Proto
:告诉后端使用的协议(HTTP 或 HTTPS)。1
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout
和 proxy_connect_timeout
功能:设置与后端服务器的连接和读取超时时间。
语法:
proxy_connect_timeout time;
proxy_read_timeout time;
用法:
proxy_connect_timeout
设置连接到后端服务器的最大时间。1
proxy_connect_timeout 30s;
proxy_read_timeout
设置从后端服务器读取响应的最大时间。1
proxy_read_timeout 60s;
proxy_redirect
功能:修改后端服务器返回的重定向响应中的
Location
头。语法:
proxy_redirect default;
或proxy_redirect off;
用法:
修改重定向的 URL。
1
proxy_redirect http://backend.example.com/ https://example.com/;
default
表示使用默认重写规则,off
表示不进行任何修改。
proxy_cache
功能:启用响应缓存以提高性能。
语法:
proxy_cache zone;
用法:
zone
是定义的缓存区域名,使用proxy_cache_path
指令定义。1
proxy_cache my_cache;
需要结合其他指令如
proxy_cache_valid
来控制缓存策略。
proxy_buffering
功能:控制代理缓冲行为。
语法:
proxy_buffering on|off;
用法:
on
表示启用缓冲(默认),off
表示禁用缓冲。1
proxy_buffering off;
proxy_buffers
功能:设置用于存储来自后端服务器的响应的缓冲区大小和数量。
语法:
proxy_buffers number size;
用法:
设置缓冲区数量和每个缓冲区的大小。
1
proxy_buffers 8 16k;
反向代理示例
结合上述指令,完整的 Nginx 反向代理配置示例:
1 | http { |
代理缓存
代理缓存(proxy_cache
),它允许 Nginx 缓存从后端服务器获取的响应数据,并在后续的请求中直接从缓存中提供这些数据,而无需再次请求后端服务器。这不仅可以减轻后端服务器的负载,还可以提高响应速度。
当客户端向 Nginx 发送请求时,Nginx 首先检查缓存中是否已经存在该请求的响应。如果存在并且未过期,Nginx 会直接将缓存中的数据返回给客户端。如果缓存中没有响应数据或数据已过期,Nginx 会将请求转发到后端服务器,获取响应后再将其缓存,以供后续请求使用。
配置代理缓存
要配置 Nginx 的代理缓存,通常需要以下几个步骤:
1. 定义缓存区域
首先,定义一个缓存区域,用来存储缓存的内容。使用 proxy_cache_path
指令指定缓存的位置、大小以及其他缓存参数。
1 | http { |
/var/cache/nginx
:缓存文件的存储路径。levels=1:2
:缓存文件目录层次结构,用于提高文件系统的性能。keys_zone=my_cache:10m
:定义一个名为my_cache
的缓存区域,10m
表示存储元数据(如缓存键)的内存大小。max_size=10g
:缓存区域的最大大小,超过后旧的缓存文件会被删除。inactive=60m
:缓存文件在 60 分钟内未被访问则过期删除。use_temp_path=off
:禁用使用临时路径,提高性能。
2. 在服务器块中启用缓存
在需要缓存的服务器块或位置块中启用缓存,并设置缓存相关参数。
1 | server { |
proxy_cache my_cache;
:启用my_cache
区域的缓存。proxy_cache_valid
:设置不同状态码响应的缓存时间。200
:正常的响应(如200 OK
)。302
:重定向响应。404
:未找到的响应。
proxy_cache_key
:定义缓存键,决定哪些请求会被缓存。通常包括协议、请求方法、主机名和请求 URI。proxy_cache_use_stale
:当后端服务器不可用或请求超时时,使用旧的缓存数据。常用选项包括error
、timeout
、invalid_header
、updating
等。add_header X-Cache-Status $upstream_cache_status;
:在响应头中添加缓存状态信息,如HIT
、MISS
或EXPIRED
,帮助调试。
3. 设置缓存控制头
Nginx 默认会遵循后端服务器的 Cache-Control
和 Expires
头来决定是否缓存和缓存多久。可以通过 proxy_ignore_headers
指令忽略这些头信息,自定义缓存策略。
1 | location / { |
常见的代理缓存配置示例
1 | http { |
缓存管理和监控
清除缓存:可以通过删除缓存目录中的文件手动清除缓存,也可以使用 Nginx 的
nginx -s reload
命令重新加载配置。缓存监控:通过查看响应头中的
X-Cache-Status
信息(如HIT
、MISS
),可以了解缓存的命中率。缓存日志:启用访问日志,结合缓存状态,分析缓存效果。
通过合理配置 Nginx 代理缓存,可以大幅提高网站的响应速度,减轻后端服务器的负载,提高整体性能。
参见:
nginx负载均衡
Nginx 负载均衡是一种用于将客户端请求分发到多个后端服务器的技术,它可以提高应用程序的性能、可用性和容错性。Nginx 充当一个前端代理服务器,将请求根据特定的算法分配给一组后端服务器(也称为 upstream
)。这些后端服务器可以是 Web 服务器、应用服务器、数据库服务器等。Nginx 提供了多种负载均衡算法和配置选项,可以根据不同的需求进行优化。
常见的负载均衡算法
Nginx 支持以下几种常用的负载均衡算法:
- 轮询(Round Robin):默认的负载均衡方式,每个请求按照顺序依次分发到不同的后端服务器。
- 加权轮询(Weighted Round Robin):允许为每个服务器分配权重(weight),权重越高,分配的请求越多,适合后端服务器性能不均的情况。
- 最少连接数(Least Connections):将请求分发给当前连接数最少的服务器,适用于后端处理时间较长的场景。
- IP 哈希(IP Hash):基于客户端 IP 地址的哈希值分配请求,确保同一个客户端总是被分配到同一台后端服务器。适合需要会话保持的场景。
- 一致性哈希(Consistent Hashing):用于在缓存或分布式存储场景下确保同一组数据总是落到同一台服务器上。
负载均衡配置http load balancing
首先使用upstream
指令定义该组,放置在http上下文中。
组中的服务器用server
指令配置
1 | http { |
使用proxy_pass
指令将请求传递到服务器组
1 | server { |
结合起来,http请求代理到后端服务器组
1 | http { |
upstream块中未指定负载均衡算法,默认使用round robin算法,即轮询。
选择负载均衡算法
1. round robin
循环法 在服务器间均匀分布,并考虑服务器权重。默认使用此负载均衡策略,不需要额外的配置。
1 | http { |
可以为每个后端服务器设置权重,以调整服务器接收请求的比例。
1 | http { |
weight
参数设置服务器的权重,权重越高,服务器接收请求的频率越高。
适用场景
Round Robin 算法适用于以下场景:
- 负载均衡:适用于负载较均匀、请求处理时间大致相同的场景。
- 资源利用:多个服务器性能相似,不需要考虑单个服务器的负载情况。
- 简单部署:不需要复杂的负载均衡策略,快速实现请求分发。
2. least connections
最少连接 将请求分配给连接数最少的服务器
使用least_conn
指令配置
1 | http { |
进阶配置
可以为每个后端服务器设置权重、连接数等参数,以更精细地控制负载均衡策略
1 | http { |
weight
参数设置服务器的权重,权重越高,服务器被选择的概率越大。
max_fails
参数指定最大失败尝试次数,达到此次数后服务器将被视为不可用。
fail_timeout
参数指定服务器在不可用状态下的超时时间。
适用场景
Least Connections 算法适用于以下场景:
- 请求处理时间不均匀:例如数据库查询、文件上传等场景,不同请求的处理时间可能差异较大。
- 高并发应用:例如电商网站、社交网络等,需要在高并发环境下均衡负载,避免某些服务器过载。
3. ip hash
ip哈希 根据客户端ip地址确定请求发送到服务器。使用ipv4地址的前3个8位字节,或整个ipv6地址计算哈希值。保证来自同一地址的请求到达同一服务器,除非该服务器不可用。
这种方法特别适合需要会话保持的应用场景,如购物车、用户登录等。
1 | http { |
如果其中一台服务器需要暂时从负载平衡轮换中删除,则可以使用down参数标记,本服务器要处理的请求会自动发送到组中下一个服务器
1 | http { |
注意事项
- 服务器故障处理:如果某台服务器宕机,IP Hash 可能导致部分客户端请求失败,需要结合其他健康检查和故障转移机制。
- 平衡性:IP Hash 的负载均衡效果依赖于客户端 IP 地址的分布,如果 IP 地址分布不均匀,负载可能不平衡。
- IPv6 支持:确保你的Nginx 版本支持 IPv6 地址的哈希计算。
可以为每个后端服服务器设置额外参数,如权重、失败处理等,weight/max_fails/fail_timeout.
4. generic hash
通用哈希(Generic Hash)算法是一种基于某些请求特征(如 URL、Cookie、Header 等)进行哈希运算来分配请求的算法。这种方法类似于 IP Hash,但可以根据更灵活的规则来决定如何分配请求,从而实现更细粒度的负载均衡和会话保持。
使用hash
指令指定基于指定请求特征的哈希负载均衡
1 | http { |
根据请求的user-Agent头进行哈希计算,使用$http_user_agent
参数
根据请求的 Cookie 进行一致性哈希运算,适用于需要基于用户标识(如会话 ID)进行会话保持的场景,使用$http_cookie
可以通过hash
指令的consistent
参数启用一致性哈希,提高哈希分布的一致性
启用一致性哈希后,添加或删除服务器时,只会影响部分请求的分配,提高系统的稳定性和可扩展性。
1 | http { |
5. least time
最短时间(仅限 NGINX Plus) - 对于每个请求,NGINX Plus 选择具有最低平均延迟和最少活动连接数的服务器,其中最低平均延迟是根据 least_time
不同的参数计算选择。
least_time
指令有三 个参数可选:
least_time header
:基于服务器的响应头时间进行选择。least_time last_byte
:基于服务器的整个响应时间(包括请求到最后一个字节)进行选择。least_time inflight
: 基于从服务器接收到完整响应所需的时间,并考虑当前未完成的请求数来选择目标服务器。
适用场景
Least Time 算法适用于以下场景:
- 高并发应用:如电商网站、社交网络等,需要在高并发环境下确保请求快速响应。
- 动态负载环境:如微服务架构,服务响应时间可能变化较大,Least Time 算法可以动态调整分配策略。
- 优化用户体验:希望尽量减少用户等待时间,提高系统响应速度。
6. random
随机负载均衡算法 通过随机选择一台后端服务器来处理请求。与其他负载均衡算法(如轮询、最少连接等)相比,随机负载均衡算法简单直接,适用于需要基本负载分配但不需要精细控制的场景。
可以为每个后端服务器分配权重,权重越高的服务器被选择的概率越大。如果指定了 two
参数,NGINX首先根据服务器权重随机选择两台服务器,然后使用指定的方法选择其中一台服务器:
- least_conn
- least_time=header
- least_time=last_byte
1 | upstream backend { |
注意:配置除循环之外的任何方法时,请放置相应的指令( hash
、 ip_hash
、 least_conn
、 least_time
或 random
)位于 upstream {}
块中的 server
指令列表上方。
server weights
前面例子已经用到了weight
指令
在round robin循环算法中,根据服务器权重分配请求,默认为1.权重越高,接收的请求数量也越多。
通过设置不同的权重,你可以根据后端服务器的处理能力分配请求。例如,处理能力较强的服务器可以设置较高的权重,以便处理更多的请求
1 | http { |
server slow-start
服务器慢启动 用于负载均衡场景下,防止新上线的服务节点因瞬间高负载,再次被标记为故障,设置慢启动可以平滑过渡。在upstream
模块中配置slow_start
指令
1 | http { |
通常与负载均衡算法一起使用,将slow_start
写在特写server
后面,那么慢启动策略只会用于该特定的服务器。
1 | http { |
enableing session persistence
启用会话保持
可以确保同一个客户端的请求始终被路由到一个后端服务器。对于需要在多次请求间保持状态的应用(如用户登录会话、购物车等)非常有用。
之前的负载算法中用到的hash, ip hash就是其中方法,使用hash
或ip_hash
指令。
1 | http { |
nginx plus支持三种会话持久性方法。使用sticky
指令设置,
- sticky cookie
- sticky route
- sticky learn
Sticky Cookie方法在服务器第一次响应客户端时设置一个Cookie,后续请求会使用这个Cookie来确定路由的后端服务器。nginx plus内置功能,nginx需要第三方模块支持,如nginx-sticky-module-ng
。
1 | upstream backend { |
nginx 下载安装nginx-sticky-module-ng
模块
1 | wget http://nginx.org/download/nginx-1.18.0.tar.gz |
如果已安装nginx,想添加模块
1 | git clone https://bitbucket.org/nginx-goodies/nginx-sticky-module-ng.git |
配置
1 | http { |
安全性:如果使用HTTPS,确保Cookie标记为Secure
以防止在不安全的连接中发送。这是一种安全最佳实践,用于保护会话Cookie免受中间人攻击。
1 | http { |
安全最佳实践
除了将Cookie标记为Secure
,还可以考虑以下安全措施:
- HttpOnly:将Cookie标记为
HttpOnly
,以防止通过客户端脚本(如JavaScript)访问Cookie。 - SameSite:将Cookie的
SameSite
属性设置为Lax
或Strict
,以防止跨站请求伪造(CSRF)攻击。
虽然在Nginx Plus中直接配置HttpOnly
和SameSite
属性较为复杂,但可以通过后端应用服务器设置这些属性。例如,在Nginx反向代理配置中可以通过HTTP头部设置:
1 | http { |
sticky route
这种方法通过在响应中插入一个“路由”信息,让后续请求能够始终路由到同一台后端服务器。
1 | http { |
基于Cookie的路由信息:可以通过应用程序在响应中设置一个包含路由信息的Cookie,以便Nginx在后续请求中使用。
1 | # 在应用程序中设置 Cookie,例如: |
sticky learn
在Nginx Plus中,sticky
的learn
模式是一种高级的会话持久性方法,通过动态学习客户端的会话信息(如Cookie或HTTP头)来决定将请求路由到哪个后端服务器。这种方法非常适用于需要高度灵活性的场景,如用户登录会话的管理。
1 | http { |
limiting the number of connections
在Nginx中,配置upstream
块中的queue
和max_conns
参数可以帮助控制后端服务器的连接和请求排队策略。这个配置非常有用,特别是在负载高峰期,可以防止后端服务器过载,并确保请求能够在一定时间内得到处理。
1 | upstream backend { |
- 防止过载:通过限制每个服务器的最大连接数,可以防止后端服务器被过多的请求淹没,从而保证服务的稳定性。
- 排队机制:即使所有后端服务器的连接都已达到上限,请求也不会立即被拒绝,而是进入队列等待处理,这提高了服务的可用性。
根据具体需求,还可以结合其他Nginx指令进行更详细的配置。例如,设置全局的连接限制和请求速率限制。
1 | http { |