Appearance
JVM vs JRE vs JDK 的 区别
JVM(Java Virtual Machine)
- 提供了 Java 程序运行的虚拟环境,实现“一次编译,到处运行”。
- 只要环境支持 JVM,就能运行 Java 程序,但同时也会消耗较多系统内存,容易引起内存不足(OOM)。
JRE(Java Runtime Environment)
- 包含 JVM 以及 Java 程序运行所必需的库和依赖,是 Java 应用的运行环境。
JDK(Java Development Kit)
- 包含 JRE 和开发工具(如编译器、调试工具等),用于 Java 程序的开发和排查问题。
配置JDK和tomcat
shell
#安装JDK
rpm -ivh jdk-8u351-linux-x64.rpm
java -version
#解压apache-tomcat的tar包 到/app/tools/
mkdir -p /app/tools/
tar -xf apache-tomcat-9.0.52.tar.gz -C /app/tools/
#当升级 Tomcat 到新版本时,新版本通常会安装在一个带有版本号的目录中,比如 /app/tools/apache-tomcat-9.0.52/。
#如果所有相关配置、脚本和服务引用的是固定的软链接路径(如 /app/tools/tomcat),
#只需要修改软链接的目标指向新版本目录,就能快速切换,无需逐一修改各处引用。
ln -s /app/tools/apache-tomcat-9.0.52/ /app/tools/tomcat
cd /app/tools/
ll
#检查 Tomcat 版本信息,同时确认 JDK 部署正确。
/app/tools/tomcat/bin/version.sh
#启动:bin/startup.sh 或 catalina.sh start
#停止:bin/shutdown.sh 或 catalina.sh stop
/app/tools/tomcat/bin/startup.sh
#查看端口
ss -lntup | grep java
#查看 Java 进程
ps -ef | grep java
java -version
tmocat目录
目录 | 文件 | 说明 |
---|---|---|
bin | tomcat的管理脚本. catalina.sh 做jvm优化 startup.sh shutdown.sh | 用于启动、关闭Tomcat以及进行JVM优化等相关操作 |
conf | server.xml 主要配置文件 logging.properties 日志功能配置文件 | 包含Tomcat的主要配置以及日志相关的配置 |
lib | tomcat依赖的目录,一般是.jar结尾. | 存放Tomcat运行所依赖的JAR包 |
logs | 日志 catalina.out 应用日志,业务日志. accessxxxlog访问日志 | 记录Tomcat运行过程中的各种日志信息,包括应用日志、业务日志和访问日志等,查看时一般关注业务/应用日志中的关键词如error、failed、exception等 |
webapps | 站点目录 | 用于部署Web应用程序 |
work | 加载jvm中的文件信息. | 存放Tomcat在运行时加载到JVM中的文件相关信息 |
systemctl配置
shell
pkil java
ps -ef | grep java
ss -lntup | grep java
vim /usr/lib/systemd/system/tomcat.service
###########################
[Unit]
Description=Tomcat java web container #描述服务(如“Tomcat java web container”)。
After=network.target #确保网络服务启动后再启动 Tomcat。
[Service]
Type=forking #表示该服务采用 fork 模式启动(启动脚本会创建子进程)。
#EnvironmentFile=/etc/sysconfig/tomcat
ExecStart=/app/tools/tomcat/bin/startup.sh#分别指向 Tomcat 的启动和关闭脚本。
ExecStop=/app/tools/tomcat/bin/shutdown.sh#指定服务在哪个运行级别下自动启动。
[Install]
WantedBy=multi-user.target
################################
#重新加载systemctl 配置
systemctl daemon-reload tomcat
#然后systemctl 管理tomcat开机自启动与启动服务
systemctl enable --now tomcat
Java 业务部署流程
完整部署流程
- 开发到部署的基本流程:
- 开发源代码
- 编译打包:将源代码编译后打成 war 包或 jar 包。
- 部署:
- war 包:通常部署到 Tomcat 中,由 Tomcat 解析和运行。
- jar 包:可直接使用
java -jar xxx.jar
运行,其中 jar 内部可能已经集成了嵌入式容器(如 Tomcat 或 Jetty)。
- 系统服务管理
- 在部署完成后,通过 systemctl 对 Tomcat 或 Java 服务进行管理,实现自动重启、开机自启等功能。
jar包部署
shell
#查看日志
cat /app/tools/tomcat/logs/catalina.out
#前台运行
java -jar -Dfile.encoding=UTF-8 nginxWebUI-3.4.0.jar --server.port=8848 --project.home=/app/code/ngx/
#后台运行
nohup java -jar -Dfile.encoding=UTF-8 nginxWebUI-3.4.0.jar --server.port=8848 --project.home=/app/code/ngx/ &
1. nohup
作用:nohup 命令用于在 Linux/Unix 系统中运行一个进程,使其不受挂起(hangup)信号的影响,即使你退出终端,该进程仍会继续运行。
用途:常用于需要长时间运行、后台执行的任务。
2. java -jar
作用:java -jar 命令用来启动一个 Java 应用程序,该程序以 JAR(Java ARchive)文件的形式打包。
说明:在这里,nginxWebUI-3.4.0.jar 是待执行的 JAR 文件,代表一个特定版本(3.4.0)的 Nginx WebUI 应用。
3. -Dfile.encoding=UTF-8
作用:这是一个 JVM 参数,用来设置 Java 程序的默认字符编码为 UTF-8。
原因:设置为 UTF-8 可保证程序在处理文本(尤其是中文)时不会出现编码问题,从而避免乱码现象。
4. 参数说明:--server.port=8848 和 --project.home=/app/code/ngx/
--server.port=8848:
作用:指定应用程序启动时所监听的服务器端口为 8848。也就是说,程序启动后会在此端口上提供服务。
--project.home=/app/code/ngx/:
作用:设定程序运行时的项目根目录或配置目录为 /app/code/ngx/。这个参数通常用于让程序知道在哪个目录下查找配置文件、日志或其他资源。
5. & (后台运行)
作用:在命令末尾添加 &,表示将该命令放入后台运行,这样终端就不会被该进程占用,可以继续执行其他命令。
部署简单的应用
- 创建zrlog库,添加zrlog用户并配置密码.
- zrlog.war放在tomcat webapps目录下.
- 数据库
shell
#数据库处理
[root@db01 ~]# mysql -u root -p
MariaDB [(none)]> create database zrlog
Query OK, 0 rows affected (0.001 sec)
MariaDB [(none)]> GRANT ALL ON zrlog.* TO 'zrlog'@'172.16.1.%' IDENTIFIED BY 'lidao';
Query OK, 0 rows affected (0.001 sec)
MariaDB [(none)]> GRANT ALL ON zrlog.* TO 'zrlog'@'localhost' IDENTIFIED BY 'lidao';
Query OK, 0 rows affected (0.000 sec)
MariaDB [(none)]> exit
--将 应用部署为 Tomcat 的默认(ROOT)站点
shell
#移动 war 文件到 webapps 目录
mv zrlog.war /app/tools/tomcat/webapps/
systemctl stop tomcat
rm -rf ROOT
#zrlog成ROOT目录,解压后的 zrlog 应用目录被重命名为 ROOT,
#这样 Tomcat 将其作为默认站点处理(即通过直接访问服务器 IP 或域名时,会访问这个应用)。
mv zrlog ROOT
#重启 Tomcat 后,Tomcat 会以 ROOT 为上下文路径部署该应用。
mv zrlog.war ROOT.war
systemctl start tomcat
--- nginx 与 Tomcat 实现动静分离
通过 nginx 作为前端反向代理,将请求转发到 Tomcat 上,从而实现负载均衡、静态资源缓存等
接入NGINX方便对静态资源做处理
shell
#配置 Nginx 软件仓库
[root@web01 ~]# cat /etc/yum.repos.d/ngx.repo
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/7/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true
[root@web01 ~]# yum -y install nginx
#修改default.conf
#default_server:表示当前 server 块是 默认的虚拟主机。
#当客户端请求的域名或 IP 地址与所有 server_name 都不匹配时,
#Nginx 会使用该 default_server 来处理请求。
[root@web03 ~]# cat /etc/nginx/conf.d/zrlog.oldblinux.cn.conf
server {
listen 80;
server_name zrlog.oldboylinux.cn;
#accesslog
#eccorlog
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $http_host;
proxy_set_header X-Fordwarded-for $proxy_add_x_forwarded_for;
proxy_set_header X-Real-Ip $remote_addr;
}
location ~* \.(html|css|js|jpg|png|jpeg)$ {
root /app/tools/tomcat/webapps/ROOT/;
expires 7d;
}
}
#Tomcat有权限问题,目录755,文件644如果文件名中可能包含空格或特殊字符
#使用 -print0 和 xargs -0 来确保正确处理文件名:
{root@web03 ~]# find /app/tools/tomcat/webapps/ -type f -print0 | xargs -0 chmod 644 --
[root@web03 ~]# find /app/tools/tomcat/webapps/ -type d -print0 | xargs -0 chmod 755 --
或者
#find /app/tools/tomcat/webapps/ -type f -exec chmod 644 {} \;
#find /app/tools/tomcat/webapps/ -type f -exec chmod 644 {} \;
#检测配置文件
nginx -t
#windows host解析
tomcat vs nginx对比
tomcat vs nginx对比 | tomcat | nginx |
---|---|---|
web端口 | Connector=8080 | listen 80/443 |
站点/虚拟主机 | <Host></Host> 部分 | server{}部分 |
域名 | name="localhost" | server_name |
站点目录 | appBase="webapps" | root |
自动解压(war包解压目录) zip压缩包 | unpackWARs="true" | 无 |
自动部署(加载jvm) | autoDeploy="true" | 无 |
Tomcat 配置文件-访问日志格式
访问日志格式项 | 说明 | Tomcat对应配置项 |
---|---|---|
客户端ip地址 | 记录访问客户端的IP地址 | %h |
访问的时间 | 记录请求访问的时间 | %t |
请求起始行(请求方法,URI) | 包含请求的方法(如GET、POST等)和请求的URI | %r |
状态码 | 记录服务器响应的状态码(如200、404等) | %s |
大小 | 记录响应内容的大小(以字节为单位) | %b |
从哪里跳转来的(用户如何访问网站) | 记录请求的来源引用地址 | %{Referer}i |
客户端类型,浏览器 | 记录客户端使用的浏览器类型等信息 | %{User-Agent}i |
XFF头记录 | 记录X-Forwarded-For头信息,用于获取客户端真实IP(在经过代理时) | %{X-Forwarded-For}i |
shell
tar -xf apache-tomcat-9.0.52.tar.gz
cp -r apache-tomcat-9.0.52 tomcat_8081
cp -r apache-tomcat-9.0.52 tomcat_8082
sed -i 's/8080/8081/g' tomcat_8081/conf/server.xml
sed -i 's/8080/8082/g' tomcat_8082/conf/server.xml
sed -i 's/8085/8086/g' tomcat_8081/conf/server.xml
sed -i 's/8085/8087/g' tomcat_8082/conf/server.xml
echo 8081tomcat > tomcat_8081/webapps/ROOT/index.jsp
echo 8082tomcat > tomcat_8082/webapps/ROOT/index.jsp
mv tomcat_808* /app/tools/
cd /app/tools/
cd tomcat_8081
cd bin/
./startup.sh
/app/tools/tomcat_8082/bin
./startup.sh
[root@web03 /app/tools/tomcat_8082/bin]# curl http://10.0.0.9:8081/index.jsp
8081tomcat
[root@web03 /app/tools/tomcat_8082/bin]# curl http://10.0.0.9:8082/index.jsp
8082tomcat
Java 进程和线程监控命令
查看 Java 进程信息:
- `ps`: 查看所有进程
- `jps -lvm`: 列出所有 Java 进程及其详细信息
- `jstack <PID>`: 查看进程的线程信息
进程和线程基本概念:
- 进程:是正在运行的程序实例,具有独立的内存空间、资源(文件描述符、网络连接等)和执行环境。进程间相互隔离。
- 线程:是进程内的最小执行单元,同一进程内的线程共享内存和资源。多线程提高资源利用率,但要注意线程安全问题。
查看线程状态:
- `jstack <PID> | grep -i thread.state`: 查看线程的状态,如 `RUNNABLE`, `WAITING`, `TIMED_WAITING`。
- `jstack <PID> | grep -i thread.state | awk '{print $2}'`: 提取线程的状态。
- `top -H -p <PID>`: 查看进程内的线程。
- `ps aux` 或 `ps -efL`: 列出进程和线程。
shell
[root@web03 /app/tools/tomcat_8082/bin]# jstack 4637| grep -i thread.state
java.lang.Thread.State: RUNNABLE
java.lang.Thread.State: TIMED_WAITING (sleeping)
java.lang.Thread.State: WAITING (parking)
java.lang.Thread.State: RUNNABLE
java.lang.Thread.State: TIMED_WAITING (parking)
java.lang.Thread.State: TIMED_WAITING (sleeping)
java.lang.Thread.State: TIMED_WAITING (parking)
java.lang.Thread.State: TIMED_WAITING (on object monitor)
java.lang.Thread.State: WAITING (on object monitor)
java.lang.Thread.State: TIMED_WAITING (on object monitor)
java.lang.Thread.State: WAITING (parking)
java.lang.Thread.State: TIMED_WAITING (parking)
java.lang.Thread.State: WAITING (on object monitor)
java.lang.Thread.State: RUNNABLE
线程状态解释:
- `NEW`: 线程已创建但尚未启动。
- `RUNNABLE`: 线程正在运行或准备运行。
- `BLOCKED`: 线程被阻塞,等待监视器锁。
- `WAITING`: 线程无限期等待。
- `TIMED_WAITING`: 线程在指定时间内等待。
- `TERMINATED`: 线程执行完毕,已终止。
状态 | 描述 |
---|---|
NEW | 线程已创建但尚未启动(未调用start()方法)。 |
RUNNABLE | 线程正在运行或准备运行,等待CPU调度。 |
BLOCKED | 线程被阻塞,等待获取监视器锁(例如,进入同步块或方法)。 |
WAITING | 线程无限期等待,直到被其他线程显式唤醒(例如,调用object.wait())。 |
TIMED_WAITING | 线程在指定时间内等待(例如,调用Thread.sleep()或object.wait(timeout))。 |
TERMINATED | 线程已执行完毕,终止状态。 |
内存和堆转储:
- `jmap -heap <PID>`: 查看堆内存情况。
- `jmap -dump:format=b,file=<file_path> <PID>`: 将堆内存转储到文件。
shell
jmap -heap 803
jmap -dump:format=b,file=/root/test.hprof 803
使用 MAT(Memory Analyzer Tool)分析堆内存转储。
mat #windows 桌面
Java 负载排查流程
- 查看系统负载:
uptime
或top
: 检查系统负载情况,查看 load average。- 高 load average:可能表示 CPU 或 I/O 瓶颈。
- 检查 CPU 使用情况:
top -o %CPU
: 查看 CPU 使用率。htop
: 更直观地查看系统状态(需安装)。- 关注 %CPU 高的进程 和 wa(I/O 等待)高的情况。
- 检查内存使用情况:
free -h
: 查看内存使用情况,注意 available 是否低。swapon -s
: 查看 swap 使用情况。
- 检查磁盘 I/O:
iostat -x 1
: 查看磁盘 I/O 使用情况,关注await
和%util
。iotop
: 实时查看 I/O 占用高的进程。
- 检查网络:
iftop -nP
或nload
: 查看网络流量。ss -s
: 查看网络连接统计。
进程分析
- 判断进程做什么:
ps aux | grep <PID>
: 查看进程信息。top -p <PID>
: 查看特定进程的 CPU 使用情况。- 查看进程文件句柄:
ls /proc/<PID>/fd/
。 - 查看进程命令行参数:
cat /proc/<PID>/cmdline
。 - 查看进程使用的库:
ldd /proc/<PID>/exe
。 - 查看进程调用的系统资源:
strace -p <PID>
(如果有大量open
或read/write
,表示进程在读写文件)。 - 查看进程的网络连接:
ss -ntp | grep <PID>
。
- 判断进程的文件写入:
- 使用
lsof -p <PID>
:列出进程打开的所有文件。 - 监控进程的文件写入:
strace -p <PID> -e write
。 - 使用
iotop
结合lsof
:先用iotop
发现高 I/O 的进程,再用lsof
查找它打开的文件。
- 使用
Java 负载均衡排查
- IO 定位:
ps aux | grep tomcat
: 查找 Tomcat 进程。cat /proc/<PID>/io
: 查看进程的 I/O 使用情况。lsof -p <PID>
: 查看进程打开的文件。iotop -o -P
: 查看进程的 I/O 使用情况。ll /proc/<PID>/fd
: 查看进程打开的文件句柄。
- strace 排查:
strace -p <PID>
:跟踪进程系统调用,帮助判断进程正在执行什么操作。
Tomcat 配置 https
shell
mkdir -p /app/tools/tomcat/cert/
unzip 17542969_ssl.oldboylinux.cn_tomcat.zip
#修改server.xml
vim server.xml
<Connector port="8443"
protocol="HTTP/1.1"
SSLEnabled="true"
scheme="https"
secure="true"
keystoreFile="/app/tools/tomcat/cert/ssl.oldboylinux.cn.pfx"
keystoreType="PKCS12"
keystorePass="3kw46im6"
clientAuth="false"
SSLProtocol="TLSv1.1+TLSv1.2+TLSv1.3"
ciphers="TLS_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_256_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_RSA_WITH_AES_256_CBC_SHA256"/>
systemctl restart tomcat
vim /etc/hosts
curl -Lv https://ssl.oldboylinux.cn:8443/admin/login
curl https://10.0.0.9:8443
部署 Zrlog 集群模式,实现动静分离
角色/功能描述 | 详细信息/说明 |
---|---|
lb负载均衡 | keepalived |
Web服务器 | web03, web04 |
数据库服务器 | db |
存储目录 | attached目录 |
备份 | backup |
部署 Zrlog
shell
# 在 web01 上下载并上传 Zrlog WAR 包至指定目录
# 1. 创建 /zrlog 目录用于存放 WAR 包
mkdir /zrlog
# 2. 进入该目录
cd /zrlog/
# 3. 下载 Zrlog WAR 包
wget https://dl.zrlog.com/release/zrlog.war
# 4. 重命名下载的 WAR 包为 ROOT.war(Tomcat 默认部署文件名)
mv zrlog.war ROOT.war
# 5. 重启 Tomcat 应用以自动部署 ROOT.war 包
/soft/tomcat/bin/shutdown.sh
/soft/tomcat/bin/startup.sh
# 6. 检查 Tomcat 启动日志,确认 Zrlog 部署是否成功
tail -f /soft/tomcat/logs/catalina.out
# 7. 修改 Windows 的 hosts 文件,添加解析
# 编辑 C:\Windows\System32\drivers\etc\hosts,添加如下内容:
# 10.0.0.7 zrlog.oldboy.com
# 8. 解压 WAR 包(如果需要)到 /zrlog 目录下
# 例如:
# unzip /zrlog/ROOT.war -d /zrlog/
# 配置远程数据库连接
# 9. 创建 Zrlog 数据库并授权远程访问(在 MariaDB 中执行)
MariaDB [(none)]> create database zrlog charset utf8;
# 10. 创建用户并授权远程访问(确保 MySQL 远程连接已授权)
MariaDB [(none)]> grant all privileges on *.* to 'lzy'@'%' identified by 'lzy123.com';
# 11. 访问 Zrlog 站点:通过浏览器访问 zrlog.oldboy.com
前后端分离
shell
# 创建后台和前端的文件夹
[root@web03 ~]# mkdir -p /app/code/exam/{backend,fronend}
# 解压并移动前端文件到正确目录
[root@web03 ~]# unzip exam-web-前端.zip
[root@web03 ~/exam-web-前端]# mv admin/ student/ /app/code/exam/fronend/
# 启动 Spring Boot 应用,设置时区和使用生产环境配置文件
[root@web03 ~]# java -Duser.timezone=Asia/Shanghai -jar -Dspring.profiles.active=prod xzs-3.9.0.jar
# 查看日志,确认应用是否启动
[root@web03 /app/code/exam/backend]# cat xzs.20250312.log
# 配置 Nginx 服务,使得前端和后端请求可以通过域名访问
[root@web03 /etc/nginx/conf.d]# cat /etc/nginx/conf.d/exam.conf
server {
listen 80;
server_name admin.oldboylinux.cn;
root /app/code/exam/front/admin/;
location / {
index index.html;
}
location /api/ {
proxy_pass http://localhost:8000;
}
}
server {
listen 80;
server_name stu.oldboylinux.cn;
root /app/code/exam/front/student/;
location / {
index index.html;
}
location /api/ {
proxy_pass http://localhost:8000;
}
}
# 测试 Nginx 配置文件的语法是否正确
[root@web03 /app/code/exam]# nginx -t
# 重启 Nginx 使配置生效
[root@web03 /app/code/exam]# systemctl restart nginx
配置负载均衡
shell
# 定义负载均衡池 zrlog_pools,其中包括两个后端服务器 10.0.0.9 和 10.0.0.10
# 负载均衡会将流量轮流分发到这两个服务器上
upstream zrlog_pools {
server 10.0.0.9:80; # 后端服务器 1
server 10.0.0.10:80; # 后端服务器 2
}
server {
listen 80; # 监听 80 端口,即 HTTP 请求
server_name zrlog.oldboylinux.cn; # 设置服务器域名,用于接收域名 zrlog.oldboylinux.cn 的请求
# 以下两行可以用于启用错误日志和访问日志
# error_log /var/log/nginx/error.log;
# access_log /var/log/nginx/access.log;
location / {
# 将所有请求转发给 upstream zrlog_pools 配置的后端服务器
proxy_pass http://zrlog_pools;
# 设置请求头,以确保后端服务器能够获取到客户端的真实信息
proxy_set_header Host $http_host; # 设置 Host 头,确保后端获取到原始请求的域名
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 将客户端的真实 IP 地址传递给后端服务器(可能经过负载均衡器时)
proxy_set_header X-Real-Ip $remote_addr; # 设置 X-Real-Ip 头,传递客户端的真实 IP 地址
# 注意:如果你需要在访问日志中显示客户端的真实 IP 地址,
# 你需要修改 Nginx 的 log_format 配置,增加 `$http_x_real_ip` 变量
}
}
配置 NFS
shell
# 在 nfs01 上配置 NFS 服务
# 1. 配置 NFS 共享目录
# 编辑 /etc/exports 文件,指定共享目录及访问权限
echo "/nfs/blog/ 172.16.1.0/24(rw,all_squash,anonuid=1999,anongid=1999)" >> /etc/exports
# 2. 重启 NFS 服务
systemctl restart nfs
# 3. 检查共享状态,确认配置成功
cat /var/lib/nfs/etab
# 4. 设置共享目录的权限,确保 Web 服务器能够访问
chown -R nobody.nobody /nfs/zrlog/
# 在 web03 和 web04 上挂载 NFS 共享目录
# 5. 挂载 NFS 共享目录到 Tomcat 的 attached 目录
mount -t nfs nfs01:/nfs/zrlog/ /app/tools/tomcat/webapps/ROOT/attached
# 6. 验证挂载成功,查看挂载的文件系统
df -Th
# 7. 将静态文件移入挂载目录,确保所有服务器都能访问
mv attached-bak/* attached/
rm -rf attached-bak/
# 8. 配置永久挂载,修改 /etc/fstab 文件确保系统重启后挂载
echo "nfs01:/nfs/zrlog/ /app/tools/tomcat/webapps/ROOT/attached nfs defaults 0 0" >> /etc/fstab
# 9. 重启 Web 服务器后,挂载将自动生效。也可以手动挂载:
# mount -a