反向代理
1,原理
用户请求先到 Nginx,再由 Nginx 把请求转发给后端的应用服务器(比如 Tomcat、Node.js、Spring Boot)。 Nginx 在这里就像"中转站",客户端只知道自己连的是 Nginx,不知道真正提供服务的是哪台后端。
客户端 ---> Nginx ---> 多台后端服务器
2,配置
bash
vim /usr/local/nginx/conf/nginx.conf
如果nginx 只代理给后端一个服务器位置:
nginx
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://127.0.0.1:8080; # 把请求转发到后端 8080 端口
}
}
如果后端有多台服务器需要反向代理,则配置如下:
nginx
http {
#upstream 后端地址池的名称 { 中间写后端服务器的ip:port}如:
upstream backend {
server 192.168.37.133;
server 192.168.37.134;
}
server {
location / {
proxy_pass http://backend;
}
}
}
保存配置后,执行:
bash
nginx -s reload
现在访问 http://localhost/ ,实际会由 Nginx 转发到后端地址池。
负载均衡 load balance(LB)
Nginx 的负载均衡是它最常用的功能之一,可以将客户端请求分发到多台后端服务器,提高系统的并发 能力、可用性和稳定性。
基本原理
Nginx 作为反向代理服务器,接收来自客户端的请求,然后根据配置的负载均衡策略,将请求转发到后 端的多个应用服务器(upstream server)。
好处:
- 提高性能:分担单台服务器压力
- 高可用性:某台服务器宕机,Nginx 自动转发到其他正常的节点
- 可扩展性:轻松添加或移除后端节点
Nginx 支持的几种常见的分流算法(常用前4个):
1, 轮询(Round Robin)
后端服务器,一人分配一个任务,轮着来
轮询算法是 Nginx 的默认分流算法。它按顺序将请求依次分配给每一台后端服务器,直到最后 一台服务器,然后重新从第一台服务器开始。这种方法简单且均匀地分配了流量。
数据流向:每个请求依次被分配到下一个服务器。假设有三台服务器(Server A、Server B、Server C),第一个请求被分配到 Server A,第二个请求分配到 Server B,第三个请求分配到 Server C,第四 个请求又回到 Server A,依此类推。 特点:请求均匀分布,无视服务器的当前负载和响应时间。
配置示例:
nginx
upstream backend {
server backend1.example.com;
server backend2.example.com;
server backend3.example.com;
}
2,加权轮询(Weighted Round Robin)
加权轮询,以比例的方式分配任务给后端服务器
加权轮询算法允许为每台服务器设置权重,权重越大的服务器将会获得更多的请求。适用于服务器性能 不均衡的情况。
数据流向:根据服务器设置的权重值分配请求。假设 Server A 权重为 3,Server B 权重为 1,则 4 个请 求中,3 个会被分配到 Server A,1 个会被分配到 Server B。 特点:高权重服务器接收更多的请求,适用于服务器性能差异较大的场景。
配置示例:
nginx
upstream backend {
server backend1.example.com weight=3;
server backend2.example.com weight=1;
server backend3.example.com weight=2;
}
3, 最少连接数(Least Connections)
会根据后端服务器当前的连接数量(socket 三握)来分配任务
最少连接数算法将请求分配给当前活动连接数最少的服务器。这种算法适用于请求处理时间不均匀的情 况,可以有效平衡服务器的负载。
数据流向:每个请求被分配到当前连接数最少的服务器。例如,Server A 有 2 个连接,Server B 有 5 个 连接,新的请求会被分配到 Server A。 特点:动态均衡负载,适用于请求处理时间不一的场景。
配置示例:
nginx
upstream backend {
least_conn;
server backend1.example.com;
server backend2.example.com;
server backend3.example.com;
}
补充:查询 与 Nginx 建立的已连接(ESTABLISHED)的 TCP 连接数量
bash
netstat -natp | grep -i established | grep nginx| awk 'NR>=2{print}' | wc -l
- 依赖于
netstat -p来获取进程信息,这需要 root 权限才能看到其他用户的进程信息 - 如果 nginx 是 master 进程和 worker 进程,那么 master 进程通常以 root 运行,而 worker 进程以 www-data 或 nginx 用户运行
- 这个命令只统计 TCP 连接,因为 nginx 通常处理 HTTP(TCP)协议。如果你还想统计其他协议(如 UDP),那么这个命令就不适用。
bash
ss -ntp state established | grep nginx | wc -l
注意: ss 命令的输出格式与 netstat 不同,但同样可以过滤状态和进程。
这个命令在查询的是:当前 nginx 正在处理的已建立的 TCP 连接数。
4,IP 哈希(IP Hash)
实现会话保持的算法。短时间内,用户重复访问,Nginx 会直接把用户的连接请求直接交给上一次处理用户请求的服务器上,增加用户体验感+减少nginx 的资源消耗
IP 哈希算法通过计算客户端 IP 地址的哈希值,将请求始终分配给同一台服务器。适用于需要将特定客户 端的请求固定在同一台服务器上的场景。
数据流向:每个客户端的 IP 地址被哈希计算,然后根据哈希值将请求固定分配到某一台服务器。假设客 户端 X 的哈希值指向 Server A,客户端 Y 的哈希值指向 Server B,则无论多少次请求,X 的请求总是流 向 Server A,Y 的请求总是流向 Server B。 特点:同一个客户端总是被分配到同一台服务器,有助于会话保持。
配置示例:
nginx
upstream backend {
ip_hash;
server backend1.example.com;
server backend2.example.com;
server backend3.example.com;
}
5, 最少时间算法(Least Time)
最少时间算法基于请求的响应时间,将请求分配给响应时间最短的服务器。这种算法在 Nginx 1.15.3 及 以后版本中可用,适用于需要最大化响应速度的场景。
数据流向:每个请求分配到响应时间最短或平均连接时间最短的服务器。假设 Server A 的响应时间较 快,Server B 较慢,则新的请求更可能流向 Server A。
特点:进一步优化了最少连接算法,适用于高负载环境下的动态负载均衡。
配置示例:
nginx
upstream backend {
least_time header;
server backend1.example.com;
server backend2.example.com;
server backend3.example.com;
}
6,一致性哈希(Consistent Hashing): url_hash
一致性哈希算法可以保证当集群中某台服务器故障时,只有部分请求会重新分配到其他服务器,而不是 全部重新分配。这在缓存等场景中非常有用。
数据流向:根据请求的某个特定参数(如 URL、Cookie 或其他 Header),进行哈希计算,将请求分配 到哈希值对应的服务器。假设 Server A 和 Server B,参数 "foo" 的哈希值指向 Server A,参数 "bar" 的 哈希值指向 Server B,则 "foo" 请求总是流向 Server A,"bar" 请求总是流向 Server B。
特点:适应服务器节点变动,减少请求的重新分配,适合缓存敏感的场景。
配置示例(需要第三方模块如 ngx_http_upstream_hash_module):
nginx
upstream backend {
hash $request_uri consistent;
server backend1.example.com;
server backend2.example.com;
server backend3.example.com;
}
配置示例
基础轮询
nginx
http {
upstream backend {
server 192.168.0.101;
server 192.168.0.102;
}
server {
listen 80;
}
}
location / {
proxy_pass http://backend;
}
带权重和故障转移
nginx
upstream backend {
server 192.168.0.101 weight=3 max_fails=3 fail_timeout=30s;
server 192.168.0.102 weight=1 max_fails=3 fail_timeout=30s;
}
# max_fails 表示允许失败的次数,fail_timeout 表示多久后重试