Tomcat 动静分离

1、使用 Nginx + Tomcat 搭建负载均衡

nginx 一般用来做反向代理和负载均衡,将客户端请求发送到后端的 tomcat,并将 tomcat 的响应发送给客户端。后端的 tomcat 通常不止一个,nginx 根据配置来选择其中一个 tomcat,比较常见的选择策略是轮询。

Nginx 的5种负载

负载方式

说明

轮询

每个请求按时间顺序逐一分配到不同的后端服务器,如果后端某台服务器宕机,故障系统被自动剔除,使用户访问不受影响。Weight指定轮询权值,Weight值越大,分配到的访问机率越高,主要用于后端每个服务器性能不均的情况下。

ip_hash

每个请求按访问IP的hash结果分配,这样来自同一个IP的访客固定访问一个后端服务器,有效解决了动态网页存在的session共享问题。当然如果这个节点不可用了,会发到下个节点,而此时没有session同步的话就注销掉了。

least_conn

least_conn :请求被发送到当前活跃连接最少的 real server 上。会考虑 weight的值。

url_hash

此方法按访问 url 的 hash结果来分配请求,使每个 url 定向到同一个后端服务器, 可以进一步提高后端缓存服务器的效率。Nginx 本身是不支持 url_hash 的,如果需 要使用这种调度算法,必须安装 Nginx 的 hash 软件包 nginx_upstream_hash

fair

这是比上面两个更加智能的负载均衡算法。此种算法可以依据页面大小和加载时间长短智能地进行负载均衡,也就是根据后端服务器的响应时间来分配请求,响应时间短的优先分配。Nginx 本身是不支持 fair 的,如果需要使用这种调度算法,必须下载 Nginx 的 upstream_fair 模块。

实验拓扑

主机

IP

服务

JClouds

192.168.137.253

Nginx

Book

192.168.137.252

Tomcat

Client01

192.168.137.6

Tomcat

安装Nginx:Nginx 安装 · 语雀

安装Tomcat:Tomcat 简介安装 · 语雀

配置 Nginx 负载均衡

vim /usr/local/nginx/conf/nginx.conf

# 在http里面添加
upstream tomcat {
        server 192.168.137.252:8080 weight=1 max_fails=1 fail_timeout=10s;
        server 192.168.137.6:8080 weight=2 max_fails=1 fail_timeout=10s;
}

server {
    listen       8081;
    server_name  localhost;

    location / {
        root   html;
        index  index.html index.htm;
        # 在 server 的location里面调用
        proxy_pass http://tomcat;           
    }
}

设备转态

说明

down

表示当前的 server 暂时不参与负载 ;

weight

默认为 1,weight 越大,负载的权重就越大;

max_fails

允许请求失败的次数默认为 1,当超过最大次数 proxy_next_upstream 模块定义的错误 ;

fail_timeout:max_fails

请求失败后,暂停的时间

backup

其它所有的非 backup 机器 down 或者忙的时候,请求 backup 机器,所以这台机器压力会最轻。

# Ip_Hash实现负载均衡:每一个客户端访问时都生成一个 hash 码,来自同一客户端的定向到同一服务器
# 修改配置文件
vim /usr/local/nginx/conf/nginx.conf 
upstream tomcat {
	ip_hash; 
  server 192.168.1.12:8080 weight=1 max_fails=1 fail_timeout=10s; 
  server 192.168.1.13:8080 weight=2 max_fails=1 fail_timeout=10s; 
}
2、后端服务器获取客户端真实ip

如何让后端 web 服务器(tomcat/apache/nginx)日志获取客户端真实的 IP,而不是 nginx 代理服务器的 IP。

Nginx代理服务器配置
# 修改 nginx 的配置文件,在 server 或者 location 中添加
vim /usr/local/nginx/conf/nginx.conf 
location / { 
  # root html; 
  # index index.html index.htm; 
  proxy_pass http://tomcat; 
  proxy_set_header X-Forwarded-For $remote_addr;
} 

nginx -s reload
tomcat 作为后端服务器的配置

如果 tomcat 作为后端 web,在 tomcat 日志中记录客户端的真实 ip,tomcat 需要做如下修改。

vim /usr/local/tomcat/conf/server.xml 

没有 Nginx 这一层的时候直接用%a 就可以获得客户端 IP,现在我们得用%{ X-FORWARDED-FOR }i 来获得真实的 IP 了。

日志参数

说明

%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" 

# 重启 tomcat 服务,客户端访问。查看 tomcat 的日志
systemctl restart tomcat 
tail -2 /usr/local/tomcat/logs/localhost_access_log.2024-01-25.txt 

nginx 作为后端服务器的配置

如果 nginx 作为后端 web,在 nginx 日志中记录客户端的真实 ip,nginx 需要做如下修改

Tomcat 动静分离_第1张图片

重启 nginx 服务,客户端访问。查看 nginx 的日志tail -2 /usr/local/nginx/logs/access.log

Tomcat 动静分离_第2张图片

apache 作为后端服务器的配置

如果 apache 作为后端 web,在 apache 日志中记录客户端的真实 ip,apache 需要做如下修改:

Tomcat 动静分离_第3张图片

重启 apache 服务,客户端访问。查看 apache 的日志:tail -2 /var/log/httpd/access_log

Tomcat 动静分离_第4张图片

3、Nginx 的 proxy 缓存使用

启动缓存支持以后,nginx 在将请求转发到 tomcat 之前会在缓存里查找结果,如果缓存里存在匹配客户端请求的结果,则直接返回给客户端,不会将请求发送给tomcat;

如果缓存没有命中,才会将请求发送给 tomcat,接收到 tomcat 返回的结果后,会将结果进行缓存以备客户端下次的请求. 开启缓存后,缓存及时清理成为了一个问题,需要使用 ngx_cache_purge 这个模块来在过期时间未到之前,手动清理缓存。

proxy 模块中常用的指令是 proxy_pass 和 proxy_cache.

proxy_cache 指令负责反向代理缓存后端服务器的静态内容。

fastcgi_cache 主要用来处理 FastCGI 动态进程缓存。

nginx 加载 ngx_cache_purge 模块

nginx 的所有模块必须在编译的时候添加,不能再运行的时候动态加载。如果你想在已安装好的 nginx 上添加第三方模块,依然需要重新编译,但为了不覆盖你原有的配置,请不要 make install,而是直接拷贝可执行文件。

# ngx_cache_purge 模块下载地址 
wget https://github.com/FRiCKLE/ngx_cache_purge/archive/refs/tags/2.3.tar.gz -O \
ngx_cache_purge-2.3.tar.gz

#  解压缩模块 
tar zxvf ngx_cache_purge-2.3.tar.gz -C /usr/local/src/


# 预编译 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=../ngx_cache_purge-2.3

make -j 2 && make install

# 先做备份
cp /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx.bak 
[root@cong11 nginx-1.22.0]# cp objs/nginx /usr/local/nginx/sbin/nginx
配置缓存
vim /usr/local/nginx/conf/nginx.conf

#定义缓存
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; 

upstream tomcat { 
  server 192.168.137.6:8080 weight=1 max_fails=1 fail_timeout=10s; 
  server 192.168.137.252:8080 weight=2 max_fails=1 fail_timeout=10s; 
} 

server { 
  listen 8081; 
  server_name localhost; 
  #charset koi8-r; 
  #access_log logs/host.access.log main; 
  #ngx_cache_purge 实现缓存清除
  
  location ~ /purge(/.*) { 
    allow 127.0.0.1; 
    allow 192.168.137.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; 
    # 在 location 里定义带参数
    proxy_redirect off;
    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; 
    # 在 location 里是用 my-cache 缓存
    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; 
  } 
  
  location / { 
    # root html; 
    # index index.html index.htm; 
    proxy_pass http://tomcat; 
    proxy_set_header X-Forwarded-For $remote_addr; 
  }
}

选项

说明

proxy_buffering on

代理的时候,开启或关闭缓冲后端服务器的响应。 当开启缓冲时,nginx 尽可能快地从被代理的服务器接收响应,再将它存入缓冲区中。

proxy_temp_path

缓存临时目录。后端的响应并不直接返回客户端,而是先写到一个临时文件中,然后被 rename 一下当做缓存放在 proxy_cache_path。0.8.9 版本 以后允许 temp 和 cache 两个目录在不同文件系统上(分区),然而为了减少性能损失还是建议把它们设成一个文件系统上。

proxy_cache_path

设置缓存目录,目录里的文件名是 cache_key 的 MD5 值。

levels=1:2 keys_zone=my-cache:100m 表示采用 2 级目录结构,第一层目录只有一个字符,是由 levels=1:2 设置,总共二层目录,子目录名字由二个字符组成。Web缓存区名称为 my-cache,内存缓存空间大小为 100MB。文件系统上看到的缓存文 件名类似于/usr/local/nginx/proxy_cache/c/29/b7f54b2df7773722d382f4809d65029c 。

inactive=600 max_size=2g 表示 600 分钟没有被访问的内容自动清除,硬盘最大缓存空间为 2GB,超过这个大小将清除最近最少使用的数据。

默认情况,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 这个变量来显示缓存的状态,我们可以在配置中添加一个 http 头来显示这一状态, $upstream_cache_status 包含以下几种状态:

  • MISS 未命中,请求被传送到后端
  • HIT 缓存命中
  • EXPIRED 缓存已经过期请求被传送到后端
  • UPDATING 正在更新缓存,将使用旧的应答
  • STALE 后端将得到过期的应答

expires

在响应头里设置 Expires:或 Cache-Control:max-age,返回给客户端的浏览器缓存失效时间。

# 重启 nginx 
nginx -s reload 

# 测试缓存功能
echo "server1 html" > /usr/local/tomcat/webapps/ROOT/index.html 
echo "server2 html" > /usr/local/tomcat/webapps/ROOT/index.html

Tomcat 动静分离_第5张图片

Tomcat 动静分离_第6张图片

清除缓存

使用 ngx_cache_purge 模块清除缓存(直接删除缓存目录下的文件也可以)GET 方式请求 URL,即使用配置文件中的 location ~ /purge(/.*)

location ~ /purge(/.*) {
    allow 127.0.0.1;
    allow 192.168.137.0/24;
    deny all;
    proxy_cache_purge my-cache $host$1$is_args$args;
}

Tomcat 动静分离_第7张图片

4、Nginx 实现动静分离

Nginx 的高并发能力很强,因此,可以在公司里面结合其他的 web 服务器来使用动静分离技术,在 server{}使用正则匹配的 location 来进行流量过滤,静态资源交给 Nginx 处理,动态资源交给 PHP-FPM 模块或 Apache、tomcat、IIS 处理。

Tomcat 动静分离_第8张图片

vim /usr/local/nginx/conf/nginx.conf

upstream nginx {
		server 192.168.137.253:8082 weight=1 max_fails=2 fail_timeout=10s; 
	}
	
upstream tomcat { 
  server 192.168.137.6:8080 weight=1 max_fails=1 fail_timeout=10s; 
  server 192.168.137.252:8080 weight=2 max_fails=1 fail_timeout=10s; 
} 


server{
  listen 8082; 
  server_name www.nihao.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; 
  } 
} 

server { 
  listen 8081; 
  server_name localhost; 
  #charset koi8-r; 
  #access_log logs/host.access.log main; 
  #ngx_cache_purge 实现缓存清除
  allow 192.168.137.0/24; 
  deny all; 
  
  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; 
  } 
  
  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; 
  }
}

Tomcat 动静分离_第9张图片

5、Jemeter 压力测试

Tomcat 动静分离_第10张图片

Tomcat 动静分离_第11张图片

1000 个线程,每个线程循环 10 次,也就是 tomcat 会接收到 10000 个请求

Tomcat 动静分离_第12张图片

Tomcat 动静分离_第13张图片

Tomcat 动静分离_第14张图片

Tomcat 动静分离_第15张图片

Tomcat 动静分离_第16张图片

Tomcat 动静分离_第17张图片

你可能感兴趣的:(Tomcat,tomcat,java)