基于tomcat的动静分离

动静分离(单台)

文章目录

bash 复制代码
[root@web03 ~]# cat /etc/nginx/conf.d/zrlog.song.com.conf 
server{
  listen 80;
  server_name zrlog.song.com;

  error_log /var/log/nginx/zrlog-error.log notice;
  access_log /var/log/nginx/zrlog-access.log main;

  location ~* \.(html|css|js)$ {
   root /app/tools/apache-tomcat-9.0.111/webapps/ROOT/;
   expires 7d;
  }

  location / {
   proxy_pass http://127.0.0.1:8080;
   proxy_set_header Host $host;
   proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
   proxy_set_header X-Real_Ip $remote_addr;
  }
}

如果访问页面只有文字,没有js,css样式,需要给权限

bash 复制代码
find /app/tools/tomcat/webapps/ -type d | xargs chmod 755
find /app/tools/tomcat/webapps/ -type f | xargs chmod 644

注意查看/tomcat/bin/下的执行权限

浏览器访问就正常了

tomcat配置文件server.xml文件

  • tomcat/conf/server.xml
bash 复制代码
cp server.xml server.xml.bak

#删除xml注释命令
sed -i '/<!--/,/-->/d' server.xml.bak
#删除xml空行
sed -i '/^$/d' server.xml.bak


[root@web03 ~]# cat server.xml.bak 
<?xml version="1.0" encoding="UTF-8"?>
<Server port="8005" shutdown="SHUTDOWN">
  <Listener className="org.apache.catalina.startup.VersionLoggerListener" />
  <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
  <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
  <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
  #配置用户数据库资源
  <GlobalNamingResources>
    <Resource name="UserDatabase" auth="Container"
              type="org.apache.catalina.UserDatabase"
              description="User database that can be updated and saved"
              factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
              pathname="conf/tomcat-users.xml" />
  </GlobalNamingResources>
  #http连接器接口
  <Service name="Catalina">
    <Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443"  #https认证
               maxParameterCount="1000"
               />
    <Engine name="Catalina" defaultHost="localhost">
      <Realm className="org.apache.catalina.realm.LockOutRealm">
        <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
               resourceName="UserDatabase"/>
      </Realm>
           #域名                站点目录
      <Host name="localhost"  appBase="webapps"
            #自动解压 ,自动部署(jvm)
            unpackWARs="true" autoDeploy="true">
          #日志文件格式。日志名字,日志后缀
        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
               prefix="localhost_access_log" suffix=".txt"
               pattern="%h %l %u %t &quot;%r&quot; %s %b" />
      </Host>
    </Engine>
  </Service>
</Server>

配置文件关键部分说明:

  1. Server 节点

    • port="8005":Tomcat 关闭端口(默认,用于接收关闭命令)。
    • shutdown="SHUTDOWN":关闭命令字符串(默认)。
  2. Listener 节点

    包含了 Tomcat 启动时的必要监听器(如防止 JRE 内存泄漏、线程本地变量泄漏等),都是默认且推荐的配置。

  3. GlobalNamingResources 节点

    配置了用户数据库资源(UserDatabase),关联到 conf/tomcat-users.xml,用于 Tomcat 自带的用户认证(如管理界面登录)。

  4. Service 与 Connector 节点

    • port="8080":HTTP 连接器端口(默认,对外提供 HTTP 服务的端口)。
    • protocol="HTTP/1.1":HTTP 协议版本。
    • redirectPort="8443":HTTPS 重定向端口(若启用 HTTPS,HTTP 请求会重定向到该端口)。
  5. Engine 与 Host 节点

    • 默认主机 localhost,应用部署目录 appBase="webapps"(Tomcat 默认的应用存放路径)。
    • unpackWARs="true":自动解压 webapps 目录下的 WAR 包。
    • autoDeploy="true":自动部署新的应用(无需重启 Tomcat)。
tomcat vs ngx 对比 tomcat ngx
web 端口 Connector=8080 listen 80/443
站点 / 虚拟主机 部分 server {} 部分
域名 name="localhost" server_name
站点目录 appBase="webapps" root
自动解压 (war 包解压目录) zip 压缩包 unpackWARs="true"
自动部署 (加载 jvm) autoDeploy="true"

配置tomcat访问日志格式

说明 Tomcat Nginx 解读
定义访问日志的格式 Host 部分的 pattern 定义 http 区域 log_format 部分 Tomcat 在<Host>配置块中通过pattern属性定义日志格式;Nginx 在http块中通过log_format指令定义。
客户端 ip 地址 %h $remote_addr 均记录发起请求的客户端 IP 地址,用于识别访问来源。
访问的时间 %t $local_time 记录请求被处理的时间,Tomcat 格式为[日期:时间 时区],Nginx 为本地时间格式。
请求起始行 (请求方法,URI,HTTP) %r $request 记录请求的第一行(如GET /index.html HTTP/1.1),包含请求方法、URI、协议版本。
状态码 %s $status 记录 HTTP 响应状态码(如 200、404、500),用于判断请求处理结果。
大小 %b $body_bytes_sent 记录响应体的字节大小(不含响应头),用于统计流量和数据量。
从哪里跳转来 (用户如何访问网站) %{Referer} i 新增 $http_referer 记录 Referer 头,即用户跳转来源页面,用于流量分析和防盗链。Tomcat 需显式配置该字段,Nginx 为原生变量。
客户端类型,浏览器 %{User-Agent} i 新增 $http_user_agent 记录 User-Agent 头,包含浏览器、操作系统等信息,用于分析用户设备分布。Tomcat 需显式配置,Nginx 为原生变量。
XFF 头记录 %{X-Forwarded-For} i 新增 $http_x_forwarded_for 记录 X-Forwarded-For 头,在反向代理场景下获取真实客户端 IP。Tomcat 需显式配置,Nginx 为原生变量。
js 复制代码
#直接复制到valve块即可,将原来的value块注释
<!--    -->


<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
                  prefix="localhost_access" suffix=".log"
                 pattern="%h %l %u %t &quot;%r&quot; %s %b &quot;%{Referer}i&quot; 
                 &quot;%{User-Agent}i&quot; &quot;%{X-Forwarded-For}i&quot;" />

tomcat多站点

/tomcat/conf/server.xml

js 复制代码
       <Host name="localhost"  appBase="webapps"
            unpackWARs="true" autoDeploy="true">
           <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
                  prefix="localhost_access" suffix=".log"
                 pattern="%h %l %u %t &quot;%r&quot; %s %b &quot;%{Referer}i&quot; 
                 &quot;%{User-Agent}i&quot; &quot;%{X-Forwarded-For}i&quot;" />
     </Host>
     
<!-- ----------------设置新站点---------------->
                <!-- 设置域名                    站点目录-->
     <Host name="java.songhong.cn"  appBase="2webapps"
              unpackWARs="true" autoDeploy="true">
           <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"       
                       <!--日志名字                后缀-->
                  prefix="java.songhong_access" suffix=".log"
                 pattern="%h %l %u %t &quot;%r&quot; %s %b &quot;%{Referer}i&quot;
                 &quot;%{User-Agent}i&quot; &quot;%{X-Forwarded-For}i&quot;" />
     </Host>
shell 复制代码
systemctl restart tomcat
#会自动生成一个新目录
[root@web03 ~]# ll /tomcat/2webapps/

mkdir /tomcat/2webapps/ROOT/

echo 11111111 >/tomcat/2webapps/ROOT/index.jsp

curl -H Host:java.songhong.cn http://10.0.0.9:8080
[root@web03 ~]# curl -H Host:java.songhong.cn http://10.0.0.9:8080
1111111111111111java.songhong.com

tomcat处理用户请求流程

  1. 请求入口:Connector(对应 Nginx 的 listen 端口)
  • 配置文件位置<Connector> 标签定义在 server.xml<Service> 内。

  • 功能

    • 监听指定端口(如 80/443)和协议(HTTP/1.1、AJP、HTTP/2)。
    • 接收客户端请求,处理协议解析(如 HTTP 报文解析)。
    • 支持 SSL 配置(通过 SSLEnabledkeystoreFile 等参数)。
  • Nginx 对比

    • 类似 Nginx 的 listen 80listen 443 ssl 配置。
    • 一个 <Service> 可以包含多个 <Connector>,类似 Nginx 的多个 server 监听不同端口。

配置示例

xml 复制代码
<Connector
  port="8080"
  protocol="HTTP/1.1"
  connectionTimeout="20000"
  redirectPort="8443"
  URIEncoding="UTF-8" />
  1. 请求分发:Engine(对应 Nginx 的 http 全局区域)
  • 配置文件位置<Engine> 标签定义在 server.xml<Service> 内,包裹在 <Connector> 之后。

  • 功能

    • 作为请求处理的全局容器,管理多个虚拟主机(<Host>)。
    • 通过 defaultHost 属性指定默认虚拟主机(类似 Nginx 的 default_server)。
  • Nginx 对比

    • 类似 Nginx 的 http { ... } 块,是所有站点配置的入口。

配置示例

xml 复制代码
<Engine name="Catalina" defaultHost="localhost">
  1. 虚拟主机匹配:Host(对应 Nginx 的 server 块)
  • 配置文件位置<Host> 标签定义在 server.xml<Engine> 内。
  • 功能
    • 根据域名(name 属性)匹配请求的 Host 头。
    • 管理多个 Web 应用(<Context>),每个应用对应一个 URL 路径。
  • Nginx 对比
    • 类似 Nginx 的 server { listen 80; server_name example.com; ... } 配置块。
    • name 属性对应 Nginx 的 server_name(用于域名匹配)。

配置示例

xml 复制代码
<Host
  name="www.example.com"
  appBase="webapps/example"
  unpackWARs="true"
  autoDeploy="true">
</Host>
  1. 应用路径匹配:Context(对应 Nginx 的 location 规则)
  • 配置文件位置<Context> 标签可定义在 <Host> 内,或通过 web.xml 隐式配置。
  • 功能
    • 通过 path 属性匹配 URL 路径,将请求路由到具体 Web 应用。
    • 指定应用资源路径(docBase 属性,类似 Nginx 的 rootalias)。
  • Nginx 对比
    • 类似 Nginx 的 location /app { ... } 规则。
    • 默认 ROOT 应用对应 path="",处理根路径请求。

配置示例

xml 复制代码
<Context
  path="/api"
  docBase="/data/webapps/api"
  reloadable="true"/>
  1. 请求处理链:Valve(类似 Nginx 的中间件模块)
  • 配置文件位置<Valve> 标签可以定义在 <Engine><Host><Context> 内。
  • 功能
    • 实现请求处理链的扩展逻辑(如日志记录、IP 过滤、权限控制)。
    • 支持自定义 Valve 组件。
  • Nginx 对比
    • 类似 Nginx 的 access_logauth_request 模块。
xml 复制代码
<Valve
  className="org.apache.catalina.valves.AccessLogValve"
  directory="logs"
  prefix="example_access"
  suffix=".log"
  pattern="%h %l %u %t &quot;%r&quot; %s %b"/>

完整请求处理流程

  1. 连接建立

    用户通过浏览器访问http://www.example.com:8080/data,请求到达tomcat的`Connector`(监听8080端口)

  2. 协议处理

Connetcor解析HTTP协议,生成RequestResponse对象

  1. 虚拟主机匹配

请求被传递到Engine,根据Host头匹配

  1. 应用路径路由

在匹配的Host中,根据URL路径/api/data查找,定位/data/webappes/api目录下的应用

  1. Servlet处理

应用内部的web.xml或注解配置的Servlet根据剩余路径/data处理请求

  1. 响应返回

处理结果通过Connetor返回客户端

关键配置文件对比总结

Tomcat 组件 Nginx 对应结构 功能描述
Connector listen 80 定义端口和协议
Engine http { ... } 全局请求处理容器
Host server { ... } 基于域名的虚拟主机配置
Context location /path URL 路径与应用映射
Valve access_log 等模块 请求处理链的扩展逻辑

tomcat多实例

  • tomcat/mysql
  • 同一台机器运行多个相同的服务tomcat
  • 编译安装软件/二进制安装软件

示例

bash 复制代码
tar -xf apache-tomcat-9.0.111.tar.gz

mv apache-tomcat-9.0.111 tomcat-9-8082

sed -i 's/8080/8082/g' tomcat-9-8082/conf/server.xml
sed -i 's/8005/8007/g' tomcat-9-8082/conf/server.xml

mv tomcat-9-8082 /app/tools/

/app/tools/tomcat-10-8081/bin/startup.sh
/app/tools/tomcat-9-8082/bin/startup.sh

[root@web03 ~]# ss -lntup | grep java
tcp    LISTEN  0       1        [::ffff:127.0.0.1]:8005                 *:*      users:(("java",pid=787,fd=54))                                                 
tcp    LISTEN  0       1        [::ffff:127.0.0.1]:8006                 *:*      users:(("java",pid=1363,fd=55))                                                
tcp    LISTEN  0       1        [::ffff:127.0.0.1]:8007                 *:*      users:(("java",pid=1405,fd=55))                                                
tcp    LISTEN  0       100                       *:8080                 *:*      users:(("java",pid=787,fd=45))                                                 
tcp    LISTEN  0       100                       *:8081                 *:*      users:(("java",pid=1363,fd=45))                                                
tcp    LISTEN  0       100                       *:8082                 *:*      users:(("java",pid=1405,fd=46))

tomcat监控

sh 复制代码
java-11-openjdk-devel软件包含了jps,jstack,jmap等命令

jps 显示java进程

bash 复制代码
[root@web03 ~]# jps
787 Bootstrap
1574 Bootstrap
1610 Jps

jps -lvm
-l 显示完整包名
-v 显示jvm参数
-m 显示启动时的参数

[root@web03 ~]# jps -l
1648 jdk.jcmd/sun.tools.jps.Jps
787 org.apache.catalina.startup.Bootstrap
1574 org.apache.catalina.startup.Bootstrap
[root@web03 ~]# jps -m
787 Bootstrap start
1574 Bootstrap start
1671 Jps -m

jstack java进程的线程信息

bash 复制代码
进程:一个命令,软件,服务运行起来后,占用资源,内存
线程:处理请求,干活,threads

1.进程启动(支持多线程)
2.进程占用资源,内存
3,干活进程中线程,处理用户请求

查看具体线程信息

线程状态 描述
NEW 线程已创建但尚未启动(未调用 start() 方法)。
RUNNABLE 线程正在运行或准备运行,等待 CPU 调度。
BLOCKED 线程被阻塞,等待获取监视器锁(例如,进入同步块或方法)。
WAITING 线程无限期等待,直到被其他线程显式唤醒(例如,调用 Object.wait())。
TIMED_WAITING 线程在指定时间内等待(例如,调用 Thread.sleep()Object.wait(timeout))。
TERMINATED 线程已执行完毕,终止状态。
bash 复制代码
jps
787 Bootstrap
1574 Bootstrap
1771 Jps

#查看具体线程信息
top -p 1574 -H
pstree -p 787

ps -efl
-e 显示所有进程
-f 以全格式输出
-l 以长格式输出,比-f更详细

#jstack pid(进程id)
jstack 1574 | grep -i thread.state
过滤进程中线程状态
正常状态:RUNNABLE  WBLOCKEDAITING
阻塞: BLOCKED(io)

#java进程中线程的状态,每种状态数量
jstack 1574 | grep -i thread.state | awk '{print $2}' |sort |uniq -c

jmap jvm信息

mat工具链接

通过网盘分享的文件:【MAT-jvm内存镜像分析工具】MemoryAnalyzer-1.8.0.20180604-win32.win32.x86_64.zip

链接: https://pan.baidu.com/s/1qAPTIqe5xFh4f1YCaSaYiA?pwd=zviv 提取码: zviv

sh 复制代码
jmap -heap 1574 #导出jvm信息,使用率,未来用自定义监控,jdk8及之前


jhsdb jmap --heap --pid 1574  #jdk8以后的版本

保存jvm文件,然后使用MAT分析,交给第三方工具分析

#导出jvm内存数据到文件中
jmap -dump:format=b,file=/root/tomcat-10.hprof 1574


[root@web03 ~]# jmap -dump:format=b,file=/root/tomcat-10.hprof 1574
Dumping heap to /root/tomcat-10.hprof ...
Unable to create /root/tomcat-10.hprof: File exists


将保存的文件导出windows的mat文件的目录下


#通过ma/mat工具分析,内存分析工具,Memory Ana---->java
windows安装jdk,然后运行mat工具

注意将导出的文件放在解压文件的目录下,以.hprof结尾

解压安装包,最好是纯英文路径,解压后双击exe进入

系统负载高排查流程-java

bash 复制代码
pidstat 1 3 #1秒更新一次,更新3次

iotop -o

[root@web03 ~]# jps
1687 Bootstrap
1436 Bootstrap
2092 Jps
[root@web03 ~]# cat /proc/1687/io
rchar: 8233004
wchar: 26708971
syscr: 4872
syscw: 127
read_bytes: 6782976
write_bytes: 27451392
cancelled_write_bytes: 0

集群模式(动静分离)

环境准备

节点 ip
web03 10.0.0.9/172.16.1.9 tomcat+nginx
web04 10.0.0.10/172.16.1.10 nginx
db01 10.0.0.51/172.16.1.51 mariadb
lb01,lb02 10.0.0.5 10.0.0.6 nginx+keepalived
  • 前提条件 web03已经成功部署zrlog
bash 复制代码
#web03将部署的包传给web04
[root@web03 ~]# scp -r /tomcat/webapps/ root@10.0.0.10:/app/tools/tomcat/
[root@web03 ~]# cat /etc/nginx/conf.d/zrlog.song.com.conf 
server{
  listen 80;
  server_name zrlog.song.com;

  error_log /var/log/nginx/zrlog-error.log notice;
  access_log /var/log/nginx/zrlog-access.log main;
  
  location / {
   proxy_pass http://127.0.0.1:8080;
   proxy_set_header Host $host;
   proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
   proxy_set_header X-Real_Ip $remote_addr;
  }
}
  • web04
bash 复制代码
[root@web04 ~]# nginx -v
nginx version: nginx/1.28.0
[root@web04 ~]# systemctl enable --now nginx
Created symlink /etc/systemd/system/multi-user.target.wants/nginx.service → /usr/lib/systemd/system/nginx.service.
mkdir -p /app/tools/tomcat/
[root@web04 ~]# cat /etc/nginx/conf.d/zrlog.song.com.conf 
server{
  listen 80;
  server_name zrlog.song.com;
  error_log /var/log/nginx/zrlog-error.log notice;
  access_log /var/log/nginx/zrlog-access.log main; 

  root /app/tools/tomcat/webapps/ROOT/;
  location / {
  index index.html;
  }
}
systemctl reload nginx
  • lb01和lb02
bash 复制代码
[root@lb01 ~]# cat /etc/nginx/conf.d/zrlog.song.com.conf
upstream zrlog_default {
  server 10.0.0.9:80;
}
upstream zrlog_static {
  server 10.0.0.10:80;
}
server {
  listen 80;
  server_name zrlog.song.com;

  error_log /var/log/nginx/zrlog-error.log notice;
  access_log /var/log/nginx/zrlog-access.log main;
  
  location / {
  proxy_pass http://zrlog_default;
   proxy_set_header Host $host;
   proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
   proxy_set_header X-Real_Ip $remote_addr;
  }
  location ~ \.(html|css|js)$ {
  proxy_pass http://zrlog_static;
   proxy_set_header Host $host;
   proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
   proxy_set_header X-Real_Ip $remote_addr;
  }

}

windows hosts解析

10.0.0.3 zrlog.song.com

浏览器访问

静态资源访问web04

动态资源访问web03

相关推荐
巨人张2 小时前
C++零基础游戏----“大鱼吃小鱼”
java·c++·游戏
伯明翰java2 小时前
Java接口
java·开发语言
云和数据.ChenGuang2 小时前
Java装箱与拆箱(面试核心解析)
java·开发语言·面试
SimonKing2 小时前
MyBatis的隐形炸弹:selectByExampleWithBLOBs使用不当,让性能下降80%
java·后端·程序员
海南java第二人2 小时前
打破Java双亲委派模型的三大核心场景与技术实现
java·spring
天天摸鱼的java工程师2 小时前
分布式 ID 生成终极方案:雪花算法优化与高可用实现
java·后端
沛沛老爹2 小时前
2025年java总结:缝缝补补又一年?
java·开发语言·人工智能·python·guava·总结·web转型ai
艾迪的技术之路2 小时前
【实践】2025年线上问题解决与总结-3
java
雨中飘荡的记忆2 小时前
MyBatis参数处理模块详解
java·mybatis