Nginx 反向代理
代理基础知识
代理分为两种,分别是正向代理和反向代理
正向代理(Forward Proxy) 和 反向代理(Reverse Proxy) 是两种常见的代理服务器,它们用于处理 网络通讯中的不同方向和用途
正向代理(Forward Proxy)
特点
- 代理服务器位于客户端和目标服务器之间
- 客户端向代理服务器发送哀求,代理服务器将哀求发送到目标服务器,并将目标服务器的相应返回给客户端
- 目标服务器不知道客户端的存在,它只知道有一个代理服务器向其发送哀求
- 客户端通过正向代理访问互联网资源时,通常需要配置客户端来使用代理
用途
- 突破访问限定:用于绕过网络访问限定,访问受限定的资源
- 隐藏客户端身份:客户端可以通过正向代理隐藏其真实 IP 地址
反向代理(Reverse Proxy)
特点
- 代理服务器位于目标服务器和客户端之间
- 客户端向代理服务器发送哀求,代理服务器将哀求转发给一个或多个目标服务器,并将其中一个目标服务器的相应返回给客户端
- 目标服务器不知道终极客户端的身份,只知道有一个代理服务器向其发送哀求
- 用于将客户端的哀求分发给多个服务器,实现负载均衡
用途
- 负载均衡:通过将流量分发到多个服务器,确保服务器的负载匀称分布
- 缓存和加速:反向代理可以缓存静态内容,减轻目标服务器的负载,并提高访问速率
- 安全性:隐藏真实服务器的信息,提高安全性,同时可以举行 SSL 终止(SSL Termination)
雷同和不同
雷同点
- 中央层:正向代理和反向代理都是位于客户端和目标服务器之间的中央层。
- 代理功能:它们都充当了代理的脚色,处理哀求和相应,使得通讯更加灵活和安全
不同点
- 方向:正向代理代理客户端,反向代理代理服务器
- 目标:正向代理主要用于访问控制和隐藏客户端身份,反向代理主要用于负载均衡、缓存和提高安全性
- 配置:客户端需要配置使用正向代理,而反向代理是对服务器透明的,客户端无需感知
Nginx 和 LVS
Nginx 和 LVS(Linux Virtual Server) 都是流行的代理和负载均衡办理方案,但它们有一些不同的特点 和应用场景
选择使用 Nginx 照旧 LVS 取决于具体的应用需求和复杂度。Nginx 更适合作为 Web 服务器和应用层负 载均衡器,而 LVS 更适用于传输层负载均衡
雷同点
- 负载均衡:Nginx 和 LVS 都可以作为负载均衡器,将流量分发到多个后端服务器,提高系统的可用 性和性能。
- 性能:Nginx 和 LVS 都具有高性能的特点,能够处理大量并发连接和哀求
不同点
- 层次:Nginx 在应用层举行负载均衡和反向代理,而 LVS 在传输层举行负载均衡
- 功能:Nginx 除了负载均衡外,还可以作为反向代理和静态文件服务器;而 LVS 主要专注于负载均 衡,实现简单而高效的四层分发
- 配置和管理:Nginx 配置相对简单,易于管理,适用于各种规模的应用;LVS 需要深入了解 Linux 内核和相干配置,适用于大规模和对性能有更高要求的场景
LVS 不监听端口,不处理哀求数据,不参与握手流程,只会在内核层转发数据报文
Nginx 需要在应用层接收哀求,根据客户端的哀求参数和Nginx中配置的规则,再重新作为客户端向后 端服务器发起哀求
LVS 通常做四层代理,Nginx 做七层代理
实现 http 协议反向代理
相干指令和参数
Nginx 可以基于ngx_http_proxy_module 模块提供 http 协议的反向代理服务,该模块是 Nginx 的默认模块
- proxy_pass URL; # 转发的后端服务器地址,可以写主机名,域名,IP地址,也可以额外指定端口,
- # 作用域 location, if in location, limit_except
- proxy_hide_header field; # Nginx 默认不会将后端服务器的 Date,Server,X-Pad,X-Accel-... 这些响应头信息传给
- # 客户端,除了这些之外的响应头字段会回传,
- # 可以使用 proxy_hide_header 显式指定不回传的响应头字段
- # 作用域 http, server, location
-
- proxy_pass_header field; # 显式指定要回传给客户端的后端服务器响应头中的字段,
- #作用域 http, server, location
-
- proxy_pass_request_body on|off; # 是否向后端服务器发送客户端 http 请求的 body 部份,默认 on,
- # 作用域 http, server, location
-
- proxy_pass_request_headers on|off; # 是否向后端服务器发送客户端 http 请求的头部信息,默认 on
- # 作用域 http, server, location
-
- proxy_connect_timeout time; # Nginx与后端服务器建立连接超时时长,默认60S,超时会向客户端返回504
- # 作用域 http, server, location
-
- proxy_read_timeout time; # Nginx 等待后端服务器返回数据的超时时长,默认60S,超时会向客户端返回504
- # 作用域 http, server, location
-
- proxy_send_timeout time; # Nginx 向后端服务器发送请求的超时时长,默认60S,超时会向客户端返回408
- # 作用域 http, server, location
-
- proxy_set_body value; # 重新定义传给后端服务器的请求的正文,可以包含文本,变量等,
- # 作用域 http, server, location
- proxy_set_header field value; # 更改或添加请求头字段并发送到后端服务器,
- # 作用域http, server, location
-
- proxy_http_version 1.0|1.1; # 设置向后端服务器发送请求时的 http 协议版本,默认值1.0,
- # 作用域http, server, location
-
- proxy_ignore_client_abort on|off; # 客户端中断连接,Nginx 是否继续执行与后端的连接,默认值 off
- #客户端中断,Nginx 也会中断后端连接, on 表示 客户端中断,nginx 还会继续处理与后端在连接
- # 作用域 http, server, location
-
- proxy_headers_hash_bucket_size size; # 当配置了 proxy_hide_header和proxy_set_header的时候,
- # 用于设置nginx保存HTTP报文头的hash表的大小,默认值 64
- # 作用域 http, server, location
- proxy_headers_hash_max_size size; # 上一个参数的上限,默认值 512
- # 作用域 http, server, location
-
- proxy_next_upstream error|timeout|invalid_header|http_500|http_502|http_503|http_504|http_403|http_404|http_429|non_idempotent| off ...;
- # 当前配置的后端服务器无法提供服务时,因为何种错误而去请求下一个后端服务器
- # 默认值 error timeout, 表示当前后端服务器因为error 和 timeout 错误时,去请求 另一个后端服务器
- # 作用域 http, server, location
-
- proxy_cache zone|off; # 是否启用代理缓存,默认 off,不启用,zone 指缓存名称,
- # 作用域 http, server, location
- proxy_cache_path path [levels=levels] [use_temp_path=on|off] keys_zone=name:size
- [inactive=time] [max_size=size] [min_free=size] [manager_files=number]
- [manager_sleep=time] [manager_threshold=time] [loader_files=number]
- [loader_sleep=time] [loader_threshold=time] [purger=on|off]
- [purger_files=number] [purger_sleep=time] [purger_threshold=time];
- # 开启代理缓存后指定缓存数据的存放路径,作用域http,默认没有设置
- # path 表示缓存数据存放路径,要保证nginx 有写权限
- # levels 表示缓存数据目录层级,16进制表示,levels=1:2 表示第一级有16个目录,0-f,第一级中每个目录下有16*16个子目录,00-ff
- # keys_zone=name:size zone 表示缓存名称,先定义后使用,size 表示该zone 空间大小
- # inactive 表示缓存数据生命周期,默认值10分钟
- # max_size 表示缓存占用的磁盘空间最大能有多大
-
- proxy_cache_key string; # 指定缓存数据的key,不同的key 对应不同的缓存文件,
- #作用域 http, server, location
- # 默认值 $scheme$proxy_host$request_uri
-
- proxy_cache_valid [code ...] time; # 为不同响应状态码的数据设置不同的缓存时长,可设置多条,默认不设置,
- # 作用域 http, server, location
- proxy_cache_use_stale error|timeout|invalid_header|updating|http_500|http_502|http_503|http_504|http_403|http_404|http_429|off ...;
- # 在后端服务器报哪些错误的情况下,直接使用过期缓存数据响应客户端请求默认off,
- #作用域 http, server, location
-
- proxy_cache_methods GET|HEAD|POST ...; # 缓存哪些请求类型的数据,默认值 GET HEAD,
- #作用域 http, server, location
复制代码 根本配置
实现动静分离
根据条件举行调度,实现动静分离
脚色
IP
Client
10.0.0.158
Proxy Server
10.0.0.157
API Server
10.0.0.161
Static Server
10.0.0.151
Client配置
- [root@Rocky-9 ~]# cat /etc/hosts
- 10.0.0.157 www.a30.com
复制代码 Proxy Server 配置
- server{
- listen 80;
- server_name www.a30.com;
- #root /var/www/html/www.a30.com;
- location /static{
- proxy_pass http://10.0.0.151;
- proxy_set_header Host "static.a30.com";
- }
- location /api{
- proxy_pass http://10.0.0.161;
- proxy_set_header Host "api.a30.com";
- }
复制代码 API Server配置
- server{
- listen 80;
- server_name api.a30.com;
- root /apps/nginx/html/api.a30.com/;
- }
- [root@ubuntu24 sites-enabled]# cat /apps/nginx/html/api.a30.com/api/index.html
- api.a30.com
复制代码 Static Server配置
- server{
- listen 80;
- server_name static.a30.com;
- root /var/www/html/static.a30.com/;
- }
- [root@ubuntu22:sites-enabled]# cat /var/www/html/static.a30.com/static/index.html
- static.a30.com
复制代码 Client测试
- [root@Rocky-9 ~]# curl http://www.a30.com/api/index.html
- api.a30.com
- [root@Rocky-9 ~]# curl http://www.a30.com/static/index.html
- static.a30.com
复制代码 proxy_pass 后面加斜线和不加斜线的区别
- #没有斜线是追加
- # http://www.a30.com/api/index.html ----> http://api.a30.com/api/index.html
- location /api{
- proxy_pass http://10.0.0.161;
- proxy_set_header Host "api.a30.com";
- }
- #有斜线是替换
- # http://www.a30.com/api/index.html -----> http://api.a30.com/index.html
- location /api{
- proxy_pass http://10.0.0.161;
- proxy_set_header Host "api.a30.com";
- }
复制代码 实现对特定资源的代理
- location ~ \.(jpe?g|png|bmp|gif)$ {
- proxy_pass http://10.0.0.161;
- proxy_set_header Host "api.a30.com";
- }
复制代码 代理服务器实现数据缓存
前置条件:各服务器时间和时区先统一,方便测试
- #Proxy Server 配置
- #定义缓存
- proxy_cache_path /tmp/proxycache levels=1:2 keys_zone=proxycache:20m inactive=60s max_size=1g;
- server{
- listen 80;
- server_name www.a30.com;
- location /static{
- proxy_pass http://10.0.0.157/;
- proxy_set_header Host "static.a30.com";
- proxy_cache proxycache; #使用缓存
- proxy_cache_key $request_uri;
- proxy_cache_valid 200 302 301 90s;
- proxy_cache_valid any 2m; #此处一定要写,否则缓存不生效
-
- }
- }
- #重载,生成缓存目录
- [root@ubuntu ~]# nginx -s reload
- [root@ubuntu ~]# ll /tmp/proxycache/
- total 8
- drwx------ 2 www-data root 4096 Feb 12 23:09 ./
- drwxrwxrwt 14 root root 4096 Feb 12 23:09 ../
- #Static Server 配置
- server {
- listen 80;
- root /var/www/html/static.a30.com;
- server_name static.a30.com;
- }
- [root@ubuntu24 sites-enabled]# ls -lh /var/www/html/static.a30.com/
- total 8.0K
- -rw-r--r-- 1 root root 657 Sep 19 09:55 fstab
- -rw-r--r-- 1 root root 18 Sep 19 09:55 index.html
- #客户端测试
- [root@Rocky-9 ~]# curl http://www.a30.com/static/fstab
- #查看 Proxy Server 上的缓存数据,文件名就是key 的 hash 值
- [root@ubuntu22:sites-enabled]# tree /tmp/proxycache/
- /tmp/proxycache/
- └── 3
- └── ab
- └── 2d291e4d45687e428f0215bec190aab3
- 2 directories, 1 file
- #并不是一个文本文件
- [root@ubuntu22:sites-enabled]# file /tmp/proxycache/3/ab/2d291e4d45687e428f0215bec190aab3
- /tmp/proxycache/3/ab/2d291e4d45687e428f0215bec190aab3: data
- #查看当前时间和缓存文件时间
- [root@ubuntu22:sites-enabled]# date
- Thu Sep 19 10:03:38 AM CST 2024
- [root@ubuntu22:sites-enabled]# stat /tmp/proxycache/3/ab/2d291e4d45687e428f0215bec190aab3
- File: /tmp/proxycache/3/ab/2d291e4d45687e428f0215bec190aab3
- Size: 1254 Blocks: 8 IO Block: 4096 regular file
- Device: fd00h/64768d Inode: 4194322 Links: 1
- Access: (0600/-rw-------) Uid: ( 33/www-data) Gid: ( 33/www-data)
- Access: 2024-09-19 10:03:16.497567601 +0800
- Modify: 2024-09-19 10:02:55.416164600 +0800
- Change: 2024-09-19 10:02:55.416164600 +0800
- Birth: 2024-09-19 10:02:55.416164600 +0800
-
-
- #除了文件内容外,还有头部信息
- [root@ubuntu22:sites-enabled]# cat /tmp/proxycache/3/ab/2d291e4d45687e428f0215bec190aab3
- ?ꦘꧥꤪeudU"66eb8498-291"
- KEY: /static/fstab
- HTTP/1.1 200 OK
- Server: nginx
- Date: Thu, 19 Sep 2024 02:05:25 GMT
- Content-Type: application/octet-stream
- Content-Length: 657
- Last-Modified: Thu, 19 Sep 2024 01:55:36 GMT
- Connection: close
- ETag: "66eb8498-291"
- Accept-Ranges: bytes
- # /etc/fstab: static file system information.
- #
- # Use 'blkid' to print the universally unique identifier for a
- # device; this may be used with UUID= as a more robust way to name devices
- # that works even if disks are added and removed. See fstab(5).
- #
- # <file system> <mount point> <type> <options> <dump> <pass>
- # / was on /dev/ubuntu-vg/ubuntu-lv during curtin installation
- /dev/disk/by-id/dm-uuid-LVM-H5gHRIOORHBs4Od7xVmGBfQE2ZJSd1kxqhie9niuE1re5q1XVMJmVvoQ7stlUKe2 / ext4 defaults 0 1
- # /boot was on /dev/sda2 during curtin installation
- /dev/disk/by-uuid/8a0cc0fa-cc21-4fe4-ab25-4a43540d9f02 /boot ext4 defaults 0 1
- /swap.img none swap sw 0 0
- #生命周期结束后文件被删除
- #但是在缓存有效期内,后端服务器内容发生了更新,客户端获取的还是缓存数据
- #后端真实数据删除,客户端还能拿到缓存数据
复制代码 实现客户端IP地址透传
在使用Nginx 做代理的情况下,默认后端服务器无法获取客户端真实IP地址
脚色
IP
Client
10.0.0.158
Proxy Server
10.0.0.157
Real Server
10.0.0.151
默认情况下,后端服务器无法获取真实客户端IP
Proxy Server 配置
- server{
- listen 80;
- server_name www.a30.com;
- location / {
- proxy_pass http://10.0.0.151;
- }
复制代码 Real Server 配置
- server {
- listen 80 default_server;
- listen [::]:80 default_server;
- root /var/www/html;
- index index.html index.htm index.nginx-debian.html;
- server_name _;
- location / {
- return 200 ${remote_addr}---${http_x_real_ip}---${http_x_forwarded_for};
- }
- }
复制代码 Client测试
- [root@Rocky-9 ~]# curl www.a30.com
- 10.0.0.157------
- #后端服务器只能获取代理服务器IP
复制代码 修改代理服务器配置,透传真实客户端IP
- server{
- listen 80;
- server_name www.a30.com;
- location / {
- proxy_pass http://10.0.0.151;
- proxy_set_header X-Real-IP $remote_addr;
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- }
- #表示将客户端IP追加请求报文中X-Forwarded-For首部字段,多个IP之间用逗号分隔,如果请求中没有X-Forwarded-For,就使用$remote_addr
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- #客户端测试 $remote_addr 获取代理IP,$http_x_real_ip 获取真实客户端IP,
- $http_x_forwarded_for 获取真实客户端IP
- #客户端测试
- [root@Rocky-9 ~]# curl www.a30.com
- 10.0.0.157---10.0.0.158---10.0.0.158
复制代码 实现多级代理客户端IP透传
脚色
IP
Client
10.0.0.158
Proxy Server - First
10.0.0.161
Proxy Server - Second
10.0.0.157
Real Server
10.0.0.151
158 -----> 161 -----> 157 -----> 151
- #Proxy Server - First 配置server{ listen 80; server_name www.a30.com; location /{ proxy_pass http://10.0.0.157; }}#Proxy Server - Second 配置server { listen 80 default_server; listen [::]:80 default_server; root /var/www/html; index index.html index.htm index.nginx-debian.html; server_name _; location / { proxy_pass http://10.0.0.151; }}#Real Server 配置server {
- listen 80 default_server;
- listen [::]:80 default_server;
- root /var/www/html;
- index index.html index.htm index.nginx-debian.html;
- server_name _;
- location / {
- return 200 ${remote_addr}---${http_x_real_ip}---${http_x_forwarded_for};
- }
- }
- #客户端测试,Real Server 只能通过 $remote_addr 获取上一级代理的IP[root@Rocky-9 ~]# curl www.a30.com10.0.0.157------
复制代码 修改第一级代理服务器配置
- server{
- listen 80;
- server_name www.a30.com;
- location /{
- proxy_pass http://10.0.0.157;
- proxy_set_header X-Real-IP $remote_addr;
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- }
- }
- #客户端测试 $remote_addr 获取上一级代理IP,$http_x_real_ip 获取真实客户端IP,$http_x_forwarded_for 获取真实客户端IP
- [root@Rocky-9 ~]# curl www.a30.com
- 10.0.0.157---10.0.0.158---10.0.0.158
复制代码 继续修改第二级代理服务器配置
- server {
- listen 80 default_server;
- listen [::]:80 default_server;
- root /var/www/html;
- index index.html index.htm index.nginx-debian.html;
- server_name _;
- location / {
- proxy_pass http://10.0.0.151;
- proxy_set_header X-Real-IP $remote_addr;
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- }
- }
- #客户端测试
- # $remote_addr 获取上一级代理IP
- # $http_x_real_ip 获取上上一级代理IP
- # $http_x_forwarded_for 累加了第一级代理的 X-Forwarded-For 和第二级代理的 X-Forwarded-For
- [root@Rocky-9 ~]# curl www.a30.com
- 10.0.0.157---10.0.0.161---10.0.0.158, 10.0.0.161
复制代码 第一级代理不透传,不添加哀求头字
- server{
- listen 80;
- server_name www.a30.com;
- location /{
- proxy_pass http://10.0.0.157;
- #proxy_set_header X-Real-IP $remote_addr;
- #proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- }
- }
- [root@Rocky-9 ~]# curl www.a30.com
- 10.0.0.157---10.0.0.161---10.0.0.161
复制代码 实现 http 协议反向代理的负载均衡
相干指令和参数
在实现 Nginx 反向代理的基础上,可以基于 ngx_http_upstream_module 模块实现后端服务器的分 组,权重分配,状态监测,调度算法等高级功能
- upstream name { server address [parameters]; } # 定义一个后端服务器组,可以包含一台或多台服务器,
- # 定义好后在 proxy_pass 指令中引用,作用域 http
-
- server address [parameters]; # 在 upstream 中定义一个具体的后端服务器,作用域upstream
- # address 指定后端服务器 可以是IP地址,主机名,或UNIX Socket,可以加端口号
- # parameters 是可选掺数,具体有以下几个属性
- # weight=number 指定该 server 的权重,默认值都是1
- # max_conns=number 该 Server 的最大活动连接数,达到后将不再给该 Server 发送请求,默认值0,表示不限制
- # max_fails=number 后端服务器的下线条件,当客户端访问时,对本次调度选中的后端服务器连续进行检测多少次,如果都失败就标记为不可用,默认为1次,当客户端访问时,才会利用TCP触发对探测后端服务器健康性检查,而非周期性的探测
- # fail_timeout=time 后端服务器的上线条件,对已经检测到处于不可用的后端服务器,每隔此时间间隔再次进行检测是否恢复可用,如果发现可用,则将后端服务器参与调度,默认为10秒
- # backup 标记该 Server 为备用,当所有后端服务器不可用时,才使用此服务器
- # down 标记该 Server 临时不可用,可用于平滑下线后端服务器,新请求不再调度到此服务器,原有连接不受影响
- hash key [consistent]; # 使用自行指定的 Key 做 hash 运算后进行调度,Key 可以是变量,比如请求头中的字段,URI等,如果对应的 server 条目配置发生了变化,会导致相同的 key 被重新hash
- # consistent 表示使用一致性 hash,此参数确保该upstream 中的 server 条目发生变化时,尽可能少的重新 hash,适用于做缓存服务的场景,提高缓存命中率
- # 作用域 upstream
-
- ip_hash; # 源地址hash调度方法,基于的客户端的remote_addr(源地址IPv4的前24位或整个IPv6地址)做hash计算,以实现会话保持,作用域 upstream
- least_conn; # 最少连接调度算法,优先将客户端请求调度到当前连接最少的后端服务器,相当于LVS中的 LC 算法
- # 配合权重,能实现类似于 LVS 中的 WLC 算法
- # 作用域 upstream
-
- keepalive connections; # 为每个 worker 进程保留最多多少个空闲保活连接数,超过此值,最近最少使用的连接将被关闭
- # 默认不设置,作用域 upstream
-
- keepalive_time time; # 空闲连接保持的时长,超过该时间,一直没使用的空闲连接将被销毁
- # 默认值 1h,作用域 upstream
复制代码 根本配置
脚色
IP
Client
10.0.0.158
Proxy Server
10.0.0.157
Real Server - 1
10.0.0.161
Real Server - 2
10.0.0.151
- # Proxy Server 配置
- upstream group1{
- server 10.0.0.161;
- server 10.0.0.151;
- }
- server{
- listen 80;
- server_name www.a30.com;
- #root /var/www/html/www.a30.com;
- keepalive_timeout 15 30;
- autoindex on;
- location /{
- proxy_pass http://group1;
- proxy_set_header host $http_host;
- }
- # Real Server-1 配置
- server {
- listen 80;
- root /var/www/html/www.a30.com;
- server_name www.a30.com;
- }
- [root@ubuntu24 www.a30.com]# cat /apps/nginx/html/www.a30.com/index.html
- 10.0.0.161
- # Real Server-2 配置
- server {
- listen 80;
- root /var/www/html/www.a30.com;
- server_name www.a30.com;
- }
- [root@ubuntu22:sites-enabled]# cat /var/www/html/www.a30.com/index.html
- www.a30.com
- 10.0.0.151
- #客户端测试-轮循调度到后端服务器
- [root@Rocky-9 ~]# curl www.a30.com
- www.a30.com
- 10.0.0.151
- [root@Rocky-9 ~]# curl www.a30.com
- 10.0.0.161
- [root@Rocky-9 ~]# curl www.a30.com
- www.a30.com
- 10.0.0.151
- [root@Rocky-9 ~]# curl www.a30.com
- 10.0.0.161
复制代码 设置权重
- #每个 server 配置的默认权重是1,这种写法,两个 server 被调度的比例为 3:1
- upstream group1{
- server 10.0.0.161 weight=3;
- server 10.0.0.151;
- }
- [root@Rocky-9 ~]# curl www.a30.com
- www.a30.com
- 10.0.0.151
- [root@Rocky-9 ~]# curl www.a30.com
- 10.0.0.161
- [root@Rocky-9 ~]# curl www.a30.com
- 10.0.0.161
- [root@Rocky-9 ~]# curl www.a30.com
- 10.0.0.161
- [root@Rocky-9 ~]# curl www.a30.com
- www.a30.com
- 10.0.0.151
复制代码 限定最大活动连接数
- #10.0.0.161 同时只能维持两个活动连接
- upstream group1{
- server 10.0.0.161 max_conns=2;
- server 10.0.0.151;
- }
- #后端服务器配置
- server {
- listen 80;
- root /var/www/html/www.a30.com;
- server_name www.a30.com;
- limit_rate 10k;
- }
- #客户端测试,开6个窗口下载文件
- [root@ubuntu ~]# wget http://www.a30.com/test.img
- #查看 10.0.0.161 上的连接,2个活动连接
- [root@ubuntu ~]# ss -tnpe | grep 80
- #查看 10.0.0.151 上的连接,4个活动连接
- #客户端继续测试,新的请求都不会调度给 10.0.0.161
复制代码 后端服务器健康性查抄
Nginx 的 upstream 指令对于后端服务器的健康性查抄是被动查抄,当有客户端哀求被调度到该服务器 上时,会在TCP协议层的三次握手时查抄该服务器是否可用,如果不可用就调度到别的服务器,当不可 用的次数达到指定次数时(默认是1次,由 Server 配置中的 max_fails 选项决定),在规定时间内(默 认是10S,由 Server 配置中的 fail_timeout 选项决定),不会再向该服务器调度哀求,直到超过规定时 间后再次向该服务器调度哀求,如果再次调度该服务器照旧不可用,则继续期待一个时间段,如果再次 调度该服务器可用,则恢复该服务器到调度列表中
- upstream group1{
- server 10.0.0.161;
- server 10.0.0.151;
- }
- server{
- listen 80;
- server_name www.a30.com;
- location /{
- proxy_pass http://group1;
- proxy_set_header host $http_host;
- }
- }
- #停止 10.0.0.161 上的Nginx 服务
- [root@ubuntu ~]# systemctl stop nginx.service
- #客户端测试,检测到 10.0.0.161不可用,将请求都调度到 10.0.0.151
- [root@ubuntu ~]# curl www.a30.com
- 10.0.0.151 index
- [root@ubuntu ~]# curl www.a30.com
- 10.0.0.151 index
- [root@ubuntu ~]# curl www.a30.com
- 10.0.0.151 index
- #启用 10.0.0.161 上的Nginx 服务,客户端需要在距离上次检测该服务器不可用10S后才能调度到该服务器
- [root@ubuntu ~]# systemctl stop nginx.service
- #如果后端服务器上的资源不存在,则不会影响调度,会返回对应的状态码和状态页
- [root@ubuntu ~]# mv /var/www/html/www.a30.com/index.html{,bak}
- #客户端测试
- [root@ubuntu ~]# curl www.a30.com/index.html
- 10.0.0.151 index
- [root@ubuntu ~]# curl www.a30.com/index.html
- <html>
- <head><title>404 Not Found</title></head>
复制代码 设置备用服务器
- #设置 backup,当 10.0.0.161 和 10.0.0.151 都不可用时,请求会被调度到 10.0.0.213
- upstream group1{
- server 10.0.0.161;
- server 10.0.0.151;
- server 10.0.0.213 backup;
- }
- server{
- listen 80;
- server_name www.a30.com;
- location /{
- proxy_pass http://group1;
- proxy_set_header host $http_host;
- }
- }
- #当前151 和 161 可用,客户端测试
- [root@ubuntu ~]# curl www.a30.com
- 10.0.0.161 index
- [root@ubuntu ~]# curl www.a30.com
- 10.0.0.151 index
- [root@ubuntu ~]# curl www.a30.com
- 10.0.0.161 index
- #停止151和161的 Nginx 服务后再次测试
- [root@ubuntu ~]# curl www.a30.com
- 10.0.0.213
复制代码 设置后端服务器平滑下线
- #Proxy Server 配置
- upstream group1{
- server 10.0.0.161;
- server 10.0.0.151;
- }
- server{
- listen 80;
- server_name www.a30.com;
- location /{
- proxy_pass http://group1;
- proxy_set_header host $http_host;
- }
- }
- #后端服务器配置
- server {
- listen 80;
- root /var/www/html/www.a30.com;
- server_name www.a30.com;
- limit_rate 10k;
- }
- #客户端测试 - 开启两个窗口下载文件
- [root@ubuntu ~]# wget http://www.a30.com/test.img
- #在10.0.0.161 上查看,有一个连接
- [root@ubuntu ~]# ss -tnep | grep 80
- #在10.0.0.151 上查看,也有一个连接
- [root@ubuntu ~]# ss -tnep | grep 80
- #修改Proxy Server 配置,将 10.0.0.161 下线
- upstream group1{
- server 10.0.0.161 down;
- server 10.0.0.151;
- }
- #重载生效
- [root@ubuntu ~]# nginx -s reload
- #你会发现原来保持的下载连接没有中断,但新的请求,不会再被调度到 10.0.0.161
- [root@ubuntu ~]# curl www.a30.com
- 10.0.0.151 index
- [root@ubuntu ~]# curl www.a30.com
- 10.0.0.151 index
复制代码 负载均衡调度算法
源IP地址hash
ip_hash 算法只使用 IPV4 的前 24 位做 hash 运算,如果客户端IP前24位同等,则会被调度到同一台后 端服务器
- #Proxy Server 配置
- upstream group1{
- ip_hash;
- server 10.0.0.161;
- server 10.0.0.151;
- }
- server{
- listen 80;
- server_name www.a30.com;
- location /{
- proxy_pass http://group1;
- proxy_set_header host $http_host;
- }
- }
- #10.0.0.208 - 客户端测试,被调度到 10.0.0.151
- [root@ubuntu ~]# curl www.a30.com
- 10.0.0.151 index
- [root@ubuntu ~]# curl www.a30.com
- 10.0.0.151 index
- [root@ubuntu ~]# curl www.a30.com
- 10.0.0.151 index
- #10.0.0.213 - 客户端测试,被调度到 10.0.0.151
- [root@rocky ~]# curl www.a30.com
- 10.0.0.151 index
- [root@rocky ~]# curl www.a30.com
- 10.0.0.151 index
- [root@rocky ~]# curl www.a30.com
- 10.0.0.151 index
复制代码 使用自行指定的 key 做 hash 调度
- #Proxy Server 配置
- #三台 server 权重一样,调度算法 hash($remoute_addr)%3,值为 0,1,2根据不同的值调度到不同server
- upstream group1{
- hash $remote_addr;
- server 10.0.0.161;
- server 10.0.0.151;
- server 10.0.0.213;
- }
- server{
- listen 80;
- server_name www.a30.com;
- location /{
- proxy_pass http://group1;
- proxy_set_header host $http_host;
- }
- }
- #10.0.0.208 - 客户端测试,被调度到 10.0.0.151
- [root@ubuntu ~]# curl www.a30.com
- 10.0.0.151 index
- [root@ubuntu ~]# curl www.a30.com
- 10.0.0.151 index
- [root@ubuntu ~]# curl www.a30.com
- 10.0.0.151 index
- #10.0.0.207 - 客户端测试,被调度到 10.0.0.213
- [root@rocky ~]# curl www.a30.com
- 10.0.0.213 index
- [root@rocky ~]# curl www.a30.com
- 10.0.0.213 index
- [root@rocky ~]# curl www.a30.com
- 10.0.0.213 index
- #三台 server 权重不一样,调度算法 hash($remoute_addr)%(1+2+3),值为 0,1,2,3,4,5
- #0 调度到 161
- #1,2调度到 151
- #3,4,5调度到 213
- upstream group1{
- hash $remote_addr;
- server 10.0.0.161 weight=1;
- server 10.0.0.151 weight=2;
- server 10.0.0.213 weight=3;
- }
- #Proxy Server 配置
- #根据 request_uri 进行调度,不同客户端访问同一个资源会被调度到同一台后端服务器上
- upstream group1{
- hash $request_uri;
- server 10.0.0.161;
- server 10.0.0.151;
- server 10.0.0.213;
- }
- server{
- listen 80;
- server_name www.a30.com;
- location /{
- proxy_pass http://group1;
- proxy_set_header host $http_host;
- }
- }
- #10.0.0.208 - 客户端测试
- [root@ubuntu ~]# curl www.a30.com/index.html
- 10.0.0.213 index
- [root@ubuntu ~]# curl www.a30.com/index.html
- 10.0.0.213 index
- [root@ubuntu ~]# curl www.a30.com/index.html
- 10.0.0.213 index
- [root@ubuntu ~]# curl www.a30.com/a.html
- 10.0.0.161 aaa
- [root@ubuntu ~]# curl www.a30.com/a.html
- 10.0.0.161 aaa
- [root@ubuntu ~]# curl www.a30.com/a.html
- 10.0.0.161 aaa
- #10.0.0.207 - 客户端测试
- [root@rocky ~]# curl www.a30.com
- 10.0.0.213 index
- [root@rocky ~]# curl www.a30.com
- 10.0.0.213 index
- [root@rocky ~]# curl www.a30.com
- 10.0.0.213 index
- [root@rocky ~]# curl www.a30.com/a.html
- 10.0.0.161 aaa
- [root@rocky ~]# curl www.a30.com/a.html
- 10.0.0.161 aaa
复制代码 最少连接调度算法
- #Proxy Server 配置,最少连接调度算法
- upstream group1{
- least_conn;
- server 10.0.0.161;
- server 10.0.0.151;
- }
- server{
- listen 80;
- server_name www.a30.com;
- location /{
- proxy_pass http://group1;
- proxy_set_header host $http_host;
- }
- }
- #客户端开启一个下载连接,限速,让该连接一直保持
- [root@ubuntu ~]# wget www.a30.com/test.img
- #下载请求被调度到 10.0.0.161上了
- [root@ubuntu ~]# ss -tnep | grep 80
- #新开客户端测试,请求不会被调度到 10.0.0.161 上
- [root@rocky ~]# curl www.a30.com
- 10.0.0.151 index
- [root@rocky ~]# curl www.a30.com
- 10.0.0.151 index
- [root@rocky ~]# curl www.a30.com
- 10.0.0.151 index
复制代码 同等性 hash
- #Proxy Server 配置
- #三台 server 权重一样,调度算法 hash($remoute_addr)%3,值为 0,1,2 根据不同的值调度到不
- 同 server
- upstream group1{
- hash $remote_addr;
- server 10.0.0.161;
- server 10.0.0.151;
- server 10.0.0.213;
- }
- server{
- listen 80;
- server_name www.a30.com;
- location /{
- proxy_pass http://group1;
- proxy_set_header host $http_host;
- }
- }
复制代码 在上述配置中,三台后端服务器的权重都为 1,则总权重为 3,再使用客户端IP的 hash 值对总权重求余
假设当前调度情况如下
hash($remoute_addr)
hash($remoute_addr)%3
server
3,6,9
0,0,0
10.0.0.161
1,4,7
1,1,1
10.0.0.151
2,5,8
2,2,2
10.0.0.213
此时如果后端新增一台服务器,则总权重会变为 4,那么同样的 hash 值,最后的调度结果如下
hash($remoute_addr)
hash($remoute_addr)%4
server
4,8
0,0
10.0.0.161
1,5,9
1,1,1
10.0.0.151
2,6
2,2
10.0.0.213
3,7
3,3
10.0.0.223
我们会发现,新增后端服务器后,总权重发生变革,则所有前端的哀求都会被重新盘算,调度到和原来 不同的后端服务器上了,这样会导致在原来后端服务器上创建的数据,在新的服务器上没有了淘汰后端服务器或修改后端服务器权重,都会导致重新调度,会导致原有缓存数据失效(比方登录状 态,购物车等)
同等性哈希
同等性哈希(Consistent Hashing)是一种用于分布式系统中数据分片和负载均衡的算法,其中 的"hash环"是该算法的核心概念之一
在同等性哈希中,所有可能的数据节点或服务器被映射到一个虚拟的环上。这个环的范围通常是一个固 定的哈希空间,比如0到2^32-1,每个数据节点或服务器被映射到环上的一个点,通过对其举行哈希计 算得到。这个哈希值的范围也是在0到2^32-1之间
在这个环上,数据会被分散到最靠近它的节点。当有新的数据要存储时,首先通过哈希盘算得到该数据 的哈希值,然后在环上找到离这个哈希值最近的节点,将数据存储在这个节点上。同样,当要查询数据 时,也是通过哈希盘算得到数据的哈希值,然后找到最近的节点举行查询
由于哈希环是一个环形布局,节点的添加和删除对整体的影响相对较小。当添加或删除节点时,只有相 邻的节点受到影响,而其他节点保持不变。这使得同等性哈希算法在分布式系统中能够提供较好的负载 均衡性能,同时减小了数据迁移的开销
总的来说,同等性哈希中的哈希环是通过哈希盘算将数据节点映射到环上,以实现数据分片和负载均衡 的分布式算法
环偏移
在同等性哈希中,哈希环可能碰面对的一个题目是环偏移(Ring Wrapping)。环偏移指的是哈希环上 的某个地区过于拥挤,而其他地区相对空闲,这可能导致负载不均衡。为了办理这个题目,一些改进的 同等性哈希算法引入了虚拟节点(Virtual Nodes)的概念
虚拟节点是对物理节点的一种扩展,通过为每个物理节点创建多个虚拟节点,将它们匀称地分布在哈希 环上。这样一来,每个物理节点在环上的位置会有多个副本,而不是只有一个位置。这样一来,即使哈 希环上的某个地区过于拥挤,也可以通过调整虚拟节点的数目来使得负载更均衡
综合案例
实现 http 自动重定向至 https,并将客户端 https 哀求通过负载均衡的方式反向代理到后端的多台 http 服务器上
- # upstream 配置
- upstream group1{
- server 10.0.0.161;
- server 10.0.0.151;
- }
- # http 重定向到 https
- server{
- listen 80;
- server_name www.a30.com;
- return 302 https://$server_name$request_uri;
- }
- # https 配置
- server{
- listen 443 ssl http2;
- server_name www.a30.com;
- ssl_certificate /usr/share/easy-rsa/pki/www.a30.com.pem;
- ssl_certificate_key /usr/share/easy-rsa/pki/private/www.a30.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 ~]# curl -Lk www.a30.com
- 10.0.0.151 index
- [root@ubuntu ~]# curl -LkI www.a30.com
- HTTP/1.1 302 Moved Temporarily
- Server: nginx
- Date: Sat, 17 Feb 2024 13:55:01 GMT
- Content-Type: text/html
- Content-Length: 138
- Connection: keep-alive
- Location: https://www.a30.com/
- HTTP/2 200
- server: nginx
- date: Sat, 17 Feb 2024 13:55:01 GMT
- content-type: text/html; charset=utf8
- content-length: 17
- last-modified: Wed, 14 Feb 2024 02:45:15 GMT
- etag: "65cc293b-11"
- accept-ranges: bytes
复制代码 Nginx 的四层代理和负载
相干指令和参数
Nginx在1.9.0版本开始支持tcp模式的负载均衡,在1.9.13版本开始支持udp协议的负载,udp主要用于 DNS的域名解析,其配置方式和指令和http 代理雷同,其基于ngx_stream_proxy_module模块实现tcp 负载,别的基于模块ngx_stream_upstream_module实现后端服务器分组转发、权重分配、状态监测、 调度算法等高级功能
如果编译安装,需要指定 –with-stream 选项才能支持 ngx_stream_proxy_module模块
实现TCP协议的反向代理
- #10.0.0.206 Proxy Server 配置,此配置要写在最外层
- stream{
- server{
- listen 3306;
- proxy_pass 10.0.0.161:3306;
- }
-
- server{
- listen 6379;
- proxy_pass 10.0.0.151:6379;
- }
- }
- #10.0.0.161 安装mysql-server,并配置远程用户
- [root@ubuntu ~]# apt update;apt install mysql-server
- mysql> create user proxyer@'10.0.0.%' identified by '123456';
- Query OK, 0 rows affected (0.01 sec)
- mysql> flush privileges;
- Query OK, 0 rows affected (0.00 sec)
- #当前mysql-server 只监听了本机的3306
- [root@ubuntu ~]# ss -tnlp | grep 3306
- #修改配置,注释掉这两行
- [root@ubuntu ~]# vim /etc/mysql/mysql.conf.d/mysqld.cnf
- #bind-address = 127.0.0.1
- #mysqlx-bind-address = 127.0.0.1
- skip-name-resolve #添加此行,跳过主机名反解
- #重启服务
- [root@ubuntu ~]# systemctl restart mysql.service
- [root@ubuntu ~]# ss -tnlp | grep 3306
- #10.0.0.151 安装redis-server
- [root@ubuntu ~]# apt update;apt install redis-server
- #当前只监听了127.1
- [root@ubuntu ~]# ss -tnlp | grep 6379
- #修改配置并重启
- [root@ubuntu ~]# vim /etc/redis/redis.conf
- #bind 127.0.0.1 ::1
- protected-mode no #关闭保护模式
- [root@ubuntu ~]# systemctl restart redis-server.service
- [root@ubuntu ~]# ss -tnlp | grep 6379
- #客户端配置,并测试
- [root@ubuntu ~]# apt update;
- [root@ubuntu ~]# apt install mysql-client-8.0 redis
- #直连测试
- [root@ubuntu ~]# mysql -h 10.0.0.161 -uproxyer -p'123456'
- #redis 测试,客户端直连
- [root@ubuntu ~]# redis-cli -h 10.0.0.151
- #代理测试
- [root@ubuntu ~]# mysql -h 10.0.0.206 -uproxyer -p'123456'
- #redis 测试
- [root@ubuntu ~]# redis-cli -h 10.0.0.206
复制代码 实现TCP协议的负载均衡
- Proxy Server 配置,此配置要写在最外层
- stream{
- upstream mysql{
- server 10.0.0.161:3306;
- server 10.0.0.151:3306;
- }
- upstream redis{
- server 10.0.0.161:6379;
- server 10.0.0.151:6379;
- }
- server{
- listen 3306;
- proxy_pass mysql;
- }
-
- server{
- listen 6379;
- proxy_pass redis;
- }
- }
复制代码 实现 FastCGI 代理
相干指令和参数
- fastcgi_index name; # 后端 FastCGI 服务器默认资源,默认值为空,
- # 作用域 http, server, location
-
- fastcgi_pass address; # 指定后端 FastCGI 服务器地址,可以写 IP:port,也可以指定socket 文件
- # 作用域 location, if in location
-
- fastcgi_param parameter value [if_not_empty];# 设置传递给FastCGI服务器的参数值,可以是文本,变量或组合,可用于将Nginx的内置变量赋值给自定义key
- # 作用域 http, server, location
复制代码 免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |