mac系统中Java项目环境配置与问题解决全记录|项目启动篇:从编译打包到生产级部署

文章目录

    • [Spring Boot 项目启动与运维完全指南](#Spring Boot 项目启动与运维完全指南)
    • [------ 从编译打包到生产级部署的全流程详解](#—— 从编译打包到生产级部署的全流程详解)
    • [📖 写在前面](#📖 写在前面)
    • [第一章:Spring Boot 应用启动全览](#第一章:Spring Boot 应用启动全览)
      • [1.1 项目结构回顾](#1.1 项目结构回顾)
      • [1.2 Spring Boot 启动原理简述](#1.2 Spring Boot 启动原理简述)
      • [1.3 可执行 JAR 包结构](#1.3 可执行 JAR 包结构)
    • [第二章:Spring Boot 启动方式详解](#第二章:Spring Boot 启动方式详解)
      • [2.1 方式一:标准启动(最常用)](#2.1 方式一:标准启动(最常用))
      • [2.2 方式二:指定配置启动](#2.2 方式二:指定配置启动)
      • [2.3 方式三:使用配置文件启动](#2.3 方式三:使用配置文件启动)
      • [2.4 方式四:后台守护启动(生产环境)](#2.4 方式四:后台守护启动(生产环境))
      • [2.5 方式五:使用系统服务(生产环境)](#2.5 方式五:使用系统服务(生产环境))
        • [创建 Systemd 服务(Linux)](#创建 Systemd 服务(Linux))
        • [创建 Launch Agent(macOS)](#创建 Launch Agent(macOS))
    • 第三章:JVM参数调优详解
      • [3.1 JVM内存模型](#3.1 JVM内存模型)
      • [3.2 关键JVM参数](#3.2 关键JVM参数)
      • [3.3 GC日志配置](#3.3 GC日志配置)
      • [3.4 完整启动脚本示例](#3.4 完整启动脚本示例)
    • 第四章:启动失败问题系统化排查
      • [4.1 排查方法论](#4.1 排查方法论)
      • [4.2 常见启动错误及解决方案](#4.2 常见启动错误及解决方案)
        • [错误 1:端口被占用](#错误 1:端口被占用)
        • [错误 2:数据库连接失败](#错误 2:数据库连接失败)
        • [错误 3:Redis连接失败](#错误 3:Redis连接失败)
        • [错误 4:OutOfMemoryError](#错误 4:OutOfMemoryError)
        • [错误 5:类找不到](#错误 5:类找不到)
      • [4.3 日志级别调整](#4.3 日志级别调整)
      • [4.4 调试模式启动](#4.4 调试模式启动)
    • 第五章:应用健康检查与监控
      • [5.1 Spring Boot Actuator 配置](#5.1 Spring Boot Actuator 配置)
      • [5.2 健康检查端点](#5.2 健康检查端点)
      • [5.3 自定义健康检查](#5.3 自定义健康检查)
      • [5.4 应用信息端点](#5.4 应用信息端点)
    • 第六章:日志管理详解
      • [6.1 Logback 配置](#6.1 Logback 配置)
      • [6.2 日志切割与归档](#6.2 日志切割与归档)
      • [6.3 日志查看与分析](#6.3 日志查看与分析)
      • [6.4 日志级别动态调整](#6.4 日志级别动态调整)
    • 第七章:性能优化与压测
    • 第八章:运维场景实战
      • [8.1 优雅关闭应用](#8.1 优雅关闭应用)
      • [8.2 应用版本回滚](#8.2 应用版本回滚)
      • [8.3 数据库迁移](#8.3 数据库迁移)
      • [8.4 应用备份与恢复](#8.4 应用备份与恢复)
      • [8.5 快速问题诊断命令集](#8.5 快速问题诊断命令集)
    • 第九章:总结与最佳实践
      • [9.1 启动运维清单](#9.1 启动运维清单)

Spring Boot 项目启动与运维完全指南

------ 从编译打包到生产级部署的全流程详解


📖 写在前面

在前两篇文章中,我们完成了:

  • 第一篇:JDK 17 + Maven 3.9.8 的环境配置
  • 第二篇:MySQL 8.0 + Redis 的安装与数据初始化

现在,所有准备工作已经就绪,是时候启动 Spring Boot 应用了。然而,java -jar 只是万里长征的第一步。应用启动过程中可能遇到各种问题:端口冲突、内存不足、配置文件错误、数据库连接池耗尽、日志配置不当......

本文将极其详细地讲解:

  1. Spring Boot 应用的多种启动方式与参数调优
  2. 启动失败问题的系统化排查方法论
  3. 应用健康检查与性能监控
  4. 生产级部署的最佳实践
  5. 常见运维场景的操作指南

第一章:Spring Boot 应用启动全览

1.1 项目结构回顾

复制代码
~/Desktop/FeiChenERP/backend/
├── pom.xml                          # Maven项目配置
├── src/
│   ├── main/
│   │   ├── java/                    # Java源代码
│   │   │   └── com/erp/
│   │   │       ├── OpenerpApplication.java  # 启动类
│   │   │       ├── controller/      # 控制器层
│   │   │       ├── service/         # 业务逻辑层
│   │   │       ├── repository/      # 数据访问层
│   │   │       └── config/          # 配置类
│   │   ├── resources/
│   │   │   ├── application.yml      # 主配置文件
│   │   │   ├── application-dev.yml  # 开发环境配置
│   │   │   ├── application-prod.yml # 生产环境配置
│   │   │   ├── static/              # 静态资源
│   │   │   └── templates/           # 模板文件
│   │   └── webapp/                  # Web资源(可选)
│   └── test/                        # 测试代码
└── target/                          # 编译输出目录
    ├── classes/                     # 编译后的class文件
    ├── openerp-backend-1.0.0.jar   # 可执行JAR包
    └── openerp-backend-1.0.0.jar.original  # 原始JAR(不含依赖)

1.2 Spring Boot 启动原理简述

Spring Boot 应用启动的核心流程:

复制代码
java -jar app.jar
         ↓
    加载 META-INF/MANIFEST.MF
         ↓
    定位 Main-Class: org.springframework.boot.loader.JarLauncher
         ↓
    JarLauncher 启动嵌入式 Tomcat
         ↓
    加载 Spring 容器配置
         ↓
    执行 AutoConfiguration(自动配置)
         ↓
    初始化 DataSource、Redis、JPA 等组件
         ↓
    执行 CommandLineRunner / ApplicationRunner
         ↓
    应用启动完成,监听端口(默认 8080)

1.3 可执行 JAR 包结构

Spring Boot 生成的 JAR 包是一个 "Fat JAR"(胖JAR),包含了所有依赖:

bash 复制代码
# 查看JAR包内容
jar tf target/openerp-backend-1.0.0.jar | head -30

# 输出结构:
# META-INF/
# META-INF/MANIFEST.MF          # 清单文件,定义启动类
# BOOT-INF/
# BOOT-INF/classes/              # 应用编译后的class文件
# BOOT-INF/lib/                  # 所有依赖JAR包(可能有几十到上百个)
# org/
# org/springframework/boot/loader/  # Spring Boot类加载器

JAR包大小分析

bash 复制代码
# 查看JAR包大小
ls -lh target/openerp-backend-1.0.0.jar

# 分析JAR包组成
unzip -l target/openerp-backend-1.0.0.jar | sort -nr -k3 | head -20
# 可以找出最大的依赖包

第二章:Spring Boot 启动方式详解

2.1 方式一:标准启动(最常用)

bash 复制代码
cd ~/Desktop/FeiChenERP/backend
java -jar target/openerp-backend-1.0.0.jar

启动日志解读

复制代码
  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v3.2.5)
                    ↑ Spring Boot 版本

2026-07-26 10:30:15.123  INFO 12345 --- [           main] com.erp.OpenerpApplication               : Starting OpenerpApplication v1.0.0 using Java 17.0.11 with PID 12345 (/Users/xxx/Desktop/FeiChenERP/backend/target/openerp-backend-1.0.0.jar started by xxx in /Users/xxx/Desktop/FeiChenERP/backend)
                    ↑ 启动信息:应用名、版本、Java版本、进程ID、JAR路径、工作目录

2026-07-26 10:30:15.456  INFO 12345 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port 8080 (http)
                    ↑ 嵌入式Tomcat初始化,监听8080端口

2026-07-26 10:30:15.789  INFO 12345 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...
2026-07-26 10:30:16.123  INFO 12345 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.
                    ↑ 数据库连接池初始化

2026-07-26 10:30:16.456  INFO 12345 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port 8080 (http) with context path ''
                    ↑ Tomcat启动完成,上下文路径为空(即根路径)

2026-07-26 10:30:16.789  INFO 12345 --- [           main] com.erp.OpenerpApplication               : Started OpenerpApplication in 3.456 seconds (process running for 4.123)
                    ↑ 应用启动完成,耗时3.456秒

2.2 方式二:指定配置启动

bash 复制代码
# 覆盖单个配置项
java -jar target/openerp-backend-1.0.0.jar \
  --server.port=9090 \
  --spring.datasource.url="jdbc:mysql://localhost:3306/openerp?useSSL=false" \
  --spring.datasource.password=123456 \
  --spring.sql.init.mode=never

常用覆盖参数

参数 默认值 说明
--server.port 8080 HTTP服务端口
--server.context-path 应用上下文路径
--spring.profiles.active default 激活的配置文件
--spring.datasource.url 配置文件中 数据库连接URL
--spring.datasource.username 配置文件中 数据库用户名
--spring.datasource.password 配置文件中 数据库密码
--spring.redis.host localhost Redis主机
--spring.redis.port 6379 Redis端口
--logging.level.root INFO 日志级别
--spring.sql.init.mode embedded SQL初始化模式

2.3 方式三:使用配置文件启动

bash 复制代码
# 使用外部的application.yml
java -jar target/openerp-backend-1.0.0.jar \
  --spring.config.location=file:/path/to/application.yml

# 使用环境特定的配置文件
java -jar target/openerp-backend-1.0.0.jar \
  --spring.profiles.active=prod \
  --spring.config.additional-location=file:/etc/erp/config/

配置文件加载优先级(从高到低):

  1. 命令行参数
  2. 操作系统环境变量(SPRING_APPLICATION_JSON
  3. JAR包外的 application-{profile}.properties/yml
  4. JAR包内的 application-{profile}.properties/yml
  5. JAR包外的 application.properties/yml
  6. JAR包内的 application.properties/yml

2.4 方式四:后台守护启动(生产环境)

bash 复制代码
# 使用nohup
nohup java -jar target/openerp-backend-1.0.0.jar \
  --spring.profiles.active=prod \
  > logs/app.log 2>&1 &

# 记录进程ID
echo $! > app.pid

# 查看日志
tail -f logs/app.log

# 停止应用
kill $(cat app.pid)

nohup 参数说明

符号 含义
nohup 忽略挂断信号(终端关闭不影响进程)
> logs/app.log 标准输出重定向到日志文件
2>&1 标准错误重定向到标准输出(也写入日志)
& 后台运行
$! 最后一个后台进程的PID

2.5 方式五:使用系统服务(生产环境)

创建 Systemd 服务(Linux)
ini 复制代码
# /etc/systemd/system/openerp.service
[Unit]
Description=OpenERP Backend Application
After=network.target mysql.service redis.service

[Service]
Type=simple
User=erpuser
WorkingDirectory=/opt/openerp/backend
ExecStart=/usr/bin/java -jar /opt/openerp/backend/openerp-backend-1.0.0.jar --spring.profiles.active=prod
Restart=always
RestartSec=10
StandardOutput=journal
StandardError=journal
Environment="JAVA_HOME=/usr/lib/jvm/java-17"

[Install]
WantedBy=multi-user.target
bash 复制代码
# 启动服务
sudo systemctl start openerp

# 设置开机自启动
sudo systemctl enable openerp

# 查看状态
sudo systemctl status openerp

# 查看日志
sudo journalctl -u openerp -f
创建 Launch Agent(macOS)
xml 复制代码
<!-- ~/Library/LaunchAgents/com.erp.openerp.plist -->
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.erp.openerp</string>
    <key>ProgramArguments</key>
    <array>
        <string>/usr/bin/java</string>
        <string>-jar</string>
        <string>/Users/xxx/Desktop/FeiChenERP/backend/openerp-backend-1.0.0.jar</string>
        <string>--spring.profiles.active=prod</string>
        <string>--server.port=8080</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
    <key>KeepAlive</key>
    <true/>
    <key>WorkingDirectory</key>
    <string>/Users/xxx/Desktop/FeiChenERP/backend</string>
    <key>StandardOutPath</key>
    <string>/Users/xxx/Desktop/FeiChenERP/backend/logs/app.log</string>
    <key>StandardErrorPath</key>
    <string>/Users/xxx/Desktop/FeiChenERP/backend/logs/error.log</string>
</dict>
</plist>

第三章:JVM参数调优详解

3.1 JVM内存模型

复制代码
┌─────────────────────────────────────────────────────────────┐
│                        JVM 内存                              │
├─────────────────────────────────────────────────────────────┤
│  ┌─────────────────────┐  ┌─────────────────────────────┐  │
│  │     堆内存 (Heap)     │  │    非堆内存 (Non-Heap)       │  │
│  │  ┌──────┐ ┌──────┐  │  │  ┌──────────┐ ┌──────────┐  │  │
│  │  │Young │ │ Old  │  │  │  │ Metaspace│ │  Code    │  │  │
│  │  │Gen   │ │ Gen  │  │  │  │          │ │  Cache   │  │  │
│  │  └──────┘ └──────┘  │  │  └──────────┘ └──────────┘  │  │
│  └─────────────────────┘  └─────────────────────────────┘  │
│       ↑ 对象实例              ↑ 类元数据、JIT编译代码        │
│       ↑ 由GC管理              ↑ 无GC或弱GC                  │
└─────────────────────────────────────────────────────────────┘

3.2 关键JVM参数

bash 复制代码
java -Xms2g -Xmx2g -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m \
     -XX:+UseG1GC -XX:MaxGCPauseMillis=200 \
     -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/log/erp/dump.hprof \
     -jar target/openerp-backend-1.0.0.jar

参数详解

参数 说明 推荐值
-Xms 初始堆内存大小 -Xmx 相同,避免动态调整
-Xmx 最大堆内存大小 物理内存的60-70%(如8GB内存设4-5GB)
-Xmn 年轻代大小 堆大小的1/3
-XX:MetaspaceSize 元空间初始大小 256m
-XX:MaxMetaspaceSize 元空间最大大小 512m
-XX:+UseG1GC 使用G1垃圾回收器 Java 9+默认,适合大堆内存
-XX:MaxGCPauseMillis GC最大暂停时间目标 200ms
-XX:+HeapDumpOnOutOfMemoryError OOM时导出堆转储 建议开启
-XX:HeapDumpPath 堆转储文件路径 指定目录

3.3 GC日志配置

bash 复制代码
java -jar target/openerp-backend-1.0.0.jar \
  -Xlog:gc*:file=logs/gc.log:time,uptime,level,tags:filecount=5,filesize=50m \
  -XX:+PrintGCDetails \
  -XX:+PrintGCDateStamps

3.4 完整启动脚本示例

bash 复制代码
#!/bin/bash
# start.sh - 生产环境启动脚本

APP_NAME="openerp-backend"
APP_VERSION="1.0.0"
JAR_FILE="target/${APP_NAME}-${APP_VERSION}.jar"
LOG_DIR="logs"
PID_FILE="${APP_NAME}.pid"

# JVM参数
JAVA_OPTS="-Xms2g -Xmx2g -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m"
JAVA_OPTS="${JAVA_OPTS} -XX:+UseG1GC -XX:MaxGCPauseMillis=200"
JAVA_OPTS="${JAVA_OPTS} -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=${LOG_DIR}/heapdump.hprof"
JAVA_OPTS="${JAVA_OPTS} -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:${LOG_DIR}/gc.log"

# Spring参数
SPRING_OPTS="--spring.profiles.active=prod"
SPRING_OPTS="${SPRING_OPTS} --spring.sql.init.mode=never"

start() {
    echo "Starting ${APP_NAME}..."
    mkdir -p ${LOG_DIR}
    nohup java ${JAVA_OPTS} -jar ${JAR_FILE} ${SPRING_OPTS} \
        > ${LOG_DIR}/app.log 2>&1 &
    echo $! > ${PID_FILE}
    echo "Started with PID $(cat ${PID_FILE})"
}

stop() {
    echo "Stopping ${APP_NAME}..."
    if [ -f ${PID_FILE} ]; then
        kill $(cat ${PID_FILE})
        rm ${PID_FILE}
        echo "Stopped"
    else
        echo "PID file not found"
    fi
}

status() {
    if [ -f ${PID_FILE} ]; then
        PID=$(cat ${PID_FILE})
        if ps -p ${PID} > /dev/null 2>&1; then
            echo "${APP_NAME} is running with PID ${PID}"
        else
            echo "${APP_NAME} is not running (stale PID file)"
        fi
    else
        echo "${APP_NAME} is not running"
    fi
}

case "$1" in
    start)   start ;;
    stop)    stop ;;
    restart) stop && sleep 2 && start ;;
    status)  status ;;
    *)       echo "Usage: $0 {start|stop|restart|status}" ;;
esac

第四章:启动失败问题系统化排查

4.1 排查方法论

复制代码
启动失败
    ↓
查看日志(最快信息源)
    ↓
识别错误类型
    ↓
    ├── 数据库相关 ──→ 检查MySQL连接
    ├── Redis相关 ──→ 检查Redis连接
    ├── 端口冲突 ──→ 检查端口占用
    ├── 内存不足 ──→ 调整JVM参数
    ├── 配置错误 ──→ 检查配置文件
    ├── 类加载失败 ──→ 检查依赖冲突
    └── 其他异常 ──→ 分析具体堆栈

4.2 常见启动错误及解决方案

错误 1:端口被占用
复制代码
APPLICATION FAILED TO START
***************************

Description:
Web server failed to start. Port 8080 was already in use.

Action:
Identify and stop the process that's listening on port 8080 or configure this application to listen on another port.

解决方案

bash 复制代码
# 1. 查找占用端口的进程
lsof -i :8080
sudo netstat -anp | grep 8080  # Linux

# 2. 结束进程
kill -9 [PID]

# 3. 或修改应用端口
java -jar app.jar --server.port=9090

# 4. 或使用系统属性
java -Dserver.port=9090 -jar app.jar
错误 2:数据库连接失败
复制代码
APPLICATION FAILED TO START
***************************

Description:
Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured.

Reason: Failed to determine a suitable driver class

原因:Spring Boot 无法连接到配置的数据库。

解决方案

bash 复制代码
# 1. 检查MySQL是否运行
ps aux | grep mysql
mysqladmin -u root -p status

# 2. 检查配置文件
cat src/main/resources/application.yml | grep -A5 "datasource"

# 3. 手动测试数据库连接
mysql -u root -p123456 -h localhost -P 3306 -e "SELECT 1"

# 4. 检查数据库是否存在
mysql -u root -p123456 -e "SHOW DATABASES LIKE 'openerp'"

# 5. 启动时指定数据库配置
java -jar app.jar \
  --spring.datasource.url="jdbc:mysql://localhost:3306/openerp?useSSL=false&allowPublicKeyRetrieval=true" \
  --spring.datasource.username=root \
  --spring.datasource.password=123456
错误 3:Redis连接失败
复制代码
Redis connection failed: Connection refused: localhost/127.0.0.1:6379

解决方案

bash 复制代码
# 1. 启动Redis
brew services start redis
# 或
redis-server --daemonize yes

# 2. 测试连接
redis-cli ping

# 3. 如果应用强制要求Redis,暂时禁用Redis配置
java -jar app.jar --spring.data.redis.repositories.enabled=false
错误 4:OutOfMemoryError
复制代码
java.lang.OutOfMemoryError: Java heap space

解决方案

bash 复制代码
# 增加堆内存
java -Xmx2g -Xms2g -jar app.jar

# 增加元空间大小
java -XX:MaxMetaspaceSize=512m -jar app.jar

# 启用G1GC优化
java -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -jar app.jar
错误 5:类找不到
复制代码
java.lang.ClassNotFoundException: org.springframework.boot.SpringApplication

原因:JAR包不完整或损坏。

解决方案

bash 复制代码
# 1. 重新构建
mvn clean package -DskipTests

# 2. 检查JAR包完整性
jar tf target/openerp-backend-1.0.0.jar | grep SpringApplication

# 3. 检查Maven依赖
mvn dependency:tree

# 4. 清理本地仓库(修复损坏依赖)
rm -rf ~/.m2/repository/org/springframework/boot
mvn clean package -DskipTests

4.3 日志级别调整

bash 复制代码
# 启动时调整日志级别
java -jar app.jar \
  --logging.level.root=DEBUG \
  --logging.level.org.springframework.boot=DEBUG \
  --logging.level.com.erp=DEBUG

# 在application.yml中配置
logging:
  level:
    root: INFO
    com.erp: DEBUG
    org.springframework.boot: INFO
    org.hibernate: DEBUG
    com.zaxxer.hikari: DEBUG

4.4 调试模式启动

bash 复制代码
# 远程调试(端口 5005)
java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005 \
  -jar app.jar

# IDEA中连接:Run → Debug → Remote JVM Debug
# Host: localhost, Port: 5005

第五章:应用健康检查与监控

5.1 Spring Boot Actuator 配置

Spring Boot Actuator 提供了生产级的监控和管理端点。

yaml 复制代码
# application.yml
management:
  endpoints:
    web:
      exposure:
        include: health,info,metrics,env,configprops
      base-path: /actuator
  endpoint:
    health:
      show-details: always
      show-components: always
  info:
    env:
      enabled: true

info:
  app:
    name: ${spring.application.name}
    version: @project.version@
    description: @project.description@
  build:
    artifact: @project.artifactId@
    time: @maven.build.timestamp@

5.2 健康检查端点

bash 复制代码
# 基础健康检查
curl http://localhost:8080/actuator/health

# 响应示例
{
  "status": "UP",
  "components": {
    "db": {
      "status": "UP",
      "details": {
        "database": "MySQL",
        "validationQuery": "isValid()"
      }
    },
    "redis": {
      "status": "UP",
      "details": {
        "version": "7.2.4"
      }
    },
    "diskSpace": {
      "status": "UP",
      "details": {
        "total": 500068036608,
        "free": 234567890123,
        "threshold": 10485760
      }
    }
  }
}

# 详细健康信息(需要 management.endpoint.health.show-details=always)
curl http://localhost:8080/actuator/health | jq .

5.3 自定义健康检查

java 复制代码
@Component
public class CustomHealthIndicator implements HealthIndicator {
    
    @Override
    public Health health() {
        boolean isHealthy = checkExternalService();
        if (isHealthy) {
            return Health.up()
                .withDetail("service", "External API")
                .withDetail("status", "Available")
                .build();
        }
        return Health.down()
            .withDetail("service", "External API")
            .withDetail("status", "Unavailable")
            .withDetail("error", "Connection timeout")
            .build();
    }
}

5.4 应用信息端点

bash 复制代码
# 查看应用信息
curl http://localhost:8080/actuator/info

# 查看指标
curl http://localhost:8080/actuator/metrics

# 查看特定指标(如内存使用)
curl http://localhost:8080/actuator/metrics/jvm.memory.used

# 查看线程信息
curl http://localhost:8080/actuator/threaddump

# 查看环境属性
curl http://localhost:8080/actuator/env

第六章:日志管理详解

6.1 Logback 配置

创建 src/main/resources/logback-spring.xml

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <!-- 控制台输出 -->
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>

    <!-- 文件输出 - 所有日志 -->
    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>logs/openerp.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>logs/openerp.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <maxHistory>30</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>

    <!-- 错误日志单独输出 -->
    <appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>logs/error.log</file>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>ERROR</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>logs/error.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <maxHistory>30</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>

    <!-- 异步日志(提高性能) -->
    <appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender">
        <appender-ref ref="FILE"/>
        <queueSize>1024</queueSize>
        <discardingThreshold>0</discardingThreshold>
    </appender>

    <!-- 根日志级别 -->
    <root level="INFO">
        <appender-ref ref="CONSOLE"/>
        <appender-ref ref="ASYNC"/>
        <appender-ref ref="ERROR_FILE"/>
    </root>

    <!-- 特定包的日志级别 -->
    <logger name="com.erp" level="DEBUG"/>
    <logger name="org.springframework.web" level="INFO"/>
    <logger name="org.hibernate" level="INFO"/>
    <logger name="com.zaxxer.hikari" level="INFO"/>
</configuration>

6.2 日志切割与归档

yaml 复制代码
# application.yml 日志配置
logging:
  file:
    name: logs/openerp.log
    path: logs/
  logback:
    rollingpolicy:
      max-file-size: 100MB
      max-history: 30
      total-size-cap: 10GB
      clean-history-on-start: true

6.3 日志查看与分析

bash 复制代码
# 实时查看日志
tail -f logs/app.log

# 查看最近100行
tail -100 logs/app.log

# 搜索错误
grep ERROR logs/app.log

# 统计错误数量
grep -c ERROR logs/app.log

# 查看特定时间段的日志
sed -n '/2026-07-26 10:/,/2026-07-26 11:/p' logs/app.log

# 使用less查看大日志
less logs/app.log
# 在less中: / 搜索, G 跳到末尾, g 跳到开头

6.4 日志级别动态调整

bash 复制代码
# 通过Actuator调整日志级别(需要开启)
curl -X POST http://localhost:8080/actuator/loggers/com.erp \
  -H "Content-Type: application/json" \
  -d '{"configuredLevel": "DEBUG"}'

# 查看当前日志级别
curl http://localhost:8080/actuator/loggers/com.erp

第七章:性能优化与压测

7.1 应用性能调优

数据库连接池优化
yaml 复制代码
spring:
  datasource:
    hikari:
      # 连接池大小
      maximum-pool-size: 20
      minimum-idle: 5
      # 连接超时
      connection-timeout: 30000
      idle-timeout: 600000
      max-lifetime: 1800000
      # 验证查询
      connection-test-query: SELECT 1
      validation-timeout: 3000
线程池优化
yaml 复制代码
server:
  tomcat:
    threads:
      max: 200
      min-spare: 10
    max-connections: 10000
    connection-timeout: 20000
    accept-count: 100

7.2 压力测试

bash 复制代码
# 使用 Apache Bench (ab)
# 安装
brew install httpd  # macOS
sudo apt install apache2-utils  # Ubuntu

# 基础压测
ab -n 1000 -c 10 http://localhost:8080/api/health

# 参数说明
# -n: 总请求数
# -c: 并发数
# -H: 添加请求头
# -p: POST数据文件
# -T: Content-Type

# 使用 wrk (更强大)
# 安装
brew install wrk

# 压测
wrk -t 4 -c 100 -d 30s http://localhost:8080/api/users
# -t: 线程数
# -c: 连接数
# -d: 持续时间

7.3 性能监控指标

bash 复制代码
# 查看JVM内存使用
curl http://localhost:8080/actuator/metrics/jvm.memory.used

# 查看GC情况
curl http://localhost:8080/actuator/metrics/jvm.gc.pause

# 查看请求QPS
curl http://localhost:8080/actuator/metrics/http.server.requests

# 查看数据库连接池
curl http://localhost:8080/actuator/metrics/hikaricp.connections

第八章:运维场景实战

8.1 优雅关闭应用

Spring Boot 支持优雅关闭:

yaml 复制代码
server:
  shutdown: graceful

spring:
  lifecycle:
    timeout-per-shutdown-phase: 30s
bash 复制代码
# 发送SIGTERM信号触发优雅关闭
kill -15 $(cat app.pid)
# 或
pkill -15 -f openerp-backend

8.2 应用版本回滚

bash 复制代码
# 保留多个版本
ls -la releases/
# openerp-backend-1.0.0.jar
# openerp-backend-1.0.1.jar
# openerp-backend-1.0.2.jar

# 创建符号链接
ln -sf releases/openerp-backend-1.0.1.jar current/openerp-backend.jar

# 重启应用
./start.sh restart

8.3 数据库迁移

bash 复制代码
# 使用Flyway或Liquibase进行版本化数据库迁移
# 或手动执行SQL脚本
mysql -u root -p123456 openerp < migrations/V1.1__add_new_table.sql

# 验证迁移结果
mysql -u root -p123456 openerp -e "SHOW TABLES;"

8.4 应用备份与恢复

bash 复制代码
# 备份JAR包
cp target/openerp-backend-1.0.0.jar backups/openerp-backend-$(date +%Y%m%d).jar

# 备份配置文件
cp src/main/resources/application.yml backups/application-$(date +%Y%m%d).yml

# 备份数据库
mysqldump -u root -p123456 openerp > backups/openerp-$(date +%Y%m%d).sql

# 恢复数据库
mysql -u root -p123456 openerp < backups/openerp-20260726.sql

8.5 快速问题诊断命令集

bash 复制代码
# 一键检查应用状态
echo "=== 应用状态 ===" && ps aux | grep openerp | grep -v grep && \
echo "=== 端口监听 ===" && lsof -i :8080 && \
echo "=== MySQL状态 ===" && mysqladmin -u root -p123456 status && \
echo "=== Redis状态 ===" && redis-cli ping && \
echo "=== 健康检查 ===" && curl -s http://localhost:8080/actuator/health | jq .status && \
echo "=== 最近错误 ===" && tail -20 logs/app.log | grep ERROR

第九章:总结与最佳实践

9.1 启动运维清单

检查项 命令/方法 预期结果
应用是否运行 `ps aux grep app.jar`
端口是否监听 `lsof -

您好,我是肥晨。

欢迎关注我获取前端/AI学习资源,日常分享技术变革,生存法则;行业内幕,洞察先机。

相关推荐
geovindu1 小时前
CSharp: Breadth First Search Algorithm and Depth First Search Algorithm
开发语言·后端·算法·c#·.net·搜索算法
景同学2 小时前
把 AI 用到线上运维:可行、有效,前提是喂足信息——一次 Full GC 排障实录
java·人工智能·后端
库克克2 小时前
【C++】set 与multiset
开发语言·c++
Wang's Blog2 小时前
Go-Zero项目开发34: 微服务超时控制与重试机制实践
开发语言·微服务·golang·go-zero
C++、Java和Python的菜鸟2 小时前
第7章 后端Web实战(Tlias系统)
java
憧憬成为java架构高手的小白2 小时前
黑马八股--spring框架学习
java·学习·spring
唐青枫3 小时前
Java Picocli 实战详解:用注解写出好用的命令行工具
java
2zcode3 小时前
项目文档:基于MATLAB神经网络的心力衰竭预测与临床辅助决策系统研究
开发语言·神经网络·matlab·心力衰竭预测\
X-⃢_⃢-X3 小时前
四、OpenFeign远程调用
java·微服务·springboot·springcloud
减瓦3 小时前
深入 Quarkus:云原生时代 Java 的重生之路
java·开发语言·云原生