案例:Nginx + Tomcat集群(负载均衡 动静分离)

目录

案例

案例环境

案例步骤

部署Tomcat服务器

部署Nginx服务器

实现负载均衡和读写分离

日志控制


案例

案例环境

|----------------|----------------|---------------|
| 操作系统 | IP 地址 | 角色 |
| CentOS | 192.168.10.101 | Nginx服务器(调度器) |
| CentOS | 192.168.10.102 | Tomcat服务器① |
| CentOS | 192.168.10.103 | Tomcat服务器② |
| Windows虚拟机或宿主机 | | 浏览器测试 |

需求:静态请求交给Nginx解析,动态请求交给2个Tomcat服务器实现动静分离和负载均衡

以及日志的控制

假如有DDOS等网络攻击,服务器的连接数会被耗尽,需要获取真实客户端的地址

DDOS:分布式拒绝服务攻击


案例步骤

部署Tomcat服务器

因为102和103都是作为Tomcat服务器,部署的大致步骤相同,这里我们只开启102和103的会话同步

分别导入tomcat源码软件包到102和103主机

在102(Tomcat服务器①)操作

为了方便实验关闭防火墙和内核安全机制

tomcat是java开发的,这里我们需要在系统上安装java,确保开发环境一致

这里yum安装的java没有指定版本,安装的java版本是1.8的,可能仅适用于本次案例

bash 复制代码
[root@localhost ~]# systemctl stop firewalld
[root@localhost ~]# setenforce 0
[root@localhost ~]# yum -y install java

tomcat是解压即用的,不需要编译和安装。

移动到/usr/local/下方便使用

bash 复制代码
[root@localhost ~]# tar zxvf apache-tomcat-9.0.8.tar.gz
[root@localhost ~]# mv apache-tomcat-9.0.8 /usr/local/tomcat9

在根目录下创建一个用来存放网页文件的目录

在该目录下添加动态内容和静态内容,以达到更好的测试效果

bash 复制代码
[root@localhost webapps]# mkdir -p /web/webapp1
[root@localhost webapps]# cd /web/webapp1/
[root@localhost webapp1]# vim index.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<html>
<head>
     <title>JSP test1 page</title>   </head>
   <body>
     <% out.println("动态页面 1,http://www.test1.com");%>
   </body>
   <body>
    <div>动态页面的图片 1</div><br><img src="logo.jpg">
   </body>
</html>

在103(Tomcat服务器②)操作

为了实现调度的效果,暂时关闭会话同步,来到103把其中的文本内容改一下

bash 复制代码
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> 
<html>   
<head>
     <title>JSP test2 page</title>
</head>
   <body>
     <% out.println("动态页面 2,http://www.test2.com");%>
   </body> 
   <body> 
    <div>动态页面的图片 2</div><br><img src="logo.jpg"> 
   </body> 
</html>

在102(Tomcat服务器①)操作

开启会话同步

打开tomcat配置文件

在第150行,Host单元中添加Context标签,指定网页文件的位置

bash 复制代码
[root@localhost tomcat9]# vim /usr/local/tomcat9/conf/server.xml
<Context docBase="/web/webapp1" path="" />

保存并退出,启动tomcat

bash 复制代码
[root@localhost ~]# /usr/local/tomcat9/bin/startup.sh

使用宿主机的浏览器测试,访问两个Web服务器的IP+端口号。结果如下,动态和静态的内容都显示出来了

图像、音频、视频之类的资源我们交给Nginx去解析,所以现在看不到图片是正常的


部署Nginx服务器

在101(Nginx服务器)操作

首先导入Nginx的源码软件包,准备安装

为了方便实验,关闭防火墙和内核安全机制

再安装Nginx依赖软件包,创建程序用户

bash 复制代码
[root@localhost ~]# systemctl stop firewalld
[root@localhost ~]# setenforce 0
[root@localhost ~]# yum -y install pcre-devel zlib-devel gcc*
[root@localhost ~]# useradd -M -s /sbin/nologin nginx

解压Nginx源码包,进入解压目录,运行configure脚本,指定安装参数,编译(make)、安装(make install)

bash 复制代码
[root@localhost ~]# tar zxvf nginx-1.12.0.tar.gz
[root@localhost ~]# cd nginx-1.12.0
[root@localhost nginx-1.12.0]# ./configure --prefix=/usr/local/nginx --user=nginx --group=nginx
[root@localhost nginx-1.12.0]# make && make install

优化调用命令的方式,创建软链接到命令目录下,然后使用nginx -t测试是否能正常调用命令

bash 复制代码
[root@localhost nginx-1.12.0]# ln -s /usr/local/nginx/sbin/nginx /usr/local/sbin/
[root@localhost ~]# nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful

cd进入Nginx存放网页文件的目录,删除index.html文件中的内容,替换为下方代码块的内容

bash 复制代码
[root@localhost ~]# cd /usr/local/nginx/html/
[root@localhost html]# vim index.html
<body>
<h1>静态页面</h1>
</body>

因为我们的网页有中文,所以打开Nginx配置文件,在第39行指定字符集为utf8,然后保存并退出

bash 复制代码
[root@localhost ~]# vim /usr/local/nginx/conf/nginx.conf
charset utf8;

启动nginx服务,结果如下图

bash 复制代码
[root@localhost ~]# nginx

实现负载均衡和读写分离

刚才说了在这个案例的环境中,图像等静态资源由Nginx负责解析,那么相应的要实现动静分离

cd进入Nginx存放网页文件的目录,在该目录下创建一个存放图片资源的子目录,进入该目录,把之前在tomcat指定的logo.jpg导入进该目录下

bash 复制代码
[root@localhost ~]# cd /usr/local/nginx/html/
[root@localhost html]# mkdir img
[root@localhost html]# cd img/

除此之外,还需要修改配置文件来实现动静分离

返回上一级目录知道nginx根目录,打开配置文件

bash 复制代码
[root@localhost img]# cd ..
[root@localhost html]# cd ..
[root@localhost nginx]# vim conf/nginx.conf

在第34行,添加upstream单元来配置负载均衡

再往下隔一个location单元,添加2个location单元实现读写分离(看下图)

下方代码表示nginx会将到达的请求按照权重分发到两台Tomcat服务器上,权重值(weight)越高,处理的请求越多

bash 复制代码
    upstream mytomcat {
        server 192.168.10.102:8080;
        server 192.168.10.103:8080;
    }
    # 省略...
    location ~ .*\.jsp$ {
        proxy_set_header HOST $host;
        proxy_pass http://mytomcat;
    }

    location ~ .*\.(jpg|png|gif)$ {
        root /usr/local/nginx/html/img;
        expires 30d;
    }

|------------------------------|------------------------------------------------------------------|
| 参数 | 说明 |
| proxy_set_header HOST $host; | 把原http请求中的Header中的Host字段放到转发的请求报文里,后端的web服务器利用这个host判断请求的是哪个虚拟主机 |

  • ~:不区分大小写
  • .*.\.jsp$:nginx匹配所有以.jsp结尾的请求,并将它们转发到定义的mytomcat后端服务器组中的某个Tomcat服务器处理。
  • .*\.(jpg|png|gif)$:这个配置用于处理静态图片文件。对于这些文件的请求,nginx会直接从指定的目录中提供,并设置响应头以便客户端进行缓存。
  • expires 30d:缓存时间为30天

由于修改了配置文件,需要重启服务使其生效,使用宿主机的浏览器访问192.168.10.101/index.jsp,此时就可以解析图片了,效果如下图

bash 复制代码
[root@localhost nginx]# nginx -s stop
[root@localhost nginx]# nginx

日志控制

在102(Tomcat服务器①)操作

如果此时查看Tomcat的访问日志,可以看到访问的IP都是代理服务器的IP

那么我们需要把这些源IP改为客户端的真实IP,以便Tomcat的访问日志能够详细记录

bash 复制代码
[root@localhost ~]# tail /usr/local/tomcat9/logs/localhost_access_log.2024-08-08.txt 
192.168.10.101 - - [08/Aug/2024:10:10:17 +0800] "GET /index.jsp HTTP/1.0" 200 215
192.168.10.101 - - [08/Aug/2024:10:10:18 +0800] "GET /index.jsp HTTP/1.0" 200 215
192.168.10.101 - - [08/Aug/2024:10:10:19 +0800] "GET /index.jsp HTTP/1.0" 200 215

在101(Nginx服务器)操作

打开配置文件,可以在location单元中设置对应参数来改变tomcat访问日志中的源IP

bash 复制代码
location ~ .*\.jsp$ {
            proxy_set_header HOST $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header Client-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_pass  http://myTomcat;
        }

|--------------------------------------------------------------|---------------------------------------------------------------------------------------------------|
| 参数 | 说明 |
| proxy_set_header X-Real-IP remote_addr; | 使用remote_addr变量获得用户的真实ip 如果有多个代理,$remote_addr一般设置在第一个代理服务器上。 当一个请求通过多个代理服务器时,用户的IP将会被代理服务器IP覆盖 |
| proxy_set_header Client-IP $remote_addr; | 获取客户端ip地址 |
| proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; | 从客户的真实ip为起点,穿过多层代理的proxy ,最终到达web服务器,都会记录下来。 所以在获取用户真实ip的时候,最后一个nginx配置此变量,用来获取客户端的ip地址 适合多层代理的场景 |

在102、103(Tomcat服务器①②)操作

打开Tomcat配置文件

在第162行添加代理服务器定义的变量

bash 复制代码
[root@localhost ~]# vim /usr/local/tomcat9/conf/server.xml
pattern="%{X-Real-IP}i %h %l %u %t &quot;%r&quot; %s %b" />
  • i:请求头

然后重启Tomcat服务

bash 复制代码
[root@localhost ~]# /usr/local/tomcat9/bin/shutdown.sh 
[root@localhost ~]# /usr/local/tomcat9/bin/startup.sh 

然后查看访问日志,就可以看到客户端的真实IP被加到开头了

bash 复制代码
[root@localhost ~]# tail /usr/local/tomcat9/logs/localhost_access_log.2024-08-08.txt 

192.168.10.1 192.168.10.101 - - [08/Aug/2024:11:02:52 +0800] "GET /index.jsp HTTP/1.0" 200 215
192.168.10.1 192.168.10.101 - - [08/Aug/2024:11:02:52 +0800] "GET /index.jsp HTTP/1.0" 200 215
192.168.10.1 192.168.10.101 - - [08/Aug/2024:11:02:52 +0800] "GET /index.jsp HTTP/1.0" 200 215
相关推荐
丶21362 分钟前
【Nginx】在 Docker 上安装 Nginx 的详细指南
运维·nginx·docker
沐风ya3 分钟前
Reactor介绍,如何从简易版本的epoll修改成Reactor模型(demo版本代码+详细介绍)
网络
SUGERBOOM7 分钟前
【网络安全】网络基础第一阶段——第一节:网络协议基础---- OSI与TCP/IP协议
网络·网络协议·web安全
danplus16 分钟前
node发送邮件:如何实现Node.js发信功能?
服务器·node.js·外贸开发信·邮件群发·蜂邮edm邮件营销·邮件接口·营销邮件
神即道 道法自然 如来18 分钟前
Jenkins怎么设置每日自动执行构建任务?
运维·jenkins
petaexpress24 分钟前
常用的k8s容器网络模式有哪些?
网络·容器·kubernetes
小黑爱编程25 分钟前
【LInux】HTTPS是如何实现安全传输的
linux·安全·https
BeyondESH30 分钟前
Linux线程同步—竞态条件和互斥锁(C语言)
linux·服务器·c++
wn53131 分钟前
【Go - 类型断言】
服务器·开发语言·后端·golang
hanniuniu1332 分钟前
详细解读,F5服务器负载均衡的技术优势
运维·服务器·负载均衡