1、Tomcat基础部分
1.1、tomcat配置文件
/app/tools/tomcat/conf/server.xml内容:
<?xml version="1.0" encoding="UTF-8"?>
#8005端口
<Server port="8005" shutdown="SHUTDOWN">
#8005:shutdown端口,连接这个端口输入shutdown,就可以关闭tomcat
<Listener className="org.apache.catalina.startup.VersionLoggerListener" />
<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
<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>
<Service name="Catalina">
#8080端口 处理用户的http请求
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
#8443端口:用于处理https请求
<!--
<Connector protocol="AJP/1.3"
address="::1"
port="8009"
redirectPort="8443" />
-->
#engine部分,指定默认的虚拟主机,defaultHost名称要与Host的name一致
<Engine name="Catalina" defaultHost="localhost">
<Realm className="org.apache.catalina.realm.LockOutRealm">
<Realm className="org.apache.catalina.realm.UserDatabaseRealm"
resourceName="UserDatabase"/>
</Realm>
#Host部分,虚拟主机的配置,name:域名
<Host name="localhost" appBase="webapps" #站点目录,相对路径
unpackWARs="true" autoDeploy="true"> #自动解压,自动部署
#配置访问日志
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="localhost_access_log" suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" />
</Host>
</Engine>
</Service>
</Server>
tomcat与nginx虚拟主机对比
虚拟主机对比 | tomcat | nginx |
---|---|---|
虚拟主机 | Host部分 | server{} |
域名 | name=”域名” | server_name 域名; |
端口 | Connector部分 port=”8080″ | listen 80; |
站点目录 | appBase=”webapps” | root /app/code/blog; |
自动解压 | unpackWARs=”true” | 无 |
自动部署 | autoDeploy=”true”,即加载到jvm中 | 无 |
日志记录 | <Valve部分 日志记录 directory=”logs” 后半部分suffix=”.txt” | access_log /var/log/nginx/access.log main; |
日志格式 | <Valve部分 patten=”%h %l %u %t “%r” %s %b” | log_format main …… |
1.2、规范tomcat访问日志格式
说明 | tomcat | nginx |
---|---|---|
定义访问日志的格式 | Host部分的patten定义 | http区域log_format部分 |
客户端ip | %h | $remote_addr |
访问时间 | %t | $local_time |
请求起始行(请求方法,URI) | %r | $request |
状态码 | %s | $status |
大小 | %b | $body_bytes_sent |
从哪里跳转来的(用户如何访问网站) | %{Referer}i | $http_referer |
客户端类型,浏览器 | %{User-Agent}i | $http_user_agent |
XFF头记录 | %{X-Forwarded-For}i | $http_x_forwarded_for |
注意:
" 表示双引号
日志格式:
pattern="%h %l %u %t "%r" %s %b "%{Referer}i ""%{User-Agent}i""%{X-Forwarded-For}i"" />
1.3、tomcat与用户请求
虚拟主机部分:
<Engine name="Catalina" defaultHost="localhost">
<Realm className="org.apache.catalina.realm.LockOutRealm">
<Realm className="org.apache.catalina.realm.UserDatabaseRealm"
resourceName="UserDatabase"/>
</Realm>
#Host部分,虚拟主机的配置,name:域名
<Host name="localhost" appBase="webapps" #站点目录,相对路径
unpackWARs="true" autoDeploy="true"> #自动解压,自动部署
#配置访问日志
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="localhost_access_log" suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" />
</Host>
</Engine>
处理用户请求流程:
1、请求与8080端口连接
2、域名与Host部分的name进行匹配
a)匹配成功,则使用对应的虚拟主机
b)匹配失败,则使用Engine部分defaultHost指定的默认的虚拟主机进行处理
注意:
tomcat可以处理静态与动态请求
处理静态请求的效率较低,擅长动态
因此,静态的可以交给nginx
2、部署zrlog应用
zrlog:开源的java程序编写的博客程序
2.1、web端
在web01上部署,web01:192.168.10.7
a)下载zrlog代码
[root@web01 ~]#curl -o zrlog.war https://dl.zrlog.com/release/zrlog-2.2.1-efbe9f9-release.war?attname=ROOT.war&ref=index
b)部署代码包
直接把zrlog.war复制到webapps目录中
[root@web01 ~]#cp zrlog.war /app/tools/tomcat/webapps/
但浏览器访问的时候要加上zrlog。因此:
备份webapps目录中的ROOT目录
把zrlog.war包改名为ROOT.war到tomcat的webapps目录中
[root@web01 ~]#mv /app/tools/tomcat/webapps/ROOT{,.bak}
[root@web01 ~]#mv zrlog.war ROOT.war
[root@web01 ~]#cp ROOT.war /app/tools/tomcat/webapps/
结果如下:

但是,这样操作的话,访问tomcat默认的站点得加上ROOT.bak,如下:
浏览器打开:http://192.168.10.7:8080/ROOT.bak/

2.2、数据库端
数据库服务器:db01:192.168.10.5、172.16.1.51
创建名为zrlog的数据库,用户名:zrlog,密码:12345,白名单:172.16.1.%
[root@db01 ~]#mysql -uroot -p
MariaDB [(none)]> create database zrlog;
MariaDB [(none)]> grant all on zrlog.* to 'zrlog'@'172.16.1.%' identified by '12345';
MariaDB [(none)]> grant all on zrlog.* to 'zrlog'@'localhost' identified by '12345';
MariaDB [(none)]> flush privileges;
2.3、安装zrlog
浏览器打开:192.168.10.7:8080
如下:

填写相关信息,点击下一步,如下:

填写相关信息,点击下一步:

点击完成或点击查看,即可

3、nginx与tomcat
通过nginx的80端口转发到tomcat的8080
web01端提前yum安装好nginx
配置文件:
[root@web01 ~]#vim /etc/nginx/conf.d/zrlog.test.com.conf
server {
listen 80;
server_name zrlog.test.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 $http_host;
proxy_set_header X-Forwarded-For $http_add_x_forwared_for;
proxy_set_header X-Real-Ip $remote_addr;
}
}
重启nginx服务:
[root@web01 ~]#systemctl reload nginx
Windows本地做hosts解析
192.168.10.7 zrlog.test.com
浏览器打开: zrlog.test.com
如下:

4、动静分离
实际上,未来需要开发人员把代码拆分,把静态资源拆分出来单独存放
架构示意图:

4.1、修改zrlog站点目录的权限
由于修改nginx的运行用户为www(默认是nginx),所以修改zrlog站点目录属主属组为www:
[root@web01 ~]#chown -R www.www /app/tools/tomcat/webapps/ROOT/
4.2、配置nginx静态资源处理
zrlog站点目录:/app/tools/tomcat/webapps/ROOT/
修改nginx配置文件:配置静态资源的location规则
[root@web01 ~]#vim /etc/nginx/conf.d/zrlog.test.com.conf
server {
listen 80;
server_name zrlog.test.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 $http_host;
proxy_set_header X-Forwarded-For $http_add_x_forwared_for;
proxy_set_header X-Real-Ip $remote_addr;
}
location ~* \.(html|js|css|png|jpeg|bmp|webp)$ {
root /app/tools/tomcat/webapps/ROOT/;
expires 7d;
}
}
重启nginx,浏览器打开:http://zrlog.test.com/

403报错。权限拒绝。
查看nginx日志:
[root@web01 ~]#tail /var/log/nginx/zrlog-error.log
2023/07/08 21:25:18 [error] 11692#11692: *87075 open() "/app/tools/tomcat/webapps/ROOT/include/templates/default/js/sheshui.js" failed (13: Permission denied), client: 192.168.10.1, server: zrlog.test.com, request: "GET /include/templates/default/js/sheshui.js?t=1624781874000 HTTP/1.1", host: "zrlog.test.com"
关键词:Permission denied,权限拒绝
通过分析发现,/app/tools/tomcat/webapps/权限为750,修改为755即可
[root@web01 ~]#ll -d /app/tools/tomcat/webapps/
drwxr-x--- 9 root root 147 Jul 8 20:43 /app/tools/tomcat/webapps/
[root@web01 ~]#chmod 755 /app/tools/tomcat/webapps/
然后刷新浏览器即可。
ngx+tomcat动静分离目录权限设置问题:
前面中,是修改为www用户。建议使用以下设置权限:
[root@web01 ~]#chown -R root.root /app/tools/tomcat/
[root@web01 ~]#find /app/tools/tomcat/webapps/ -type f | xargs chmod 644
[root@web01 ~]#find /app/tools/tomcat/webapps/ -type d | xargs chmod 755
因为nginx不涉及写的问题,而tomcat是以root身份运行。
5、tomcat多实例
在同一台机子上运行多个tomcat实例
步骤:
1、多个tomcat目录
2、配置文件修改端口(默认是8080,8005)
3、启动
5.1 准备多个Tomcat
例如,再准备2个tomcat(tomcat-8081、tomcat-8082)
[root@web01 ~]#tar xf apache-tomcat-9.0.52.tar.gz
[root@web01 ~]#cp -r apache-tomcat-9.0.52 tomcat-8081
[root@web01 ~]#cp -r apache-tomcat-9.0.52 tomcat-8082
[root@web01 ~]#mv tomcat-808* /app/tools/
5.2 修改配置
tomcat-8081的端口8080改为8081,8005改成8006
tomcat-8082的端口8080改为8082,8005改为8007
[root@web01 ~]#cd /app/tools/
[root@web01 /app/tools]#sed -i 's#8080#8081#g' tomcat-8081/conf/server.xml
[root@web01 /app/tools]#sed -i 's#8005#8006#g' tomcat-8081/conf/server.xml
[root@web01 /app/tools]#sed -i 's#8005#8007#g' tomcat-8082/conf/server.xml
[root@web01 /app/tools]#sed -i 's#8080#8082#g' tomcat-8082/conf/server.xml
5.3 测试文件
[root@web01 ~]#echo "java tomcat 8081" > /app/tools/tomcat-8081/webapps/ROOT/test.jsp
[root@web01 ~]#echo "java tomcat 8082" > /app/tools/tomcat-8082/webapps/ROOT/test.jsp
5.4 手动启动tomcat
多实例无法使用systemctl启动tomcat,因此,要手动启动:
[root@web01 ~]#/app/tools/tomcat-8081/bin/startup.sh
[root@web01 ~]#/app/tools/tomcat-8082/bin/startup.sh
可以分别写systemctl配置文件使用systemctl管理8081、8082的tomcat
5.5 测试
浏览器打开:192.168.10.7:8081/test.jsp

浏览器打开:192.168.10.7:8082/test.jsp

OK,多实例tomcat运行成功
未来生成上,可以直接把tomcat+应用整体打包,使用的时候直接解压即可。
6、java远程监控功能
6.1 概述
未来通过各种监控工具(zabbix、grafana、prometheus….)监控tomcat、java
需要开启java远程监控功能(JMX remote)
6.2 步骤
Tomcat配置中修改tomcat启动的选项,开启jmx远程监控功能
交给zabbix就可以了(使用Windows jdk连接tomcat)
在catalina.sh文件中125行后面的CATALINA_OPTS 指定java启动的时候的选项
[root@web01 ~]#vim /app/tools/tomcat/bin/catalina.sh
CATALINA_OPTS="$CATALINA_OPTS \
-Dcom.sun.management.jmxremote \
-Dcom.sun.management.jmxremote.port=12345 \
-Dcom.sun.management.jmxremote.authenticate=false \
-Dcom.sun.management.jmxremote.ssl=false \
-Djava.rmi.server.hostname=192.168.10.7"
参数解析:
开启远程监控功能选项 | 说明 |
---|---|
-Dcom.sun.management.jmxremote | 开启远程监控功能 |
-Dcom.sun.management.jmxremote.port=12345 | 指定端口 |
-Dcom.sun.management.jmxremote.authenticate=false | 关闭认证功能 |
-Dcom.sun.management.jmxremote.ssl=false | 关闭ssl功能 |
-Djava.rmi.server.hostname=192.168.10.7 | 本地网卡的地址,监听的地址(根据实际修改) |
温馨提示:
从tomcat8.5开始,配置的每一行要通过\进行续行
重启tomcat
[root@web01 ~]#systemctl restart tomcat
6.3 连接tomcat
在Windows中连接tomcat
windows要安装jdk(安装过程略)

找到jdk的安装目录的bin下的jconsole.exe,双击打开:

输入192.168.10.7:12345,点连接:

点击不安全的连接即可。
此外,jvisualvm.exe也可以连接:

点击确定:

7、java故障案例
7.1 命令
1)jps
jps命令,就是java的ps命令,只显示java进程,类似于:ps -ef | grep java
[root@web01 ~]#jps -lvm | grep tomca
2)jstack
jstack查看java进程内部信息,线程信息
进程:占空间、占系统资源,类似于厂房
线程:厂房里面的工人,处理与用户的请求
需要代码使用多线程技术,通过ps aux查看进程是否支持多线程(是否使用多线程技术)
流程:
1、先过滤出java进程的pid
2、查看java进程的线程信息
jstack pid
3、查看java线程状态
jstack pid | grep -i state
例如:
#1、过滤java进程的pid
[root@web01 ~]#ps aux | grep java | awk '{print $2}'
15008
[root@web01 ~]#
#2、查看线程信息
[root@web01 ~]#jstack 15008
#3、查看线程状态
[root@web01 ~]#jstack 15008 | grep -i state
java.lang.Thread.State: RUNNABLE
java.lang.Thread.State: TIMED_WAITING (parking)
java.lang.Thread.State: WAITING (parking)
java.lang.Thread.State: RUNNABLE
java.lang.Thread.State: RUNNABLE
java.lang.Thread.State: TIMED_WAITING (parking)
java.lang.Thread.State: WAITING (parking)
....
线程状态解释:
New:新建状态
Runnable:就绪状态
Running:运行状态
Blocked:阻塞状态(io)
Dead:死亡状态
统计每种状态的个数:
[root@web01 ~]#jstack 15008 | grep -i state | sort | uniq -c
3)jmap
jmap:查看或导出jvm信息
jmap -heap java-pid 导出java进程的jvm内存使用情况,例如:
jmap -heap 15008
导出jvm内存镜像:
[root@web01 ~]#jmap -dump:format=b,file=8080.hprof 15008
Dumping heap to /root/8080.hprof ...
Heap dump file created
[root@web01 ~]#ll -h 8080.hprof
-rw------- 1 root root 30M Jul 8 23:03 8080.hprof
[root@web01 ~]#
4)mat分析工具
Windows的MemoryAnalyzer-1.8.0.20180604-win32.win32.x86_64.zip
下载地址:https://www.eclipse.org/mat/downloads.php
上面导出了8080.hprof,通过该软件进行分析:

双击打开提示:

不知道什么问题,启动不了。
8、java会话共享
会话共享方案 | 说明 | 备注 |
---|---|---|
单机 | 如果单个应用,tomcat不用考虑会话共享问题 | |
session复制功能 | tomcat进行配置后,可以把session信息复制给其他节点 | 只适用于集群节点较少的情况,比如4个节点以内 |
通过插件实现会话共享,放在redis中 | tomcat通过插件,把用户会话保存在指定的服务器中 (redis) tomcat-cluster_session-manager | 需要插件,进行配置,代码支持 |
通过代码直接指定session位置 | 修改代码与增加功能,依赖 | 需要修改代码 |
使用其他方式替换会话 | oauth认证,koken认证 | 代码级别 |
9、tomcat配置https
应用建议:
tomcat可以支持https,可以在tomcat中配置https证书
未来可以在nginx中配置证书加密,tomcat未加密
1、证书申请
略
2、Tomcat配置
server.xml配置文件,配置8443端口
[root@web01 ~]#vim /app/tools/tomcat/conf/server.xml
....
<Connector port="8443"
protocol="HTTP/1.1"
SSLEnabled="true"
scheme="https"
secure="true"
keystoreFile="/xxx/xxx.pfx" #公钥
keystoreType="PKCS12"
keystorePass="xxx" #密码,相当于私钥
clientAuth="false"
SSLProtocol="TLSv1.1+TLSv1.2+TLSv1.3"
ciphers="TLS_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_256_CBX_SHA,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA1256,TLS_RSA_WITH_AES_256_CBC_SHA256"
/>
....
浏览器访问:https://ip或域名:8443
说明:
关于tomcat其他类型的证书格式配置,jsk格式:
keystoreFile="/xxx/xxx.jks" #公钥
keystoreType="PKCS12" #删除这一行
keystorePass="xxx" #密码,
3、8080跳转8443
在web.xml的</welcome-file-list>后面添加以下内容:
<login-config>
<auth-method>CLIENT-CERT</auth-method>
<realm-name>Client Cert Users-only Area</realm-name>
</login-config>
<security-constraint>
<web-resoure-collection>
<web-resource-name>ssl</web-resource-name>
<url-pattern>/*</url-parren>
</web-resource-collection>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>