ToB企服应用市场:ToB评测及商务社交产业平台

标题: Nginx 反向代理 [打印本页]

作者: 悠扬随风    时间: 2024-12-28 17:49
标题: Nginx 反向代理
Nginx 反向代理
代理基础知识

代理分为两种,分别是正向代理和反向代理
正向代理(Forward Proxy) 和 反向代理(Reverse Proxy) 是两种常见的代理服务器,它们用于处理 网络通讯中的不同方向和用途
正向代理(Forward Proxy)
特点

用途

反向代理(Reverse Proxy)
特点

用途

雷同和不同
雷同点

不同点



Nginx 和 LVS

Nginx 和 LVS(Linux Virtual Server) 都是流行的代理和负载均衡办理方案,但它们有一些不同的特点 和应用场景
选择使用 Nginx 照旧 LVS 取决于具体的应用需求和复杂度。Nginx 更适合作为 Web 服务器和应用层负 载均衡器,而 LVS 更适用于传输层负载均衡
雷同点

不同点

LVS 不监听端口,不处理哀求数据,不参与握手流程,只会在内核层转发数据报文
Nginx 需要在应用层接收哀求,根据客户端的哀求参数和Nginx中配置的规则,再重新作为客户端向后 端服务器发起哀求

LVS 通常做四层代理,Nginx 做七层代理
实现 http 协议反向代理

相干指令和参数

Nginx 可以基于ngx_http_proxy_module 模块提供 http 协议的反向代理服务,该模块是 Nginx 的默认模块
  1. proxy_pass URL; # 转发的后端服务器地址,可以写主机名,域名,IP地址,也可以额外指定端口,
  2.         # 作用域 location, if in location, limit_except
  3. proxy_hide_header field; # Nginx 默认不会将后端服务器的 Date,Server,X-Pad,X-Accel-... 这些响应头信息传给   
  4.         # 客户端,除了这些之外的响应头字段会回传,
  5.         # 可以使用 proxy_hide_header 显式指定不回传的响应头字段
  6.         # 作用域 http, server, location
  7. proxy_pass_header field; # 显式指定要回传给客户端的后端服务器响应头中的字段,
  8.         #作用域 http, server, location
  9.        
  10. proxy_pass_request_body on|off; # 是否向后端服务器发送客户端 http 请求的 body 部份,默认 on,
  11.         # 作用域 http, server, location
  12.        
  13. proxy_pass_request_headers on|off; # 是否向后端服务器发送客户端 http 请求的头部信息,默认 on
  14.         # 作用域 http, server, location
  15.        
  16. proxy_connect_timeout time; # Nginx与后端服务器建立连接超时时长,默认60S,超时会向客户端返回504
  17.         # 作用域 http, server, location
  18. proxy_read_timeout time; # Nginx 等待后端服务器返回数据的超时时长,默认60S,超时会向客户端返回504
  19.         # 作用域 http, server, location
  20.        
  21. proxy_send_timeout time; # Nginx 向后端服务器发送请求的超时时长,默认60S,超时会向客户端返回408
  22.         # 作用域 http, server, location
  23.        
  24. proxy_set_body value; # 重新定义传给后端服务器的请求的正文,可以包含文本,变量等,
  25.         # 作用域 http, server, location
  26. proxy_set_header field value; # 更改或添加请求头字段并发送到后端服务器,
  27.         # 作用域http, server, location
  28.        
  29. proxy_http_version 1.0|1.1; # 设置向后端服务器发送请求时的 http 协议版本,默认值1.0,
  30.         # 作用域http, server, location
  31.        
  32. proxy_ignore_client_abort on|off; # 客户端中断连接,Nginx 是否继续执行与后端的连接,默认值 off
  33.         #客户端中断,Nginx 也会中断后端连接, on 表示 客户端中断,nginx 还会继续处理与后端在连接
  34.         # 作用域 http, server, location
  35.        
  36. proxy_headers_hash_bucket_size size; # 当配置了 proxy_hide_header和proxy_set_header的时候,
  37.         # 用于设置nginx保存HTTP报文头的hash表的大小,默认值 64
  38.         # 作用域 http, server, location
  39. proxy_headers_hash_max_size size; # 上一个参数的上限,默认值 512
  40.         # 作用域 http, server, location
  41.        
  42. proxy_next_upstream error|timeout|invalid_header|http_500|http_502|http_503|http_504|http_403|http_404|http_429|non_idempotent| off ...;
  43.         # 当前配置的后端服务器无法提供服务时,因为何种错误而去请求下一个后端服务器
  44.         # 默认值 error timeout, 表示当前后端服务器因为error 和 timeout 错误时,去请求 另一个后端服务器
  45.         # 作用域 http, server, location
  46. proxy_cache zone|off; # 是否启用代理缓存,默认 off,不启用,zone 指缓存名称,
  47.         # 作用域 http, server, location
  48. proxy_cache_path path [levels=levels] [use_temp_path=on|off] keys_zone=name:size
  49. [inactive=time] [max_size=size] [min_free=size] [manager_files=number]
  50. [manager_sleep=time] [manager_threshold=time] [loader_files=number]
  51. [loader_sleep=time] [loader_threshold=time] [purger=on|off]
  52. [purger_files=number] [purger_sleep=time] [purger_threshold=time];
  53.         # 开启代理缓存后指定缓存数据的存放路径,作用域http,默认没有设置
  54.         # path 表示缓存数据存放路径,要保证nginx 有写权限
  55.         # levels 表示缓存数据目录层级,16进制表示,levels=1:2 表示第一级有16个目录,0-f,第一级中每个目录下有16*16个子目录,00-ff
  56.         # keys_zone=name:size zone 表示缓存名称,先定义后使用,size 表示该zone 空间大小
  57.         # inactive 表示缓存数据生命周期,默认值10分钟
  58.         # max_size 表示缓存占用的磁盘空间最大能有多大
  59. proxy_cache_key string; # 指定缓存数据的key,不同的key 对应不同的缓存文件,
  60.         #作用域 http, server, location
  61.         # 默认值 $scheme$proxy_host$request_uri
  62.                                     
  63. proxy_cache_valid [code ...] time;  # 为不同响应状态码的数据设置不同的缓存时长,可设置多条,默认不设置,
  64.         # 作用域 http, server, location
  65. proxy_cache_use_stale error|timeout|invalid_header|updating|http_500|http_502|http_503|http_504|http_403|http_404|http_429|off ...;  
  66.         # 在后端服务器报哪些错误的情况下,直接使用过期缓存数据响应客户端请求默认off,
  67.         #作用域 http, server, location
  68.    
  69. proxy_cache_methods GET|HEAD|POST ...; # 缓存哪些请求类型的数据,默认值 GET HEAD,
  70.         #作用域 http, server, location
复制代码
根本配置

  1. #转发到指定IP
  2. server{
  3. listen 80;
  4. server_name www.a30.com;
  5. #root /var/www/html/www.a30.com;
  6. location /{
  7. proxy_pass http://10.0.0.161; #161要开启WEB服务,请求的是默认default_Serve 配置
  8. }
  9. }
  10. [root@ubuntu ~]# curl http://10.0.0.161
  11. hello world
  12. #被转发到后端161
  13. [root@ubuntu ~]# curl http://www.a30.com
  14. hello world
  15. #转发到指定IP指定端口
  16. server{
  17. listen 80;
  18. server_name www.a30.com;
  19. location /{
  20. proxy_pass http://10.0.0.161:8080;
  21. }
  22. }
  23. #后端主机配置
  24. server {
  25. listen 8080;
  26. root /var/www/html/8080;
  27. }
  28. [root@ubuntu ~]# curl www.a30.com
  29. hello 8080
  30. #转发到指定域名
  31. server{
  32. listen 80;
  33. server_name www.a30.com;
  34. location /{
  35. proxy_pass http://www.node-1.com;
  36. }
  37. }
  38. #后端主机配置
  39. server {
  40. listen 80;
  41. root /var/www/html/www.node-1.com;
  42. server_name www.node-1.com;
  43. }
  44. [root@ubuntu ~]# echo "node-1" > /var/www/html/www.node-1.com/index.html
  45. #测试
  46. [root@ubuntu ~]# curl www.a30.com
  47. node-1
  48. #透传指定参数
  49. #在上述请求中,客户端访问 http://www.a30.com,该主机收到请求后作为客户端去请求http://www.node-1.com
  50. #客户端主机配置
  51. [root@ubuntu ~]# cat /etc/hosts
  52. 10.0.0.206 www.a30.com
  53. #中间主机配置
  54. [root@ubuntu ~]# cat /etc/hosts
  55. 10.0.0.161 www.a30.com
  56. server{
  57. listen 80;
  58. server_name www.a30.com;
  59. location /{
  60. proxy_pass http://10.0.0.161;
  61. proxy_set_header Host $http_host; #将客户端从请求头中传来的 Host 值传给后端服务器
  62. }
  63. }
  64. #后端主机配置
  65. server {
  66. listen 80;
  67. root /var/www/html/www.a30.com;
  68. server_name www.a30.com;
  69. }
  70. [root@ubuntu ~]# echo "a30" > /var/www/html/www.a30.com/index.html
  71. #客户端测试
  72. [root@ubuntu ~]# curl http://www.a30.com
  73. a30
  74. #如果后端服务不可用,从客户端访问会返回502
  75. #停止后端nginx
  76. [root@ubuntu ~]# systemctl stop nginx.service
  77. #客户端访问中间Nginx
  78. [root@ubuntu ~]# curl http://www.a30.com
  79. <html>
  80. <head><title>502 Bad Gateway</title></head>
  81. <body>
  82. <center><h1>502 Bad Gateway</h1></center>
  83. <hr><center>nginx</center>
  84. </body>
  85. </html>
  86. [root@ubuntu ~]# curl http://www.a30.com -I
  87. HTTP/1.1 502 Bad Gateway
  88. Server: nginx
  89. Date: Wed, 18 Sep 2024 11:32:16 GMT
  90. Content-Type: text/html; charset=utf8
  91. Content-Length: 150
  92. Connection: keep-alive
复制代码
实现动静分离

根据条件举行调度,实现动静分离
脚色
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配置
  1. [root@Rocky-9 ~]# cat /etc/hosts
  2. 10.0.0.157 www.a30.com
复制代码
Proxy Server 配置
  1. server{
  2.   listen 80;
  3.   server_name www.a30.com;
  4.   #root /var/www/html/www.a30.com;
  5.   location /static{
  6.         proxy_pass http://10.0.0.151;
  7.         proxy_set_header Host "static.a30.com";
  8. }
  9.   location /api{
  10.         proxy_pass http://10.0.0.161;
  11.         proxy_set_header Host "api.a30.com";
  12. }
复制代码
API Server配置
  1. server{
  2.    listen 80;
  3.    server_name api.a30.com;
  4.    root /apps/nginx/html/api.a30.com/;
  5. }
  6. [root@ubuntu24 sites-enabled]# cat /apps/nginx/html/api.a30.com/api/index.html
  7. api.a30.com
复制代码
Static Server配置
  1. server{
  2.    listen 80;
  3.    server_name static.a30.com;
  4.    root /var/www/html/static.a30.com/;
  5. }
  6. [root@ubuntu22:sites-enabled]# cat /var/www/html/static.a30.com/static/index.html
  7. static.a30.com
复制代码
Client测试
  1. [root@Rocky-9 ~]# curl http://www.a30.com/api/index.html
  2. api.a30.com
  3. [root@Rocky-9 ~]# curl http://www.a30.com/static/index.html
  4. static.a30.com
复制代码
proxy_pass 后面加斜线和不加斜线的区别
  1. #没有斜线是追加
  2. # http://www.a30.com/api/index.html ----> http://api.a30.com/api/index.html
  3. location /api{
  4.         proxy_pass http://10.0.0.161;
  5.         proxy_set_header Host "api.a30.com";
  6. }
  7. #有斜线是替换
  8. # http://www.a30.com/api/index.html -----> http://api.a30.com/index.html
  9. location /api{
  10.         proxy_pass http://10.0.0.161;
  11.         proxy_set_header Host "api.a30.com";
  12. }
复制代码
实现对特定资源的代理
  1. location ~ \.(jpe?g|png|bmp|gif)$ {
  2.    proxy_pass http://10.0.0.161;
  3.    proxy_set_header Host "api.a30.com";
  4. }
复制代码
代理服务器实现数据缓存

前置条件:各服务器时间和时区先统一,方便测试
  1. #Proxy Server 配置
  2. #定义缓存
  3. proxy_cache_path /tmp/proxycache levels=1:2 keys_zone=proxycache:20m inactive=60s max_size=1g;
  4. server{
  5. listen 80;
  6. server_name www.a30.com;
  7. location /static{
  8. proxy_pass http://10.0.0.157/;
  9. proxy_set_header Host "static.a30.com";
  10. proxy_cache proxycache;                 #使用缓存
  11. proxy_cache_key $request_uri;
  12. proxy_cache_valid 200 302 301 90s;
  13. proxy_cache_valid any 2m;                 #此处一定要写,否则缓存不生效
  14. }
  15. }
  16. #重载,生成缓存目录
  17. [root@ubuntu ~]# nginx -s reload
  18. [root@ubuntu ~]# ll /tmp/proxycache/
  19. total 8
  20. drwx------  2 www-data root 4096 Feb 12 23:09 ./
  21. drwxrwxrwt 14 root     root 4096 Feb 12 23:09 ../
  22. #Static Server 配置
  23. server {
  24.                 listen 80;
  25.                 root /var/www/html/static.a30.com;
  26.                 server_name static.a30.com;
  27. }
  28. [root@ubuntu24 sites-enabled]# ls -lh /var/www/html/static.a30.com/
  29. total 8.0K
  30. -rw-r--r-- 1 root root 657 Sep 19 09:55 fstab
  31. -rw-r--r-- 1 root root  18 Sep 19 09:55 index.html
  32. #客户端测试
  33. [root@Rocky-9 ~]# curl http://www.a30.com/static/fstab
  34. #查看 Proxy Server 上的缓存数据,文件名就是key 的 hash 值
  35. [root@ubuntu22:sites-enabled]# tree /tmp/proxycache/
  36. /tmp/proxycache/
  37. └── 3
  38.     └── ab
  39.         └── 2d291e4d45687e428f0215bec190aab3
  40. 2 directories, 1 file
  41. #并不是一个文本文件
  42. [root@ubuntu22:sites-enabled]# file /tmp/proxycache/3/ab/2d291e4d45687e428f0215bec190aab3
  43. /tmp/proxycache/3/ab/2d291e4d45687e428f0215bec190aab3: data
  44. #查看当前时间和缓存文件时间
  45. [root@ubuntu22:sites-enabled]# date
  46. Thu Sep 19 10:03:38 AM CST 2024
  47. [root@ubuntu22:sites-enabled]# stat /tmp/proxycache/3/ab/2d291e4d45687e428f0215bec190aab3
  48.   File: /tmp/proxycache/3/ab/2d291e4d45687e428f0215bec190aab3
  49.   Size: 1254              Blocks: 8          IO Block: 4096   regular file
  50. Device: fd00h/64768d        Inode: 4194322     Links: 1
  51. Access: (0600/-rw-------)  Uid: (   33/www-data)   Gid: (   33/www-data)
  52. Access: 2024-09-19 10:03:16.497567601 +0800
  53. Modify: 2024-09-19 10:02:55.416164600 +0800
  54. Change: 2024-09-19 10:02:55.416164600 +0800
  55. Birth: 2024-09-19 10:02:55.416164600 +0800
  56. #除了文件内容外,还有头部信息
  57. [root@ubuntu22:sites-enabled]# cat /tmp/proxycache/3/ab/2d291e4d45687e428f0215bec190aab3
  58. ?ꦘꧥꤪeudU"66eb8498-291"
  59. KEY: /static/fstab
  60. HTTP/1.1 200 OK
  61. Server: nginx
  62. Date: Thu, 19 Sep 2024 02:05:25 GMT
  63. Content-Type: application/octet-stream
  64. Content-Length: 657
  65. Last-Modified: Thu, 19 Sep 2024 01:55:36 GMT
  66. Connection: close
  67. ETag: "66eb8498-291"
  68. Accept-Ranges: bytes
  69. # /etc/fstab: static file system information.
  70. #
  71. # Use 'blkid' to print the universally unique identifier for a
  72. # device; this may be used with UUID= as a more robust way to name devices
  73. # that works even if disks are added and removed. See fstab(5).
  74. #
  75. # <file system> <mount point>   <type>  <options>       <dump>  <pass>
  76. # / was on /dev/ubuntu-vg/ubuntu-lv during curtin installation
  77. /dev/disk/by-id/dm-uuid-LVM-H5gHRIOORHBs4Od7xVmGBfQE2ZJSd1kxqhie9niuE1re5q1XVMJmVvoQ7stlUKe2 / ext4 defaults 0 1
  78. # /boot was on /dev/sda2 during curtin installation
  79. /dev/disk/by-uuid/8a0cc0fa-cc21-4fe4-ab25-4a43540d9f02 /boot ext4 defaults 0 1
  80. /swap.img        none        swap        sw        0        0
  81. #生命周期结束后文件被删除
  82. #但是在缓存有效期内,后端服务器内容发生了更新,客户端获取的还是缓存数据
  83. #后端真实数据删除,客户端还能拿到缓存数据
复制代码
实现客户端IP地址透传

在使用Nginx 做代理的情况下,默认后端服务器无法获取客户端真实IP地址
脚色
IP
Client
10.0.0.158
Proxy Server
10.0.0.157
Real Server
10.0.0.151
默认情况下,后端服务器无法获取真实客户端IP
Proxy Server 配置
  1. server{
  2.   listen 80;
  3.   server_name www.a30.com;
  4.   location / {
  5.         proxy_pass http://10.0.0.151;
  6. }
复制代码
Real Server 配置
  1. server {
  2.        listen 80 default_server;
  3.        listen [::]:80 default_server;
  4.        root /var/www/html;
  5.        index index.html index.htm index.nginx-debian.html;
  6.        server_name _;
  7.        location / {
  8.                return 200 ${remote_addr}---${http_x_real_ip}---${http_x_forwarded_for};
  9.        }
  10. }
复制代码
Client测试
  1. [root@Rocky-9 ~]# curl www.a30.com
  2. 10.0.0.157------
  3. #后端服务器只能获取代理服务器IP
复制代码
修改代理服务器配置,透传真实客户端IP
  1. server{
  2.   listen 80;
  3.   server_name www.a30.com;
  4.   location / {
  5.         proxy_pass http://10.0.0.151;
  6.         proxy_set_header X-Real-IP $remote_addr;
  7.     proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  8. }
  9. #表示将客户端IP追加请求报文中X-Forwarded-For首部字段,多个IP之间用逗号分隔,如果请求中没有X-Forwarded-For,就使用$remote_addr
  10. proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  11. #客户端测试 $remote_addr 获取代理IP,$http_x_real_ip 获取真实客户端IP,
  12. $http_x_forwarded_for 获取真实客户端IP
  13. #客户端测试
  14. [root@Rocky-9 ~]# curl www.a30.com
  15. 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
  1. #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 {
  2.        listen 80 default_server;
  3.        listen [::]:80 default_server;
  4.        root /var/www/html;
  5.        index index.html index.htm index.nginx-debian.html;
  6.        server_name _;
  7.        location / {
  8.                return 200 ${remote_addr}---${http_x_real_ip}---${http_x_forwarded_for};
  9.        }
  10. }
  11. #客户端测试,Real Server 只能通过 $remote_addr 获取上一级代理的IP[root@Rocky-9 ~]# curl www.a30.com10.0.0.157------
复制代码
修改第一级代理服务器配置
  1. server{
  2.        listen 80;
  3.        server_name www.a30.com;
  4.        location /{
  5.                proxy_pass http://10.0.0.157;
  6.                           proxy_set_header X-Real-IP $remote_addr;
  7.                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  8.        }
  9. }
  10. #客户端测试 $remote_addr 获取上一级代理IP,$http_x_real_ip 获取真实客户端IP,$http_x_forwarded_for 获取真实客户端IP
  11. [root@Rocky-9 ~]# curl www.a30.com
  12. 10.0.0.157---10.0.0.158---10.0.0.158
复制代码
继续修改第二级代理服务器配置
  1. server {
  2.        listen 80 default_server;
  3.        listen [::]:80 default_server;
  4.        root /var/www/html;
  5.        index index.html index.htm index.nginx-debian.html;
  6.        server_name _;
  7.        location / {
  8.                proxy_pass http://10.0.0.151;
  9.                proxy_set_header X-Real-IP $remote_addr;
  10.                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  11.        }
  12. }
  13. #客户端测试
  14. # $remote_addr 获取上一级代理IP
  15. # $http_x_real_ip 获取上上一级代理IP
  16. # $http_x_forwarded_for 累加了第一级代理的 X-Forwarded-For 和第二级代理的 X-Forwarded-For
  17. [root@Rocky-9 ~]# curl www.a30.com
  18. 10.0.0.157---10.0.0.161---10.0.0.158, 10.0.0.161
复制代码
第一级代理不透传,不添加哀求头字
  1. server{
  2.        listen 80;
  3.        server_name www.a30.com;
  4.        location /{
  5.                proxy_pass http://10.0.0.157;
  6.                #proxy_set_header X-Real-IP $remote_addr;
  7.                #proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  8.        }
  9. }
  10. [root@Rocky-9 ~]# curl www.a30.com
  11. 10.0.0.157---10.0.0.161---10.0.0.161
复制代码
实现 http 协议反向代理的负载均衡

相干指令和参数

在实现 Nginx 反向代理的基础上,可以基于 ngx_http_upstream_module 模块实现后端服务器的分 组,权重分配,状态监测,调度算法等高级功能
  1. upstream name { server address [parameters]; } # 定义一个后端服务器组,可以包含一台或多台服务器,
  2. # 定义好后在 proxy_pass 指令中引用,作用域 http
  3. server address [parameters]; # 在 upstream 中定义一个具体的后端服务器,作用域upstream
  4. # address 指定后端服务器 可以是IP地址,主机名,或UNIX Socket,可以加端口号
  5. # parameters 是可选掺数,具体有以下几个属性
  6. # weight=number 指定该 server 的权重,默认值都是1
  7. # max_conns=number 该 Server 的最大活动连接数,达到后将不再给该 Server 发送请求,默认值0,表示不限制
  8. # max_fails=number 后端服务器的下线条件,当客户端访问时,对本次调度选中的后端服务器连续进行检测多少次,如果都失败就标记为不可用,默认为1次,当客户端访问时,才会利用TCP触发对探测后端服务器健康性检查,而非周期性的探测
  9. # fail_timeout=time 后端服务器的上线条件,对已经检测到处于不可用的后端服务器,每隔此时间间隔再次进行检测是否恢复可用,如果发现可用,则将后端服务器参与调度,默认为10秒
  10. # backup 标记该 Server 为备用,当所有后端服务器不可用时,才使用此服务器
  11. # down 标记该 Server 临时不可用,可用于平滑下线后端服务器,新请求不再调度到此服务器,原有连接不受影响
  12. hash key [consistent]; # 使用自行指定的 Key 做 hash 运算后进行调度,Key 可以是变量,比如请求头中的字段,URI等,如果对应的 server 条目配置发生了变化,会导致相同的 key 被重新hash
  13. # consistent 表示使用一致性 hash,此参数确保该upstream 中的 server 条目发生变化时,尽可能少的重新 hash,适用于做缓存服务的场景,提高缓存命中率
  14. # 作用域 upstream
  15. ip_hash; # 源地址hash调度方法,基于的客户端的remote_addr(源地址IPv4的前24位或整个IPv6地址)做hash计算,以实现会话保持,作用域 upstream
  16. least_conn; # 最少连接调度算法,优先将客户端请求调度到当前连接最少的后端服务器,相当于LVS中的 LC 算法
  17. # 配合权重,能实现类似于 LVS 中的 WLC 算法
  18. # 作用域 upstream
  19. keepalive connections; # 为每个 worker 进程保留最多多少个空闲保活连接数,超过此值,最近最少使用的连接将被关闭
  20. # 默认不设置,作用域 upstream
  21. keepalive_time time; # 空闲连接保持的时长,超过该时间,一直没使用的空闲连接将被销毁
  22. # 默认值 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
  1. # Proxy Server 配置
  2. upstream group1{
  3.         server 10.0.0.161;
  4.         server 10.0.0.151;
  5. }
  6. server{
  7.   listen 80;
  8.   server_name www.a30.com;
  9.   #root /var/www/html/www.a30.com;
  10.   keepalive_timeout 15 30;
  11.   autoindex on;
  12.   location /{
  13.         proxy_pass http://group1;
  14.         proxy_set_header host $http_host;
  15. }
  16. # Real Server-1 配置
  17. server {
  18.        listen 80;
  19.        root /var/www/html/www.a30.com;
  20.        server_name www.a30.com;
  21. }
  22. [root@ubuntu24 www.a30.com]# cat /apps/nginx/html/www.a30.com/index.html
  23. 10.0.0.161
  24. # Real Server-2 配置
  25. server {
  26.            listen 80;
  27.        root /var/www/html/www.a30.com;
  28.        server_name www.a30.com;
  29. }
  30. [root@ubuntu22:sites-enabled]# cat /var/www/html/www.a30.com/index.html
  31. www.a30.com
  32. 10.0.0.151
  33. #客户端测试-轮循调度到后端服务器
  34. [root@Rocky-9 ~]# curl www.a30.com
  35. www.a30.com
  36. 10.0.0.151
  37. [root@Rocky-9 ~]# curl www.a30.com
  38. 10.0.0.161
  39. [root@Rocky-9 ~]# curl www.a30.com
  40. www.a30.com
  41. 10.0.0.151
  42. [root@Rocky-9 ~]# curl www.a30.com
  43. 10.0.0.161
复制代码
设置权重
  1. #每个 server 配置的默认权重是1,这种写法,两个 server 被调度的比例为 3:1
  2. upstream group1{
  3.         server 10.0.0.161 weight=3;
  4.         server 10.0.0.151;
  5. }
  6. [root@Rocky-9 ~]# curl www.a30.com
  7. www.a30.com
  8. 10.0.0.151
  9. [root@Rocky-9 ~]# curl www.a30.com
  10. 10.0.0.161
  11. [root@Rocky-9 ~]# curl www.a30.com
  12. 10.0.0.161
  13. [root@Rocky-9 ~]# curl www.a30.com
  14. 10.0.0.161
  15. [root@Rocky-9 ~]# curl www.a30.com
  16. www.a30.com
  17. 10.0.0.151
复制代码
限定最大活动连接数
  1. #10.0.0.161 同时只能维持两个活动连接
  2. upstream group1{
  3.        server 10.0.0.161 max_conns=2;
  4.        server 10.0.0.151;
  5. }
  6. #后端服务器配置
  7. server {
  8. listen 80;
  9. root /var/www/html/www.a30.com;
  10. server_name www.a30.com;
  11. limit_rate 10k;
  12. }
  13. #客户端测试,开6个窗口下载文件
  14. [root@ubuntu ~]# wget http://www.a30.com/test.img
  15. #查看 10.0.0.161 上的连接,2个活动连接
  16. [root@ubuntu ~]# ss -tnpe | grep 80
  17. #查看 10.0.0.151 上的连接,4个活动连接
  18. #客户端继续测试,新的请求都不会调度给 10.0.0.161
复制代码
后端服务器健康性查抄
Nginx 的 upstream 指令对于后端服务器的健康性查抄是被动查抄,当有客户端哀求被调度到该服务器 上时,会在TCP协议层的三次握手时查抄该服务器是否可用,如果不可用就调度到别的服务器,当不可 用的次数达到指定次数时(默认是1次,由 Server 配置中的 max_fails 选项决定),在规定时间内(默 认是10S,由 Server 配置中的 fail_timeout 选项决定),不会再向该服务器调度哀求,直到超过规定时 间后再次向该服务器调度哀求,如果再次调度该服务器照旧不可用,则继续期待一个时间段,如果再次 调度该服务器可用,则恢复该服务器到调度列表中
  1. upstream group1{
  2.        server 10.0.0.161;
  3.        server 10.0.0.151;
  4. }
  5. server{
  6.        listen 80;
  7.        server_name www.a30.com;
  8.        location /{
  9.                proxy_pass http://group1;
  10.                proxy_set_header host $http_host;
  11.        }
  12. }
  13. #停止 10.0.0.161 上的Nginx 服务
  14. [root@ubuntu ~]# systemctl stop nginx.service
  15. #客户端测试,检测到 10.0.0.161不可用,将请求都调度到 10.0.0.151
  16. [root@ubuntu ~]# curl www.a30.com
  17. 10.0.0.151 index
  18. [root@ubuntu ~]# curl www.a30.com
  19. 10.0.0.151 index
  20. [root@ubuntu ~]# curl www.a30.com
  21. 10.0.0.151 index
  22. #启用 10.0.0.161 上的Nginx 服务,客户端需要在距离上次检测该服务器不可用10S后才能调度到该服务器
  23. [root@ubuntu ~]# systemctl stop nginx.service
  24. #如果后端服务器上的资源不存在,则不会影响调度,会返回对应的状态码和状态页
  25. [root@ubuntu ~]# mv /var/www/html/www.a30.com/index.html{,bak}
  26. #客户端测试
  27. [root@ubuntu ~]# curl www.a30.com/index.html
  28. 10.0.0.151 index
  29. [root@ubuntu ~]# curl www.a30.com/index.html
  30. <html>
  31. <head><title>404 Not Found</title></head>
复制代码
设置备用服务器
  1. #设置 backup,当 10.0.0.161 和 10.0.0.151 都不可用时,请求会被调度到 10.0.0.213
  2. upstream group1{
  3. server 10.0.0.161;
  4. server 10.0.0.151;
  5. server 10.0.0.213 backup;
  6. }
  7. server{
  8. listen 80;
  9. server_name www.a30.com;
  10. location /{
  11. proxy_pass http://group1;
  12. proxy_set_header host $http_host;
  13. }
  14. }
  15. #当前151 和 161 可用,客户端测试
  16. [root@ubuntu ~]# curl www.a30.com
  17. 10.0.0.161 index
  18. [root@ubuntu ~]# curl www.a30.com
  19. 10.0.0.151 index
  20. [root@ubuntu ~]# curl www.a30.com
  21. 10.0.0.161 index
  22. #停止151和161的 Nginx 服务后再次测试
  23. [root@ubuntu ~]# curl www.a30.com
  24. 10.0.0.213
复制代码
设置后端服务器平滑下线
  1. #Proxy Server 配置
  2. upstream group1{
  3.                 server 10.0.0.161;
  4.         server 10.0.0.151;
  5. }
  6. server{
  7.        listen 80;
  8.        server_name www.a30.com;
  9.        location /{
  10.                proxy_pass http://group1;
  11.                proxy_set_header host $http_host;
  12.        }
  13. }
  14. #后端服务器配置
  15. server {
  16.        listen 80;
  17.        root /var/www/html/www.a30.com;
  18.        server_name www.a30.com;
  19.        limit_rate 10k;
  20. }
  21. #客户端测试 - 开启两个窗口下载文件
  22. [root@ubuntu ~]# wget http://www.a30.com/test.img
  23. #在10.0.0.161 上查看,有一个连接
  24. [root@ubuntu ~]# ss -tnep | grep 80
  25. #在10.0.0.151 上查看,也有一个连接
  26. [root@ubuntu ~]# ss -tnep | grep 80
  27. #修改Proxy Server 配置,将 10.0.0.161 下线
  28. upstream group1{
  29.        server 10.0.0.161 down;
  30.        server 10.0.0.151;
  31. }
  32. #重载生效
  33. [root@ubuntu ~]# nginx -s reload
  34. #你会发现原来保持的下载连接没有中断,但新的请求,不会再被调度到 10.0.0.161
  35. [root@ubuntu ~]# curl www.a30.com
  36. 10.0.0.151 index
  37. [root@ubuntu ~]# curl www.a30.com
  38. 10.0.0.151 index
复制代码
负载均衡调度算法

源IP地址hash
ip_hash 算法只使用 IPV4 的前 24 位做 hash 运算,如果客户端IP前24位同等,则会被调度到同一台后 端服务器
  1. #Proxy Server 配置
  2. upstream group1{
  3. ip_hash;
  4. server 10.0.0.161;
  5. server 10.0.0.151;
  6. }
  7. server{
  8. listen 80;
  9. server_name www.a30.com;
  10. location /{
  11. proxy_pass http://group1;
  12. proxy_set_header host $http_host;
  13. }
  14. }
  15. #10.0.0.208 - 客户端测试,被调度到 10.0.0.151
  16. [root@ubuntu ~]# curl www.a30.com
  17. 10.0.0.151 index
  18. [root@ubuntu ~]# curl www.a30.com
  19. 10.0.0.151 index
  20. [root@ubuntu ~]# curl www.a30.com
  21. 10.0.0.151 index
  22. #10.0.0.213 - 客户端测试,被调度到 10.0.0.151
  23. [root@rocky ~]# curl www.a30.com
  24. 10.0.0.151 index
  25. [root@rocky ~]# curl www.a30.com
  26. 10.0.0.151 index
  27. [root@rocky ~]# curl www.a30.com
  28. 10.0.0.151 index
复制代码
使用自行指定的 key 做 hash 调度
  1. #Proxy Server 配置
  2. #三台 server 权重一样,调度算法 hash($remoute_addr)%3,值为 0,1,2根据不同的值调度到不同server
  3. upstream group1{
  4. hash $remote_addr;
  5. server 10.0.0.161;
  6. server 10.0.0.151;
  7. server 10.0.0.213;
  8. }
  9. server{
  10.         listen 80;
  11.         server_name www.a30.com;
  12.         location /{
  13.         proxy_pass http://group1;
  14.         proxy_set_header host $http_host;
  15. }
  16. }
  17. #10.0.0.208 - 客户端测试,被调度到 10.0.0.151
  18. [root@ubuntu ~]# curl www.a30.com
  19. 10.0.0.151 index
  20. [root@ubuntu ~]# curl www.a30.com
  21. 10.0.0.151 index
  22. [root@ubuntu ~]# curl www.a30.com
  23. 10.0.0.151 index
  24. #10.0.0.207 - 客户端测试,被调度到 10.0.0.213
  25. [root@rocky ~]# curl www.a30.com
  26. 10.0.0.213 index
  27. [root@rocky ~]# curl www.a30.com
  28. 10.0.0.213 index
  29. [root@rocky ~]# curl www.a30.com
  30. 10.0.0.213 index
  31. #三台 server 权重不一样,调度算法 hash($remoute_addr)%(1+2+3),值为 0,1,2,3,4,5
  32. #0 调度到 161
  33. #1,2调度到 151
  34. #3,4,5调度到 213
  35. upstream group1{
  36. hash $remote_addr;
  37. server 10.0.0.161 weight=1;
  38. server 10.0.0.151 weight=2;
  39. server 10.0.0.213 weight=3;
  40. }
  41. #Proxy Server 配置
  42. #根据 request_uri 进行调度,不同客户端访问同一个资源会被调度到同一台后端服务器上
  43. upstream group1{
  44.         hash $request_uri;
  45.         server 10.0.0.161;
  46.         server 10.0.0.151;
  47.         server 10.0.0.213;
  48. }
  49. server{
  50. listen 80;
  51. server_name www.a30.com;
  52. location /{
  53. proxy_pass http://group1;
  54. proxy_set_header host $http_host;
  55. }
  56. }
  57. #10.0.0.208 - 客户端测试
  58. [root@ubuntu ~]# curl www.a30.com/index.html
  59. 10.0.0.213 index
  60. [root@ubuntu ~]# curl www.a30.com/index.html
  61. 10.0.0.213 index
  62. [root@ubuntu ~]# curl www.a30.com/index.html
  63. 10.0.0.213 index
  64. [root@ubuntu ~]# curl www.a30.com/a.html
  65. 10.0.0.161 aaa
  66. [root@ubuntu ~]# curl www.a30.com/a.html
  67. 10.0.0.161 aaa
  68. [root@ubuntu ~]# curl www.a30.com/a.html
  69. 10.0.0.161 aaa
  70. #10.0.0.207 - 客户端测试
  71. [root@rocky ~]# curl www.a30.com
  72. 10.0.0.213 index
  73. [root@rocky ~]# curl www.a30.com
  74. 10.0.0.213 index
  75. [root@rocky ~]# curl www.a30.com
  76. 10.0.0.213 index
  77. [root@rocky ~]# curl www.a30.com/a.html
  78. 10.0.0.161 aaa
  79. [root@rocky ~]# curl www.a30.com/a.html
  80. 10.0.0.161 aaa
复制代码
最少连接调度算法
  1. #Proxy Server 配置,最少连接调度算法
  2. upstream group1{
  3.        least_conn;
  4.        server 10.0.0.161;
  5.        server 10.0.0.151;
  6. }
  7. server{
  8.        listen 80;
  9.        server_name www.a30.com;
  10.        location /{
  11.                proxy_pass http://group1;
  12.                proxy_set_header host $http_host;
  13.        }
  14. }
  15. #客户端开启一个下载连接,限速,让该连接一直保持
  16. [root@ubuntu ~]# wget www.a30.com/test.img
  17. #下载请求被调度到 10.0.0.161上了
  18. [root@ubuntu ~]# ss -tnep | grep 80
  19. #新开客户端测试,请求不会被调度到 10.0.0.161 上
  20. [root@rocky ~]# curl www.a30.com
  21. 10.0.0.151 index
  22. [root@rocky ~]# curl www.a30.com
  23. 10.0.0.151 index
  24. [root@rocky ~]# curl www.a30.com
  25. 10.0.0.151 index
复制代码
同等性 hash

  1. #Proxy Server 配置
  2. #三台 server 权重一样,调度算法 hash($remoute_addr)%3,值为 0,1,2 根据不同的值调度到不
  3. 同 server
  4. upstream group1{
  5.         hash $remote_addr;
  6.         server 10.0.0.161;
  7.         server 10.0.0.151;
  8.         server 10.0.0.213;
  9. }
  10. server{
  11.         listen 80;
  12.         server_name www.a30.com;
  13.         location /{
  14.         proxy_pass http://group1;
  15.         proxy_set_header host $http_host;
  16. }
  17. }
复制代码
在上述配置中,三台后端服务器的权重都为 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 服务器上

  1. # upstream 配置
  2. upstream group1{
  3. server 10.0.0.161;
  4. server 10.0.0.151;
  5. }
  6. # http 重定向到 https
  7. server{
  8. listen 80;
  9. server_name www.a30.com;
  10. return 302 https://$server_name$request_uri;
  11. }
  12. # https 配置
  13. server{
  14. listen 443 ssl http2;
  15. server_name www.a30.com;
  16. ssl_certificate /usr/share/easy-rsa/pki/www.a30.com.pem;
  17. ssl_certificate_key /usr/share/easy-rsa/pki/private/www.a30.com.key;
  18. ssl_session_cache shared:sslcache:20m;
  19. ssl_session_timeout 10m;
  20. location /{
  21. proxy_pass http://group1;
  22. proxy_set_header host $http_host;
  23. }
  24. }
  25. #客户端测试
  26. [root@ubuntu ~]# curl -Lk www.a30.com
  27. 10.0.0.151 index
  28. [root@ubuntu ~]# curl -LkI www.a30.com
  29. HTTP/1.1 302 Moved Temporarily
  30. Server: nginx
  31. Date: Sat, 17 Feb 2024 13:55:01 GMT
  32. Content-Type: text/html
  33. Content-Length: 138
  34. Connection: keep-alive
  35. Location: https://www.a30.com/
  36. HTTP/2 200
  37. server: nginx
  38. date: Sat, 17 Feb 2024 13:55:01 GMT
  39. content-type: text/html; charset=utf8
  40. content-length: 17
  41. last-modified: Wed, 14 Feb 2024 02:45:15 GMT
  42. etag: "65cc293b-11"
  43. 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协议的反向代理

  1. #10.0.0.206 Proxy Server 配置,此配置要写在最外层
  2. stream{
  3. server{
  4.         listen 3306;
  5.         proxy_pass 10.0.0.161:3306;
  6. }
  7. server{
  8.         listen 6379;
  9.         proxy_pass 10.0.0.151:6379;
  10. }
  11. }
  12. #10.0.0.161 安装mysql-server,并配置远程用户
  13. [root@ubuntu ~]# apt update;apt install mysql-server
  14. mysql> create user proxyer@'10.0.0.%' identified by '123456';
  15. Query OK, 0 rows affected (0.01 sec)
  16. mysql> flush privileges;
  17. Query OK, 0 rows affected (0.00 sec)
  18. #当前mysql-server 只监听了本机的3306
  19. [root@ubuntu ~]# ss -tnlp | grep 3306
  20. #修改配置,注释掉这两行
  21. [root@ubuntu ~]# vim /etc/mysql/mysql.conf.d/mysqld.cnf
  22. #bind-address           = 127.0.0.1
  23. #mysqlx-bind-address   = 127.0.0.1
  24. skip-name-resolve #添加此行,跳过主机名反解
  25. #重启服务
  26. [root@ubuntu ~]# systemctl restart mysql.service
  27. [root@ubuntu ~]# ss -tnlp | grep 3306
  28. #10.0.0.151 安装redis-server
  29. [root@ubuntu ~]# apt update;apt install redis-server
  30. #当前只监听了127.1
  31. [root@ubuntu ~]# ss -tnlp | grep 6379
  32. #修改配置并重启
  33. [root@ubuntu ~]# vim /etc/redis/redis.conf
  34. #bind 127.0.0.1 ::1
  35. protected-mode no #关闭保护模式
  36. [root@ubuntu ~]# systemctl restart redis-server.service
  37. [root@ubuntu ~]# ss -tnlp | grep 6379
  38. #客户端配置,并测试
  39. [root@ubuntu ~]# apt update;
  40. [root@ubuntu ~]# apt install mysql-client-8.0 redis
  41. #直连测试
  42. [root@ubuntu ~]# mysql -h 10.0.0.161 -uproxyer -p'123456'
  43. #redis 测试,客户端直连
  44. [root@ubuntu ~]# redis-cli -h 10.0.0.151
  45. #代理测试
  46. [root@ubuntu ~]# mysql -h 10.0.0.206 -uproxyer -p'123456'
  47. #redis 测试
  48. [root@ubuntu ~]# redis-cli -h 10.0.0.206
复制代码
实现TCP协议的负载均衡

  1. Proxy Server 配置,此配置要写在最外层
  2. stream{
  3. upstream mysql{
  4. server 10.0.0.161:3306;
  5. server 10.0.0.151:3306;
  6. }
  7. upstream redis{
  8. server 10.0.0.161:6379;
  9. server 10.0.0.151:6379;
  10. }
  11. server{
  12. listen 3306;
  13. proxy_pass mysql;
  14. }
  15. server{
  16. listen 6379;
  17. proxy_pass redis;
  18. }
  19. }
复制代码
实现 FastCGI 代理

相干指令和参数

  1. fastcgi_index name; # 后端 FastCGI 服务器默认资源,默认值为空,
  2.         # 作用域 http, server, location
  3.        
  4. fastcgi_pass address; # 指定后端 FastCGI 服务器地址,可以写 IP:port,也可以指定socket 文件
  5.         # 作用域 location, if in location
  6.        
  7. fastcgi_param parameter value [if_not_empty];# 设置传递给FastCGI服务器的参数值,可以是文本,变量或组合,可用于将Nginx的内置变量赋值给自定义key
  8.         # 作用域 http, server, location
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4