Loading

配置Tomcat多实例、动静分离、监控、Session会话保持(三)

14. 配置多实例Tomcat

复制多份Tomcat并重新命名目录

[root@web01 ~]# cd /server/soft/
[root@web01 soft]# ll
total 188248
-rw-r--r-- 1 root root  11524133 Mar 27 23:16 apache-tomcat-9.0.52.tar.gz
-rw-r--r-- 1 root root 181238643 Mar 27 22:53 jdk-8u60-linux-x64.tar.gz
[root@web01 soft]# tar xf apache-tomcat-9.0.52.tar.gz

[root@web01 soft]# cp -r apache-tomcat-9.0.52 /app/tools/tomcat-8081
[root@web01 soft]# cp -r apache-tomcat-9.0.52 /app/tools/tomcat-8082

修改配置文件(端口信息)

[root@web01 soft]# sed -i "s#8080#8081#g" /app/tools/tomcat-8081/conf/server.xml
[root@web01 soft]# sed -i "s#8005#8006#g" /app/tools/tomcat-8081/conf/server.xml
[root@web01 soft]# sed -i "s#8080#8082#g" /app/tools/tomcat-8082/conf/server.xml
[root@web01 soft]# sed -i "s#8005#8007#g" /app/tools/tomcat-8082/conf/server.xml

书写Tomcat的systemctl配置文件,先查看现有的配置

[root@web01 soft]# cat /usr/lib/systemd/system/tomcat.service
[Unit]
Description=java tomcat service
After=network.target

[Service]
Type=forking
EnvironmentFile=/etc/sysconfig/tomcat
ExecStart=/app/tools/tomcat/bin/startup.sh
ExecStop=/app/tools/tomcat/bin/shutdown.sh
Reload=/app/tools/tomcat/bin/shutdown.sh && sleep 3 && /app/tools/tomcat/bin/startup.sh

[Install]
WantedBy=multi-user.target

复制现有的配置进行修改

[root@web01 ~]# cd /usr/lib/systemd/system/
[root@web01 system]# cp tomcat.service tomcat-8081.service
[root@web01 system]# cp tomcat.service tomcat-8082.service
[root@web01 system]# sed -i 's#/tomcat/#/tomcat-8081/#g' tomcat-8081.service
[root@web01 system]# sed -i 's#/tomcat/#/tomcat-8082/#g' tomcat-8082.service

重新加载systemd配置文件

[root@web01 ~]# systemctl daemon-reload

创建测试文件

[root@web01 ~]# echo tomcat 8081 > /app/tools/tomcat-8081/webapps/ROOT/index.jsp
[root@web01 ~]# echo tomcat 8082 > /app/tools/tomcat-8082/webapps/ROOT/index.jsp

启动服务并访问测试

[root@web01 ~]# systemctl start tomcat-8081
[root@web01 ~]# systemctl start tomcat-8082

#检查端口情况
[root@web01 ~]# ss -lntup | grep java
tcp    LISTEN     0      1        [::ffff:127.0.0.1]:8005               [::]:*                   users:(("java",pid=89689,fd=64))
tcp    LISTEN     0      1        [::ffff:127.0.0.1]:8006               [::]:*                   users:(("java",pid=103960,fd=63))
tcp    LISTEN     0      1        [::ffff:127.0.0.1]:8007               [::]:*                   users:(("java",pid=103992,fd=63))
tcp    LISTEN     0      50       [::ffff:127.0.0.1]:41513              [::]:*                   users:(("java",pid=89713,fd=19))
tcp    LISTEN     0      50       [::ffff:127.0.0.1]:21513              [::]:*                   users:(("java",pid=89713,fd=14))
tcp    LISTEN     0      100    [::]:8080               [::]:*                   users:(("java",pid=89689,fd=55))
tcp    LISTEN     0      100    [::]:8081               [::]:*                   users:(("java",pid=103960,fd=55))
tcp    LISTEN     0      100    [::]:8082               [::]:*                   users:(("java",pid=103992,fd=55))
tcp    LISTEN     0      50       [::ffff:127.0.0.1]:51513              [::]:*                   users:(("java",pid=89713,fd=13))

浏览器访问测试,OK!

image-20230329201353855


15. 动静分离

环境准备 说明
web01 nginx(处理静态)、tomcat(处理动态)
db01 存储数据信息
nfs01 暂且忽略,理应把用户上传的内容挂载到存储上

Tips:web01安装nginx、tomcat,db01安装mariadb数据库,参考之前的命令!


通过部署zrlog博客来实现动静分离,首先在web01上安装nginx、tomcat并书写好systemctl配置文件。下面下载一个java博客war包,点这!。将war上传到/app/tools/tomcat/webapps目录下。

#上传war包到指定目录,已自动解压
[root@web01 ~]# cd /app/tools/tomcat/webapps/
[root@web01 webapps]# ll
total 10988
drwxr-x--- 15 root root     4096 Mar 27 23:17 docs
drwxr-x---  7 root root       99 Mar 27 23:17 examples
drwxr-x---  6 root root       79 Mar 27 23:17 host-manager
drwxr-x---  6 root root      114 Mar 27 23:17 manager
drwxr-x---  3 root root       41 Mar 28 02:44 memtest
-rw-r--r--  1 root root      643 Mar 28 02:44 memtest.war
drwxr-x---  2 root root        6 Mar 29 09:18 ROOT
drwxr-x---  9 root root      126 Mar 29 03:56 zrlog-2.2.1-efbe9f9-release
-rw-r--r--  1 root root 11243048 Mar 29 03:54 zrlog-2.2.1-efbe9f9-release.war

#复制所有代码文件到ROOT目录下
[root@web01 webapps]# cp -r zrlog-2.2.1-efbe9f9-release/* ROOT/

#创建nginx目录
[root@web01 ~]# mkdir -p /app/code/zrlog/static

#复制所有代码文件到nginx目录下
[root@web01 ~]# cp -r /app/tools/tomcat/webapps/zrlog-2.2.1-efbe9f9-release/* /app/code/zrlog/static/

#赋予权限
[root@web01 ~]# chown -R nginx.nginx /app/code/zrlog/static/

#为什么这么做呢,因为动态代码和静态代码没有做分离,同时在nginx配置文件中root直接指tomcat的webapps/ROOT目录会直接报403错误!所以在部署这样子的项目,前期构建项目时就要进行做动静分离代码。

修改Server.xml配置文件

[root@web01 tomcat]# pwd
/app/tools/tomcat
[root@web01 tomcat]# cat conf/server.xml
<?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.AprLifecycleListener" SSLEngine="on" />
  <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
  <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
  <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />


  <Service name="Catalina">
    <Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />

    <Engine name="Catalina" defaultHost="zrlog.yinjay.com">
      <Realm className="org.apache.catalina.realm.LockOutRealm">
        <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
               resourceName="UserDatabase"/>
      </Realm>

        <Host name="zrlog.yinjay.com"  appBase="webapps" unpackWARs="true" autoDeploy="true">
        <Valve className="org.apache.catalina.valves.AccessLogValve"
               directory="logs"
               prefix="zrlog_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>
    </Engine>
  </Service>
</Server>

启动tomcat服务

systemctl start tomcat

在MariaDB数据库上进行创建zrlog数据库和创建授权用户。

create database zrlog;
grant all on zrlog.* to 'zrlog'@'172.16.1.%' identified by 'Huawei@123';
flush privileges;

书写nginx的配置文件

[root@web01 ~]# cat /etc/nginx/conf.d/zrlog.yinjay.com.conf
server {
    listen 80;
    server_name zrlog.yinjay.com;

    location / {
        proxy_pass http://10.0.0.7:8080;
        proxy_set_header Host $http_host;
    }

    location ~* \.(html|css|js|png|jpg|jpeg)$ {
        root /app/code/zrlog/static/;
        expires 30d;
    }

}

Tisp:记得在/etc/nginx/nginx.conf把server区块注释!


启动nginx服务

systemctl start nginx

宿主机进行访问zrlog.yinjay.com测试,测试看出已经动静分离进行处理。

下面是查看nginx的访问日志

image-20230331191015123


下面是查看tomcat的访问日志

image-20230331191219864


16. 监控Tomcat

通过命令获取java进程信息,jvm信息。

java管理的命令
java命令 用于启动代码,启动jar包或tomcat启动war,背后都会用java命令。
jps java ps命令,查看显示java进程。
jstack java进程和线程信息,运行状态等等。
jmap 查看jvm内存使用情况,导出jvm内存(用于故障分析)。

16.1 jps查看当前机器上已装载的jvm

[root@web01 ~]# jps -lvm

image-20230331210818777


16.2 jstack查看java进程与线程信息

jstack命令主要用来查看Java线程的调用堆栈的,可以用来分析线程问题(如死锁)。

用法:jstack java进程的pid(可通过jps -lvm获取,下面就取上面已经得出来的pid)

[root@web01 ~]# jstack 112379
2023-03-31 08:56:49
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.60-b23 mixed mode):

-----------(忽略大部分输出)------------
#更多的是关注下面的线程状态
"main" #1 prio=5 os_prio=0 tid=0x00007f4dd8009000 nid=0x1b6fe runnable [0x00007f4de1d8c000]
   java.lang.Thread.State: RUNNABLE #也就是这里
        at java.net.PlainSocketImpl.socketAccept(Native Method)
        at java.net.AbstractPlainSocketImpl.accept(AbstractPlainSocketImpl.java:409)
        at java.net.ServerSocket.implAccept(ServerSocket.java:545)
        at java.net.ServerSocket.accept(ServerSocket.java:513)
        at org.apache.catalina.core.StandardServer.await(StandardServer.java:602)
        at org.apache.catalina.startup.Catalina.await(Catalina.java:864)
        at org.apache.catalina.startup.Catalina.start(Catalina.java:810)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:497)
        at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:345)
        at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:476)

"VM Thread" os_prio=0 tid=0x00007f4dd806d800 nid=0x1b6ff runnable

"VM Periodic Task Thread" os_prio=0 tid=0x00007f4dd80b9000 nid=0x1b706 waiting on condition

JNI global references: 453

通常流程先查出最耗费CPU的线程

top -Hp 进程pid
[root@web01 ~]# top -Hp 112379

比如下面这条线程最耗费CPU

image-20230331210921505


先将线程pid进行转换成十六进制

[root@web01 ~]# printf "%x\n" 112429
1b72d

先将信息输出到文件,然后通过上面转换的十六进制信息进行查找。

[root@web01 ~]# jstack 112379 > info.txt

在文件中进行定位到指定位置,就能看到该线程的状态。

image-20230331211136560


值得关注的线程状态有:

死锁:Deadlock(重点关注)
② 执行中:Runnable
等待资源:Waiting on condition(重点关注)
等待获取监视器:Waiting on monitor entry(重点关注)
⑤ 暂停:Suspended
⑥ 对象等待中:Object.wait() 或 TIMED_WAITING
⑦ 阻塞:Blocked(重点关注)
⑧ 停止:Parked


16.3 jmap查看Jvm内存使用情况

jmap命令可以获得运行中的jvm的堆的快照,从而可以离线分析堆,以检查内存泄漏,检查一些严重影响性能的大对象的创建,检查系统中什么对象最多,各种对象所占内存的大小等等。

用法:jmap -heap java进程的pid

[root@web01 ~]# jmap -heap 112379
Attaching to process ID 112379, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.60-b23

using thread-local object allocation.
Mark Sweep Compact GC

Heap Configuration:
   MinHeapFreeRatio         = 40
   MaxHeapFreeRatio         = 70
   MaxHeapSize              = 478150656 (456.0MB)
   NewSize                  = 10485760 (10.0MB)
   MaxNewSize               = 159383552 (152.0MB)
   OldSize                  = 20971520 (20.0MB)
   NewRatio                 = 2
   SurvivorRatio            = 8
   MetaspaceSize            = 21807104 (20.796875MB)
   CompressedClassSpaceSize = 1073741824 (1024.0MB)
   MaxMetaspaceSize         = 17592186044415 MB
   G1HeapRegionSize         = 0 (0.0MB)

Heap Usage:
New Generation (Eden + 1 Survivor Space):
   capacity = 12451840 (11.875MB)
   used     = 3106144 (2.962249755859375MB)
   free     = 9345696 (8.912750244140625MB)
   24.945261101973685% used
Eden Space:
   capacity = 11075584 (10.5625MB)
   used     = 2096104 (1.9990005493164062MB)
   free     = 8979480 (8.563499450683594MB)
   18.925448987610945% used
From Space:
   capacity = 1376256 (1.3125MB)
   used     = 1010040 (0.9632492065429688MB)
   free     = 366216 (0.34925079345703125MB)
   73.39041573660714% used
To Space:
   capacity = 1376256 (1.3125MB)
   used     = 0 (0.0MB)
   free     = 1376256 (1.3125MB)
   0.0% used
tenured generation:
   capacity = 27480064 (26.20703125MB)
   used     = 16588880 (15.820388793945312MB)
   free     = 10891184 (10.386642456054688MB)
   60.366962755254136% used

20025 interned Strings occupying 2180064 bytes.

生成内存dump文件,未来通过专用的jvm内存分析工具,打开分析这个文件即可。

用法:jmap -dump:file=文件名.hprof, format=b java进程pid

[root@web01 ~]# jmap -dump:file=/root/test.hprof,format=b 112379
Dumping heap to /root/test.hprof ...
Heap dump file created

16.4 开启java远程监控功能

来通过各种监控工具(Zabbix/Grafana/Promethues/...),监控Tomcat/java,或者用于开发调试代码与查看Java状态。


开启流程:

  • 修改java配置(tomcat配置的catalina.sh)
  • 重启java(tomcat)
  • 监控(可从监控插件或者window下启动java工具查看)

修改tomcat/bin目录下的catalina.sh,添加下列内容。CATALINA_OPTS就是java变量修改tomcat启动的时候参数,本质就是给java命令增加些参数。

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=10.0.0.7"

jmxremote选项说明
Dcom.sun.management.jmxremote 开启远程监控功能
Dcom.sun.management.jmxremote.port=12345 指定功能的端口号:12345
Dcom.sun.management.jmxremote.authenticate=false 是否开启认证功能,关闭
Dcom.sun.management.jmxremote.ssl=false 是否开启ssl证书,关闭
Djava.rmi.server.hostname=10.0.0.7 指定本机的内网或公网ip

重启tomcat服务,然后查看端口情况

image-20230401093942207


jps -lvm查看,已经加载

image-20230401094044210


在宿主机通过jvisualvm工具进行监控(模拟zabbix监控java)

image-20230401094302747


16.5 高负载排查过程

排障流程 具体命令和方法
通过监控得知系统负载高,登录这台机器进行初步分析原因 通过监控或告警
分析cpu导致还是磁盘io导致 top命令关注下面情况
us、sy数值高为CPU导致
wa数值高为IO导致
查出对应进程出现异常(此处指java导致时) CPU导致可在top信息中看CPU利用率高的对应进程PID
IO导致可以用iotop -P命令看最高IO读写的进程PID
查看jvm内存情况,导出jvm内存进行分析 内存情况: jmap -heap java的PID
导出jvm内存:dump:file=xxx.hprof,format=b java的PID
分析jvm内存,需要开发参与 通过内存分析工具:Memory Analyzer Tool
分析应用日志 catalina.out
分析网站日志 xxxx.log
看日志是否有异常
找出原因 解决与处理

17. Session会话共享保持

环境 说明 ip
lb01 nginx实现负载均衡 10.0.0.5、172.16.1.5
web01 web服务,tomcat 172.16.1.7
web02 web服务,tomcat 172.16.1.8
db01 数据库、redis 172.16.1.51

Tips:本实验使用不到数据库,只是在数据库的机器上部署redis!


17.1 下载插件并修改配置文件

tomcat-cluster-redis-session插件下载地址:https://github.com/ran-jit/tomcat-cluster-redis-session-manager/ 选择适合的版本下载后上传到tomcat主机上(web01、web02)


以下步骤web01、web02都进行相同的修改。

[root@web01 ~]# cd /server/soft/
[root@web01 soft]# ll
total 189148
drwxr-xr-x 9 root root       220 Mar 29 07:57 apache-tomcat-9.0.52
-rw-r--r-- 1 root root  11524133 Mar 27 23:16 apache-tomcat-9.0.52.tar.gz
-rw-r--r-- 1 root root 181238643 Mar 27 22:53 jdk-8u60-linux-x64.tar.gz
drwxr-xr-x 3 root root        96 Mar 31 23:17 __MACOSX
drwxr-xr-x 4 root root        64 Aug 12  2019 tomcat-cluster-redis-session-manager
-rw-r--r-- 1 root root    921429 Mar 31 23:16 tomcat-cluster-redis-session-manager.zip

[root@web01 soft]# tree tomcat-cluster-redis-session-manager
tomcat-cluster-redis-session-manager
├── conf
│   └── redis-data-cache.properties   #连接redis的配置文件
├── lib                               #依赖,tomcat-redis-session管理插件
│   ├── commons-pool2-2.6.2.jar
│   ├── jedis-3.0.1.jar
│   ├── slf4j-api-1.7.26.jar
│   └── tomcat-cluster-redis-session-manager-4.0.jar
└── readMe.txt

2 directories, 6 files

复制jar包到tomcat的lib目录中,复制配置文件到tomcat的conf目录中。

[root@web01 soft]# cp tomcat-cluster-redis-session-manager/lib/*.jar /app/tools/tomcat/lib/
[root@web01 soft]# cp tomcat-cluster-redis-session-manager/conf/redis-data-cache.properties /app/tools/tomcat/conf/

修改配置文件

[root@web01 ~]# vim /app/tools/tomcat/conf/redis-data-cache.properties
redis.hosts=172.16.1.51:6379

[root@web01 ~]# vim /app/tools/tomcat/conf/context.xml
<?xml version="1.0" encoding="UTF-8"?>
<Context>
    <WatchedResource>WEB-INF/web.xml</WatchedResource>
    <WatchedResource>WEB-INF/tomcat-web.xml</WatchedResource>
    <WatchedResource>${catalina.base}/conf/web.xml</WatchedResource>
    
    #在Context里面增添下列两行
    <Valve className="tomcat.request.session.redis.SessionHandlerValve" />
    <Manager className="tomcat.request.session.redis.SessionManager" />
</Context>

17.2 安装redis并修改配置

db01下进行

yum install -y redis

更改redis服务监听地址

[root@db01 ~]# grep -n '^bind' /etc/redis.conf
61:bind 127.0.0.1
[root@db01 ~]# sed -i '61s/127.0.0.1/172.16.1.51/' /etc/redis.conf
[root@db01 ~]# grep -n '^bind' /etc/redis.conf
61:bind 172.16.1.51

启动redis服务并设置开机自启

[root@db01 ~]# systemctl start redis
[root@db01 ~]# systemctl enable redis
Created symlink from /etc/systemd/system/multi-user.target.wants/redis.service to /usr/lib/systemd/system/redis.service.

检查服务状态

[root@db01 ~]# ps -ef |grep redis
redis     75726      1  0 23:43 ?        00:00:00 /usr/bin/redis-server 172.16.1.51:6379
root      75730  74049  0 23:43 pts/2    00:00:00 grep --color=auto redis

查询redis中的数据,目前为空

[root@db01 ~]# redis-cli -h 172.16.1.51
172.16.1.51:6379> keys *
(empty list or set)
172.16.1.51:6379>

17.3 书写测试文件并重启服务访问

web01书写测试文件

[root@web01 ~]# cat /app/tools/tomcat/webapps/ROOT/session.jsp
<body>
<%
System.out.println(session.getCreationTime());
out.println("<br> web01.yinjay.com SESSIONID:" + session.getId() + "<br>");
out.println("Session created  time is :" + session.getCreationTime()+ "<br>");
%>
</body>

web02书写测试文件

[root@web02 ~]# cat /app/tools/tomcat/webapps/ROOT/session.jsp
<body>
<%
System.out.println(session.getCreationTime());
out.println("<br> web02.yinjay.com SESSIONID:" + session.getId() + "<br>");
out.println("Session created  time is :" + session.getCreationTime()+ "<br>");
%>
</body>

web01、web02重启服务

systemctl restart tomcat

进行单独访问测试,redis查询到各自的session。

image-20230401115230190


17.4 接入负载均衡

在lb01上进行修改配置文件并重新加载配置。

[root@lb01 ~]# cat /etc/nginx/conf.d/lb01.conf
upstream tomcat_pools {
   server 172.16.1.7:8080;
   server 172.16.1.8:8080;

}

server {
   listen 80;
   server_name tomcat.yinjay.com;

   location / {
       proxy_pass http://tomcat_pools;
       proxy_set_header X-Forwarded-For $remote_addr;
       proxy_set_header Host $http_host;
   }

}

[root@lb01 ~]# systemctl reload nginx

在宿主机添加host记录10.0.0.5 tomcat.yinjay.com后并进行浏览器访问。第一次负载到web01,第二次负载到web02,然后进行查询redis都是同一个session,实现会话共享保持!

image-20230401120412053

image-20230401120432506


posted @ 2023-09-17 10:31  YinJayChen  阅读(30)  评论(0编辑  收藏  举报