Nginx+Tomcat的负载均衡&动静分离 详细解读,附具体实验

Nginx的upstream负载方式

upstream负载

  • 指的是nginx如何将HTTP请求分配给一组服务器的方法。nginx支持多种负载方式。
  • upstream是nginx之中的一个模块。
    • upstream adj. adv. 在(向)上游的,逆流的

轮询(默认)

常规

  • 每个请求按时间顺序逐一分配到不同的后端服务器,若有服务器宕机,故障系统自动剔除。

加权轮询

  • 在常规的基础之上可以对服务器进行加权(weight)
  • weight越大,分配概率越大。适用于服务器性能不一样的情况下。

优缺点

  • 优点
    • 简单易用,适合处理长连接或者耗时请求场景
  • 缺点
    • 无法保证会话持久性,可以会导致客户端访问不同服务器而出现不可预知的问题。

IP哈希

根据客户端的IP地址确定请求的服务器,保证同一个IP总是访问同一个服务器,解决了动态网页存在的session共享问题

  • 优点
    • 保证会话持久,适合需要记录客户端状态或信息的场景
  • 缺点
    • 无法平衡服务器的负载,不支持 TCP/UDP 协议

IP 哈希配置

vim /usr/local/nginx/conf/nginx.conf
  • 配置在需要设置的server 块
upstream tomcat {     
        ip_hash;         
        server 192.168.45.11:8080 weight=1 max_fails=1 fail_timeout=10s;
        server 192.168.45.12:8080 weight=2 max_fails=1 fail_timeout=10s;
    }

Nginx的Session和Cookie

  • Nginx的Session是一个独特的机制,它允许应用程序在用户会话之间存储和检索信息不需要借助其他数据存储机制。
  • Cookie是一种在用户的本地计算机上存储的文本文件,由Web服务器发送给用户的浏览器,以便用户能够在访问同一站点时保持状态信息。
  • Nginx中,Session和Cookie可以结合起来使用,以维护用户的会话,如用户认证和访问控制等功能。
    • 但是,Session通常仅用于检索和存储用户特定的信息,而Cookie则提供了一种更加有效的方式来跟踪用户的会话,并在用户访问相同站点时自动将其带回服务器。

哈希

  • 根据自定义的键值(如URL、Cookie等)计算哈希值,然后根据哈希值选择服务器。
  • nginx本身不支持,需要安装 nginx_upstream_hash软件包
  • 优点
    • 可以自定义键值负载均衡
  • 缺点
    • 需要配置额外的参数,也可能出现负载不均衡的情况

最短时间

最短时间(仅NGINX Plus):请求发送给响应时间最短且活跃连接数最少的服务器。

fair负载均衡

  • Nginx的fair负载均衡模块增强了Nginx提供的标准轮换负载均衡器,以便它能够跟踪繁忙的后端服务器(例如Thin,Ebb,Mongrel),并将负载平衡到非繁忙的服务器进程。
  • 简单来说,fair采用的不是内建负载均衡使用的轮换的均衡算法,而是可以根据页面大小、加载时间长短智能地进行负载均衡

Tomcat+Nginx搭建

拓扑环境

主机 IP 服务 版本
YY 192.168.45.10 nginx 1.22.0
YY1 192.168.45.11 tomcat 8.5.82
YY2 192.168.45.12 tomcat 8.5.82

基本服务搭建

完成服务器服务搭建,这里不做讲述,如有需要后续进行超链接,单独出一篇部署的详细说明。

Nginx 负载均衡设置

配置具体参数

  • 路径
vim /usr/local/nginx/conf/nginx.conf
  • 格式示例:
    • 位置:http 模块定义后端集群
  • 参数说明
    • Down:表示当前的 server 暂时不参与负载;
    • Weight:默认为 1,weight 越大,负载的权重就越大;
    • Max_fails:允许请求失败的次数默认为 1,当超过最大次数 proxy_next_upstream 模块定义的错误;
    • Fail_timeout:max_fails:请求失败后,暂停的时间;
    • Backup:其它所有的非 backup 机器 down 或者忙的时候,才会请求 backup 机器,所以这台机器压力会最轻。
    • 注意192.168.45.10:9090192.168.45.13:7070 示范使用
    upstream tomcat { 
        server 192.168.45.10:9090 down; 
        server 192.168.45.11:8080 weight=1 max_fails=1 fail_timeout=10s; 
        server 192.168.45.12:8080 weight=1 max_fails=1 fail_timeout=10s; 
        server 192.168.45.13:7070 backup; 
        }

Nginx+Tomcat的负载均衡&动静分离 详细解读,附具体实验_第1张图片

  • server 块参数
    • proxy_pass http://tomcat;
      • 表示该 host 下转发集群的名称
      • tomcat 为之前定义的集群名称
        location / {
           # root   html;
           # index  index.html index.htm;
            proxy_pass http://tomcat;
        }
  • 每次配置文件的修改都需要进行服务的重载
    • nginx -s reload

测试负载均衡

  • 使用 curl 命令进行测试
curl 192.168.45.10
  • 成功结果:页面内容会进行跳转
    Nginx+Tomcat的负载均衡&动静分离 详细解读,附具体实验_第2张图片
  • 在 tomcat 服务器中已经定义了默认网页的内容
    • tom1 是 11 号机 tom2 是 12 号机

后端获取真实 IP

场景

  • 由于使用了 nginx 进行了 [[1-Nginx概念&安装#反向代理|反向代理]],所以在后端服务器上是无法看到真实的访问 IP 等的信息的。
  • 故需要在反向代理服务器上进行设置,将真实的 IP 访问信息发送到后端服务器。

未配置的情况

cat /usr/local/tomcat/logs/localhost_access_log.2023-03-04.txt

Nginx+Tomcat的负载均衡&动静分离 详细解读,附具体实验_第3张图片

  • 会发现访问地址都是 192.168.45.10

配置

配置反向代理服务器

vim /usr/local/nginx/conf/nginx.conf
  • 关键参数
    • 位置:location 块
    • 机器:反向代理服务器
proxy_set_header  X-Forwarded-For  $remote_addr;
  • 反向代理服务器配置
        location / {
           # root   html;
           # index  index.html index.htm;
            proxy_pass http://tomcat;
            proxy_set_header  X-Forwarded-For  $remote_addr;

        }

Nginx+Tomcat的负载均衡&动静分离 详细解读,附具体实验_第4张图片

  • 重载生效配置文件
nginx -s reload

配置后端服务器

Tomcat 作为后端服务器时
vim /usr/local/tomcat/conf/server.xml
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
    prefix="localhost_access_log" suffix=".txt"
    pattern="%{X-FORWARDED-FOR}i %a %l %u %t %r %s %b %D %q %{User-Agent}i" resolveHosts="false" />
  • 关键参数
pattern="%{X-FORWARDED-FOR}i %a %l %u %t %r %s %b %D %q %{User-Agent}i" resolveHosts="false" />

image.png

pattern参数说明
  • %a - 远程 IP 地址
  • %A - 本地IP地址
  • %b - 发送的字节数,不包括HTTP头,或“ - ”如果没有发送字节
  • %B - 发送的字节数,不包括HTTP头
  • %h - 远程主机名
  • %H - 请求协议
  • %l (小写的L)- 远程逻辑从identd的用户名(总是返回’ - ')
  • %m - 请求方法
  • %p - 本地端口
  • %q - 查询字符串(在前面加上一个“?”如果它存在,否则是一个空字符串
  • %r - 第一行的要求
  • %s - 响应的HTTP状态代码
  • %S - 用户会话ID
  • %t - 日期和时间,在通用日志格式
  • %u - 远程用户身份验证
  • %U - 请求的URL路径
  • %v - 本地服务器名
  • %D - 处理请求的时间(以毫秒为单位)
  • %T - 处理请求的时间(以秒为单位)
  • %I (大写的i) - 当前请求的线程名称
  • 此外,您可以指定以下别名来设置为普遍使用的模式之一:
    • common - %h %l %u %t “%r” %s %b
    • combined - %h %l %u %t “%r” %s %b “%{Referer}i” “%{User-Agent}i”
Nginx 作为后端服务器时
  • 修改 nginx.conf
log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                  '$status $body_bytes_sent "$http_referer" '
                  '"$http_user_agent" "$http_x_forwarded_for"';
access_log  logs/access.log  main;
  • 关键参数
 '"$http_user_agent" "$http_x_forwarded_for"';
Apache 作为后端服务器时
  • 修改 http.conf
LogFormat "%{X-Forwarded-For}i %h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
LogFormat "%{X-Forwarded-For}i %h %l %u %t \"%r\" %>s %b" common
<IfModule logio_module>
   # You need to enable mod_logio.c to use %I and %O
   LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio
</IfModule>
  • 关键参数
LogFormat "%{X-Forwarded-For}i %h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
LogFormat "%{X-Forwarded-For}i %h %l %u %t \"%r\" %>s %b" common
  • 修改完以后需要进行重启
systemctl restart httpd

测试

  • 测试成功
  • 能够看到本地机器通过代理服务器进行访问
    Nginx+Tomcat的负载均衡&动静分离 详细解读,附具体实验_第5张图片

Nginx 的 proxy 缓存

使用 proxy 的意义

  • 启动缓存支持后,nginx 请求转发到 tomcat 前会在缓存里查找结果。
  • 如缓存里存在匹配客户端请求的结果,则直接返回给客户端,不会将请求发送给 tomcat;如果缓存没有命中,才会将请求发送给 tomcat,接收到 tomcat 返回的结果后,会将结果进行缓存以备客户端下次的请求.

缓存的清理

  • 可使用 ngx_cache_purge 模块在缓存过期时间未到前,手动清理缓存。

proxy 模块

  • Proxy 模块中常用的指令是 proxy_passproxy_cache
  • Proxy_cache 指令负责反向代理缓存后端服务器的静态内容。
  • Fastcgi_cache 主要用来处理 FastCGI 动态进程缓存。

ngx_cache_purge 部署

获取

链接在2023年3月3日 08:41:17 可用。

wget https://github.com/FRiCKLE/ngx_cache_purge/archive/refs/tags/2.3.tar.gz -O ngx_cache_purge-2.3.tar.gz

安装

  1. 解压
tar zxvf ngx_cache_purge-2.3.tar.gz  -C  /usr/local/src/
  1. 重新编译 nginx
cd /usr/local/src/nginx-1.22.0/
./configure --prefix=/usr/local/nginx --with-http_dav_module --with-http_stub_status_module --with-http_addition_module --with-http_sub_module --with-http_flv_module --with-http_mp4_module --with-pcre --with-http_ssl_module --with-http_gzip_static_module --add-module=/usr/local/ngx_cache_purge-2.3/
  1. 编译不安装,此处注意不需要安装,只需要编译。
make -j 4

配置

  1. 关闭 nginx 服务 
    nginx 的开关需要使用同一类方式,系统服务或者 nginx 命令
ngninx -s stop
  1. 备份原 nginx 命令
cp /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx.bak
  1. 拷贝 ngx_cache_purge 模块的 nginx
cd /usr/local/src/nginx-1.22.0/
cp  objs/nginx  /usr/local/nginx/sbin/nginx
  1. 调整 nginx.conf 配置文件
vim /usr/local/nginx/conf/nginx.conf
  • 定义缓存模块
    • 添加到对应的sever 块之上
	# 缓存模块
    proxy_connect_timeout   75;
    proxy_send_timeout   75;
    proxy_read_timeout   75;
    proxy_buffer_size   4k;
    proxy_buffers   4 32k;
    proxy_busy_buffers_size   64k;
    proxy_temp_file_write_size  64k;
    proxy_buffering on;
    proxy_temp_path /usr/local/nginx/proxy_temp;
    proxy_cache_path /usr/local/nginx/proxy_cache levels=1:2 keys_zone=my-cache:100m max_size=1000m inactive=600m max_size=2g;

Nginx+Tomcat的负载均衡&动静分离 详细解读,附具体实验_第6张图片

  • 缓存清理模块
    • 在对应server 块内新增location 块
        #ngx_cache_purge实现缓存清除
        location  ~ /purge(/.*) {
            allow 127.0.0.1;
            allow 192.168.45.0/24;
            deny all;
            proxy_cache_purge my-cache $host$1$is_args$args; #开启缓存清理及清>理权限
        }
        location  ~ .*\.(gif|jpg|png|html|htm|css|js|ico|swf|pdf)(.*) {
            proxy_pass  http://tomcat;  #使用负载均衡
            proxy_redirect off;    #在location里定义带参数
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_ignore_headers Set-Cookie;
            proxy_hide_header Set-Cookie;
            proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
            proxy_cache my-cache;  #在location里是用my-cache缓存
            add_header Nginx-Cache $upstream_cache_status;
            proxy_cache_valid 200 304 301 302 8h;
            proxy_cache_valid 404 1m;
            proxy_cache_valid any 1d;
            proxy_cache_key $host$uri$is_args$args;
            expires 30d;
        }

Nginx+Tomcat的负载均衡&动静分离 详细解读,附具体实验_第7张图片

  1. 重启 nginx 生效配置
nginx -s reload

参数解释

  • Proxy_buffering on;
    • 代理的时候,开启或关闭缓冲后端服务器的响应。
    • 当开启缓冲时,nginx 尽可能快地从被代理的服务器接收响应,再将它存入缓冲区中。
  • Proxy_temp_path;
    • 缓存临时目录。后端的响应并不直接返回客户端,而是先写到一个临时文件中,然后被 rename 一下当做缓存放在 proxy_cache_path。
    • 0.8.9 版本以后允许 tempcache 两个目录在不同文件系统上(分区)。
      • 为减少性能损失建议把它们放在一个文件系统上。
  • Proxy_cache_path;
    • 设置缓存目录,目录里的文件名是 cache_key 的 MD5值。
    • levels=1:2 keys_zone=my-cache:100m
      • 表示采用 2 级目录结构,第一层目录只有一个字符,是由 levels=1:2设置。
      • 总共二层目录,子目录名字由二个字符组成。Web 缓存区名称为 my-cache,内存缓存空间大小为 100 MB。
      • 文件系统上看到的缓存文件名类似于 /usr/local/nginx/proxy_cache/c/29/b7f54b2df7773722d382f4809d65029c
  • Inactive=600 max_size=2g
    • 表示 600 分钟没有被访问的内容自动清除,硬盘最大缓存空间为 2 GB,超过这个大小将清除最近最少使用的数据。
  • 默认情况,nginx 不缓存从后端响应的 http 头中带有 Set-Cookie 的对象。
    • 如客户端发送的请求带有 Cookie header,nginx 将忽略缓存,直接将请求传递到后端。
    • Nginx 中通过 proxy_ignore_headers 设置忽略它们,设置方法如下:
      • Proxy_ignore_headers Set-Cookie;
      • Proxy_hide_header Set-Cookie;
  • Proxy_cache
    • 引用前面定义的缓存区 my-cache
  • Proxy_cache_key
    • 定义如何生成缓存的键,设置 web 缓存的 key 值,nginx 根据 key 值 md5哈希存储缓存
  • Proxy_cache_valid
    • 为不同的响应状态码设置不同的缓存时间。
    • 比如 200、302 等正常结果可以缓存的时间长点
    • 404、500 等缓存时间设置短一些
    • 这个时间到了文件就会过期,而不论是否刚被访问过。
  • Add_header
    • 设置 response header
    • 语法: add_header name value;
  • $upstream_cache_status ^3fce02
    • 这个变量显示缓存的状态,我们可以在配置中添加一个 http 头来显示这一状态,
  • $upstream_cache_status 包含以下几种状态:
    • MISS 未命中,请求被传送到后端
    • HIT 缓存命中
    • EXPIRED 缓存已经过期请求被传送到后端
    • UPDATING 正在更新缓存,将使用旧的应答
    • STALE 后端将得到过期的应答
  • expires
    • 在响应头里设置 Expires 或 Cache-Control: max-age,返回给客户端的浏览器缓存失效时间。

测试缓存

  • 浏览器访问 192.168.45.10/index.jsp
    • 注意:访问 192.168.45.10 是无法命中缓存的
    • 缺少相关资料的佐证,猜想了一下,大概是因为直接访问的话对应 location 块的内容是一个变量,没有办法进行缓存。
    • 根据华为云 产品的说法,CDN 是可以命中的,缓存不知可否按照该逻辑进行命中。
  • 打开 F12 开发者调整模式
  • 检查标头中 Nginx Cache 内容,即 [[8-Nginx+Tomcat 负载均衡#^3fce02|缓存状态]]。 
    Nginx+Tomcat的负载均衡&动静分离 详细解读,附具体实验_第8张图片

清除缓存

  1. 可以直接删除缓存文件
  2. 浏览缓存清除网址。

Nginx 实现动静分离

基本概念

  • 动静分离
    • 场景:nginx 的高并发很强却不能处理动态内容,tomcat 高并发较弱,却可以处理动态内容。
    • 故而:使用上,将不同的内容的进行过滤交由合适的 web 服务群处理,可提升集群整体的处理能力。
      Nginx+Tomcat的负载均衡&动静分离 详细解读,附具体实验_第9张图片

配置动静分离

分析 nginx.conf

  1. 定义集群
    • 动态集群
    • 静态集群
  2. 缺一个静态处理的服务器
    • 因使用三台机器做实验
    • 需在代理服务器上新增虚拟主机,端口 808
    • 也可以新增一台 nginx 虚拟机做后端静态处理服务器
  3. 实现负载均衡
    • 用 80 端口的代理服务器做转发
      • 需要在代理服务器的 sever 块内
        • 定义静态转发规则
        • 定义动态转发规则

修改 nginx.conf

# 定义nginx静态服务器集群
    upstream nginx {                
        server 192.168.45.10:808 weight=1 max_fails=2 fail_timeout=10s;
    }
# 定义tomcat动态服务器集群
    upstream tomcat {     
        server 192.168.45.11:8080 weight=1 max_fails=1 fail_timeout=10s;
        server 192.168.45.12:8080 weight=2 max_fails=1 fail_timeout=10s;
    }
    # 808端口服务器   
    server{
         listen 808;
         server_name  www.808.com;
         location / {
            root   html;
            index  index.html index.htm;
         }   
         location  ~  .*\.(gif|jpg|jpeg|png|bmp|rar|zip|txt|flv|mid|doc|ppt|xls|mp3|wma|html|htm|css|js|ico|swf|pdf)$ {
            # 读取静态资源的存放位置
            root html ;
            expires 30d; 
            # 资源是否进行缓存及缓存时间
         }
    }
    # 80端口服务器
    server {
        listen       80;
        server_name  www.test.com;
        # 动态内容交由tomcat处理    
        location / {
           # root   html;
           # index  index.html index.htm;
            proxy_pass http://tomcat;
            proxy_redirect off;
            proxy_set_header  Host  $host;
            proxy_set_header  X-Forwarded-For  $remote_addr;
            proxy_set_header   X-Forwarded-Proto $scheme;
            proxy_ignore_headers Set-Cookie;
            proxy_hide_header Set-Cookie;
            proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;            
        }
        # 静态内容转发至nginx集群处理
        location  ~  .*\.(gif|jpg|jpeg|png|bmp|rar|zip|txt|flv|mid|doc|ppt|xls|mp3|wma|html|htm|css|js|ico|swf|pdf)$ {
            proxy_pass  http://nginx;
            proxy_redirect off;
            proxy_set_header Host $host;
            proxy_set_header X-Forwarded-For $remote_addr;
            proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
            proxy_cache my-cache;
            add_header Nginx-Cache $upstream_cache_status;
            proxy_cache_valid 200 304 301 302 8h;
            proxy_cache_valid 404 1m;
            proxy_cache_valid any 1d;
            proxy_cache_key $host$uri$is_args$args;
            expires 30d;
        }
        # 报错指向网页
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }

实际配置文件截图

Nginx+Tomcat的负载均衡&动静分离 详细解读,附具体实验_第10张图片

测试动静分离

思路

  1. 准备两个文件,分别代表静态内容动态内容
    • 只是代表,并不是动态内容和静态内容
  2. 存放在 nginx 与 tomcat 服务器上
  3. 访问反向代理服务器域名
  4. 查看是否能够正常访问到两个文件
  5. 就能确定是否达到了动静分离的效果

测试

1. 准备符合配置文件规则的测试文件
  • 动态文件准备
    • 之前的 tomcat 主页文件名称为 index.jsp
    • 符合过滤规则故这里不做修改了
  • 静态文件准备
    • nginx 默认的网页文件为 index.html
    • 符合静态文件规则,也不需要做修改
2. 浏览器访问代理服务器
  • 访问根目录 
    Nginx+Tomcat的负载均衡&动静分离 详细解读,附具体实验_第11张图片
  • 访问动态文件 192.168.45.10/index.jsp
    Nginx+Tomcat的负载均衡&动静分离 详细解读,附具体实验_第12张图片
  • 再次访问动态文件,测试负载均衡 192.168.45.10/index.jsp
    Nginx+Tomcat的负载均衡&动静分离 详细解读,附具体实验_第13张图片
  • 访问指定的静态资源 192.168.45.10/index.html 
    Nginx+Tomcat的负载均衡&动静分离 详细解读,附具体实验_第14张图片
3. 总结
  • 达到了基本实验目的
  • 整个的配置过程,涉及到的参数较多,需要对 nginx 和 tomcat 有基本的认知。
  • 在配置过程中,需要熟悉 nginx 配置文件的结构,明确前后端集群的关系。

你可能感兴趣的:(linux,运维,服务器,tomcat,nginx)