4.4.1 相关指令和参数
在实现 Nginx 反向代理的基础上,可以基于 ngx_http_upstream_module 模块实现后端服务器的分组,权重分配,状态监测,调度算法等高级功能
https://nginx.org/en/docs/http/ngx_http_upstream_module.html
upstream name { server address [parameters]; }
server address [parameters];
hash key [consistent];
ip_hash;
least_conn;
keepalive connections;
keepalive_time time;
4.4.2 基本配置
基本使用
upstream group1 {
server 10.0.0.210;
server 10.0.0.159;
}
server {
listen 80;
server_name www.m99-josedu.com;
location / {
proxy_pass http://group1;
proxy_set_header host $http_host;
}
}
server {
listen 80;
root /var/www/html/www.m99-josedu.com;
server_name www.m99-josedu.com;
}
[root@ubuntu ~]
10.0.0.210 index
server {
listen 80;
root /var/www/html/www.m99-josedu.com;
server_name www.m99-josedu.com;
}
[root@ubuntu ~]
10.0.0.159 index
[root@ubuntu ~]
10.0.0.210 index
[root@ubuntu ~]
10.0.0.159 index
[root@ubuntu ~]
10.0.0.210 index
[root@ubuntu ~]
10.0.0.159 index
一台 Proxy Server 调度多个 Upstream
upstream group1 {
server 10.0.0.210;
server 10.0.0.159;
}
upstream group2 {
server 10.0.0.110:8080;
server 10.0.0.120:8080;
}
server {
listen 80;
server_name www.m99-josedu.com;
location / {
proxy_pass http://group1;
proxy_set_header host $http_host;
}
}
server {
listen 80;
server_name www.m99-josedu.net;
location / {
proxy_pass http://group2;
proxy_set_header host $http_host;
}
}
server {
listen 80;
root /var/www/html/www.m99-josedu.com;
server_name www.m99-josedu.com;
}
[root@ubuntu ~]
10.0.0.210 index
server {
listen 80;
root /var/www/html/www.m99-josedu.com;
server_name www.m99-josedu.com;
}
[root@ubuntu ~]
10.0.0.159 index
server {
listen 8080;
root /var/www/html/www.m99-josedu.net;
server_name www.m99-josedu.net;
}
[root@ubuntu ~]
10.0.0.110 index
server {
listen 8080;
root /var/www/html/www.m99-josedu.net;
server_name www.m99-josedu.net;
}
[root@ubuntu ~]
10.0.0.120 index
[root@ubuntu ~]
10.0.0.206 www.m99-josedu.com www.m99-josedu.net
[root@ubuntu ~]
10.0.0.210 index
[root@ubuntu ~]
10.0.0.159 index
[root@ubuntu ~]
10.0.0.210 index
[root@ubuntu ~]
10.0.0.159 index
[root@ubuntu ~]
10.0.0.110 index
[root@ubuntu ~]
10.0.0.120 index
[root@ubuntu ~]
10.0.0.110 index
[root@ubuntu ~]
10.0.0.120 index
upstream group1 {
server 10.0.0.210 weight=3;
server 10.0.0.159;
}
[root@ubuntu ~]
10.0.0.210 index
[root@ubuntu ~]
10.0.0.210 index
[root@ubuntu ~]
10.0.0.210 index
[root@ubuntu ~]
10.0.0.159 index
upstream group1 {
server 10.0.0.210 max_conns=2;
server 10.0.0.159;
}
server {
listen 80;
root /var/www/html/www.m99-josedu.com;
server_name www.m99-josedu.com;
limit_rate 10k;
}
[root@ubuntu ~]
[root@ubuntu ~]
[root@ubuntu ~]
[root@ubuntu ~]
10.0.0.159 index
[root@ubuntu ~]
10.0.0.159 index
[root@ubuntu ~]
10.0.0.159 index
[root@ubuntu ~]
10.0.0.159 index
[root@ubuntu ~]
10.0.0.159 index
[root@ubuntu ~]
10.0.0.159 index
后端服务器健康性检查
Nginx 的 upstream 指令对于后端服务器的健康性检查是被动检查,当有客户端请求被调度到该服务器上时,会在TCP协议层的三次握手时检查该服务器是否可用,如果不可用就调度到别的服务器,当不可用的次数达到指定次数时(默认是1次,由 Server 配置中的 max_fails 选项决定),在规定时间内(默认是10S,由 Server 配置中的 fail_timeout 选项决定),不会再向该服务器调度请求,直到超过规定时间后再次向该服务器调度请求,如果再次调度该服务器还是不可用,则继续等待一个时间段,如果再次调度该服务器可用,则恢复该服务器到调度列表中
upstream group1 {
server 10.0.0.210;
server 10.0.0.159;
}
server {
listen 80;
server_name www.m99-josedu.com;
location / {
proxy_pass http://group1;
proxy_set_header host $http_host;
}
}
[root@ubuntu ~]
[root@ubuntu ~]
10.0.0.159 index
[root@ubuntu ~]
10.0.0.159 index
[root@ubuntu ~]
10.0.0.159 index
[root@ubuntu ~]
10.0.0.159 index
[root@ubuntu ~]
[root@ubuntu ~]
[root@ubuntu ~]
10.0.0.159 index
[root@ubuntu ~]
<html>
<head><title>404 Not Found</title></head>
<body>
<center><h1>404 Not Found</h1></center>
<hr><center>nginx/1.18.0 (Ubuntu)</center>
</body>
</html>
upstream group1 {
server 10.0.0.210;
server 10.0.0.159;
server 10.0.0.213 backup;
}
server {
listen 80;
server_name www.m99-josedu.com;
location / {
proxy_pass http://group1;
proxy_set_header host $http_host;
}
}
[root@ubuntu ~]
10.0.0.210 index
[root@ubuntu ~]
10.0.0.159 index
[root@ubuntu ~]
10.0.0.210 index
[root@ubuntu ~]
10.0.0.213 -- 网站正在维护中,请稍后访问
设置后端服务器平滑下线#Proxy Server 配置upstream group1 {
server 10.0.0.210;
server 10.0.0.159;
}
server {
listen 80;
server_name www.m99-josedu.com;
location / {
proxy_pass http://group1;
proxy_set_header host $http_host;
}
}
server {
listen 80;
root /var/www/html/www.m99-josedu.com;
server_name www.m99-josedu.com;
limit_rate 10k;
}
[root@ubuntu ~]
[root@ubuntu ~]
ESTAB 0 0 10.0.0.210:80 10.0.0.206:35844 users:
(("nginx",pid=905,fd=5)) uid:33 ino:37122 sk:1001
cgroup:/system.slice/nginx.service <->
[root@ubuntu ~]
ESTAB 0 0 10.0.0.210:80 10.0.0.206:35844 users:
(("nginx",pid=905,fd=5)) uid:33 ino:37122 sk:1001
cgroup:/system.slice/nginx.service <->
upstream group1 {
server 10.0.0.210 down;
server 10.0.0.159;
}
server {
listen 80;
server_name www.m99-josedu.com;
location / {
proxy_pass http://group1;
proxy_set_header host $http_host;
}
}
[root@ubuntu ~]
[root@ubuntu ~]
10.0.0.159 index
[root@ubuntu ~]
10.0.0.159 index
[root@ubuntu ~]
10.0.0.159 index
[root@ubuntu ~]
10.0.0.159 index
4.4.3 负载均衡调度算法
源IP地址hash
ip_hash 算法只使用 IPV4 的前 24 位做 hash 运算,如果客户端IP前24位一致,则会被调度到同一台后端服务器
upstream group1 {
ip_hash;
server 10.0.0.210;
server 10.0.0.159;
}
server {
listen 80;
server_name www.m99-josedu.com;
location / {
proxy_pass http://group1;
proxy_set_header host $http_host;
}
}
[root@ubuntu ~]
10.0.0.159 index
[root@ubuntu ~]
10.0.0.159 index
[root@ubuntu ~]
10.0.0.159 index
[root@rocky ~]
10.0.0.159 index
[root@rocky ~]
10.0.0.159 index
[root@rocky ~]
10.0.0.159 index
C:\Users\44301>curl www.m99-josedu.com
10.0.0.159 index
C:\Users\44301>curl www.m99-josedu.com
10.0.0.159 index
C:\Users\44301>curl www.m99-josedu.com
10.0.0.159 index
upstream group1 {
hash $remote_addr;
server 10.0.0.210;
server 10.0.0.159;
server 10.0.0.213;
}
server {
listen 80;
server_name www.m99-josedu.com;
location / {
proxy_pass http://group1;
proxy_set_header host $http_host;
}
}
[root@ubuntu ~]
10.0.0.159 index
[root@ubuntu ~]
10.0.0.159 index
[root@ubuntu ~]
10.0.0.159 index
[root@rocky ~]
10.0.0.213 index
[root@rocky ~]
10.0.0.213 index
[root@rocky ~]
10.0.0.213 index
upstream group1 {
hash $remote_addr;
server 10.0.0.210 weight=1;
server 10.0.0.159 weight=2;
server 10.0.0.213 weight=3;
}
upstream group1 {
hash $request_uri;
server 10.0.0.210;
server 10.0.0.159;
server 10.0.0.213;
}
server {
listen 80;
server_name www.m99-josedu.com;
location / {
proxy_pass http://group1;
proxy_set_header host $http_host;
}
}
[root@ubuntu ~]
10.0.0.213 index
[root@ubuntu ~]
10.0.0.213 index
[root@ubuntu ~]
10.0.0.213 index
[root@ubuntu ~]
10.0.0.210 aaa
[root@ubuntu ~]
10.0.0.210 aaa
[root@ubuntu ~]
10.0.0.210 aaa
[root@rocky ~]
10.0.0.213 index
[root@rocky ~]
10.0.0.213 index
[root@rocky ~]
10.0.0.213 index
[root@rocky ~]
10.0.0.210 aaa
[root@rocky ~]
10.0.0.210 aaa
[root@rocky ~]
10.0.0.210 aaa
upstream group1 {
least_conn;
server 10.0.0.210;
server 10.0.0.159;
}
server {
listen 80;
server_name www.m99-josedu.com;
location / {
proxy_pass http://group1;
proxy_set_header host $http_host;
}
}
[root@ubuntu ~]
[root@ubuntu ~]
ESTAB 0 0 10.0.0.210:80 10.0.0.206:38880 users:
(("nginx",pid=905,fd=5)) uid:33 ino:57728 sk:1003
cgroup:/system.slice/nginx.service <->
[root@rocky ~]
10.0.0.159 index
[root@rocky ~]
10.0.0.159 index
[root@rocky ~]
10.0.0.159 index
upstream group1 {
hash $remote_addr;
server 10.0.0.210;
server 10.0.0.159;
server 10.0.0.213;
}
server {
listen 80;
server_name www.m99-josedu.com;
location / {
proxy_pass http://group1;
proxy_set_header host $http_host;
}
}
在上述配置中,三台后端服务器的权重都为 1,则总权重为 3,再使用客户端IP的 hash 值对总权重求余
假设当前调度情况如下
此时如果后端新增一台服务器,则总权重会变为 4,那么同样的 hash 值,最后的调度结果如下
我们会发现,新增后端服务器后,总权重发生变化,则所有前端的请求都会被重新计算,调度到和原来不同的后端服务器上了,这样会导致在原来后端服务器上创建的数据,在新的服务器上没有了
减少后端服务器或修改后端服务器权重,都会导致重新调度,会导致原有缓存数据失效(例如登录状态,购物车等)
一致性哈希
一致性哈希(Consistent Hashing)是一种用于分布式系统中数据分片和负载均衡的算法,其中的"hash环"是该算法的核心概念之一
在一致性哈希中,所有可能的数据节点或服务器被映射到一个虚拟的环上。这个环的范围通常是一个固定的哈希空间,比如0到2^32-1,每个数据节点或服务器被映射到环上的一个点,通过对其进行哈希计算得到。这个哈希值的范围也是在0到2^32-1之间
在这个环上,数据会被分散到最接近它的节点。当有新的数据要存储时,首先通过哈希计算得到该数据的哈希值,然后在环上找到离这个哈希值最近的节点,将数据存储在这个节点上。同样,当要查询数据时,也是通过哈希计算得到数据的哈希值,然后找到最近的节点进行查询
由于哈希环是一个环形结构,节点的添加和删除对整体的影响相对较小。当添加或删除节点时,只有相邻的节点受到影响,而其他节点保持不变。这使得一致性哈希算法在分布式系统中能够提供较好的负载均衡性能,同时减小了数据迁移的开销
总的来说,一致性哈希中的哈希环是通过哈希计算将数据节点映射到环上,以实现数据分片和负载均衡的分布式算法
upstream group1 {
hash $remote_addr consistent;
server 10.0.0.210;
server 10.0.0.159;
server 10.0.0.213;
}
| hash($remoute_addr)%(2^32-1) | | |
| | | |
| | | |
| | | |
| | | |
| | | |
环偏移
在一致性哈希中,哈希环可能会面临的一个问题是环偏移(Ring Wrapping)。环偏移指的是哈希环上的某个区域过于拥挤,而其他区域相对空闲,这可能导致负载不均衡。为了解决这个问题,一些改进的一致性哈希算法引入了虚拟节点(Virtual Nodes)的概念
虚拟节点是对物理节点的一种扩展,通过为每个物理节点创建多个虚拟节点,将它们均匀地分布在哈希环上。这样一来,每个物理节点在环上的位置会有多个副本,而不是只有一个位置。这样一来,即使哈希环上的某个区域过于拥挤,也可以通过调整虚拟节点的数量来使得负载更均衡
4.5 综合案例
实现 http 自动重定向至 https,并将客户端 https 请求通过负载均衡的方式反向代理到后端的多台 http 服务器上
upstream group1 {
server 10.0.0.210;
server 10.0.0.159;
}
server {
listen 80;
server_name www.m99-josedu.com;
return 302 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name www.m99-josedu.com;
ssl_certificate /usr/share/easy-rsa/pki/www.m99-josedu.com.pem;
ssl_certificate_key /usr/share/easy-rsa/pki/private/www.m99-josedu.com.key;
ssl_session_cache shared:sslcache:20m;
ssl_session_timeout 10m;
location / {
proxy_pass http://group1;
proxy_set_header host $http_host;
}
}
[root@ubuntu ~]
10.0.0.159 index
[root@ubuntu ~]
HTTP/1.1 302 Moved Temporarily
Server: nginx
Date: Sat, 17 Feb 2025 13:55:01 GMT
Content-Type: text/html
Content-Length: 138
Connection: keep-alive
Location: https://www.m99-josedu.com/
HTTP/2 200
server: nginx
date: Sat, 17 Feb 2025 13:55:01 GMT
content-type: text/html; charset=utf8
content-length: 17
last-modified: Wed, 14 Feb 2025 02:45:15 GMT
etag: "65cc293b-11"
accept-ranges: bytes
— END —
阅读原文:原文链接
该文章在 2025/7/1 23:14:08 编辑过