SpringBoot 自动化部署实战:从环境搭建到 CI/CD 全流程
一、自动化部署基础环境准备
1. 服务器环境配置
在开始部署前,需要先准备好服务器环境。以 Ubuntu 20.04 为例,基本环境配置步骤如下:
# 更新软件包列表sudo apt-get update# 安装JDK 11(SpringBoot 2.7+推荐JDK 11)sudo apt-get install openjdk-11-jdk# 安装Maven(用于项目构建)sudo apt-get install maven# 安装Git(用于代码拉取)sudo apt-get install git# 安装Nginx(用于反向代理)sudo apt-get install nginx# 配置防火墙sudo ufw allow 80/tcpsudo ufw allow 443/tcpsudo ufw allow 8080/tcp # SpringBoot默认端口sudo ufw enable
2. 项目结构优化
为了便于自动化部署,需要对 SpringBoot 项目结构进行优化:
your-project/├── src/│ ├── main/│ │ ├── java/│ │ ├── resources/│ │ │ ├── application.yml│ │ │ ├── application-prod.yml # 生产环境配置│ │ │ └── application-dev.yml # 开发环境配置│ └── test/├── pom.xml # Maven配置文件├── deploy/ # 部署相关脚本│ ├── build.sh # 构建脚本│ ├── start.sh # 启动脚本│ ├── stop.sh # 停止脚本│ └── deploy.yml # 部署配置└── .gitlab-ci.yml # CI/CD配置文件(以GitLab为例)
3. 日志规范设计
良好的日志规范对部署后的维护至关重要,在 application.yml 中添加如下配置:
logging: level: root: INFO com.yourcompany: DEBUG file: name: /var/log/your-project/your-project.log max-size: 10MB max-history: 7 pattern: console: "%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n" file: "%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n"
二、三种主流自动化部署方式实战
1. Shell 脚本部署方式
这是最基础的自动化部署方式,适合中小型项目。在项目根目录下创建 deploy 目录,添加以下脚本:
# deploy/build.sh#!/bin/bash# 构建项目mvn clean package -DskipTests -Pprod# 复制jar包到部署目录mkdir -p /opt/your-project/releasescp target/your-project-1.0.0.jar /opt/your-project/releases/your-project-latest.jar
# deploy/start.sh#!/bin/bash# 停止当前运行的进程./stop.sh# 创建日志目录mkdir -p /var/log/your-project# 启动新进程nohup java -jar \-XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m \-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/opt/your-project/heapdump \-Dspring.config.location=/opt/your-project/application-prod.yml \/opt/your-project/releases/your-project-latest.jar > /var/log/your-project/start.log 2>&1 &# 输出进程IDecho $! > /opt/your-project/pid.txtecho "项目已启动,进程ID: $(cat /opt/your-project/pid.txt)"
# deploy/stop.sh#!/bin/bash# 停止进程if [ -f /opt/your-project/pid.txt ]; then PID=$(cat /opt/your-project/pid.txt) if [ -n "$PID" ]; then echo "正在停止进程: $PID" kill -15 $PID sleep 5 # 强制终止 if ps -p $PID > /dev/null; then echo "进程未正常停止,强制终止" kill -9 $PID fi fi rm -f /opt/your-project/pid.txtelse echo "未找到进程ID文件"fi
执行部署时,只需按顺序执行build.sh 和start.sh 脚本:
./deploy/build.sh./deploy/start.sh
2. Docker 容器化部署
Docker 部署方式具有更好的环境一致性和可移植性,首先在项目根目录添加 Dockerfile:
FROM openjdk:11-jdk-slimWORKDIR /app# 复制依赖和配置COPY pom.xml .COPY src/main/resources/application-prod.yml application.yml# 下载依赖(利用Docker缓存)RUN apt-get update && apt-get install -y maven && \ mvn dependency:go-offline -B# 复制项目代码COPY src ./src# 构建项目RUN mvn package -DskipTests -Pprod# 复制构建好的jar包COPY target/your-project-1.0.0.jar app.jar# 暴露端口EXPOSE 8080# 启动命令ENTRYPOINT ["java","-jar","app.jar"]
然后创建 docker-compose.yml 文件:
version: '3'services: your-project: build: . container_name: your-project restart: always ports: - "8080:8080" volumes: - /var/log/your-project:/var/log/your-project - /opt/your-project/conf:/app/conf environment: - SPRING_PROFILES_ACTIVE=prod healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8080/actuator/health"] interval: 30s timeout: 10s retries: 3
部署时只需执行:
docker-compose up -d
3. Kubernetes 集群部署
对于大型项目,推荐使用 Kubernetes 进行部署,首先创建 deployment.yaml:
apiVersion: apps/v1kind: Deploymentmetadata: name: your-project labels: app: your-projectspec: replicas: 3 selector: matchLabels: app: your-project template: metadata: labels: app: your-project spec: containers: - name: your-project image: your-registry/your-project:latest ports: - containerPort: 8080 livenessProbe: httpGet: path: /actuator/health port: 8080 initialDelaySeconds: 30 periodSeconds: 10 readinessProbe: httpGet: path: /actuator/health port: 8080 initialDelaySeconds: 10 periodSeconds: 5 env: - name: SPRING_PROFILES_ACTIVE value: prod volumeMounts: - name: config-volume mountPath: /app/conf volumes: - name: config-volume configMap: name: your-project-config
创建 service.yaml:
apiVersion: v1kind: Servicemetadata: name: your-project-servicespec: type: NodePort ports: - port: 8080 targetPort: 8080 nodePort: 30080 selector: app: your-project
创建 configmap.yaml:
apiVersion: v1kind: ConfigMapmetadata: name: your-project-configdata: application-prod.yml: | spring: datasource: url: jdbc:mysql://mysql-service:3306/yourdb?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true username: youruser password: yourpassword redis: host: redis-service port: 6379
部署到 Kubernetes 集群:
kubectl apply -f deployment.yamlkubectl apply -f service.yamlkubectl apply -f configmap.yaml
三、CI/CD 流程搭建实战
1. GitLab CI/CD 配置
在项目根目录创建.gitlab-ci.yml 文件:
stages: - build - test - deployimage: maven:3.8.4-openjdk-11before_script: - echo "CI/CD流程开始" - mkdir -p .m2/repositorybuild_job: stage: build script: - mvn clean package -DskipTests artifacts: paths: - target/your-project-1.0.0.jar only: - maintest_job: stage: test script: - mvn test only: - maindeploy_to_staging: stage: deploy script: - echo "部署到测试环境" - scp target/your-project-1.0.0.jar staging-server:/opt/your-project/releases/ - ssh staging-server "cd /opt/your-project && ./deploy/start.sh" only: - developdeploy_to_production: stage: deploy script: - echo "部署到生产环境" - scp target/your-project-1.0.0.jar production-server:/opt/your-project/releases/ - ssh production-server "cd /opt/your-project && ./deploy/start.sh" only: - main when: manual # 生产环境部署需要手动确认
2. Jenkins CI/CD 配置
在 Jenkins 中创建 Pipeline 项目,Jenkinsfile 内容如下:
pipeline { agent any tools { maven 'Maven 3.8.4' jdk 'Java 11' } stages { stage('Build') { steps { sh 'mvn clean package -DskipTests' } artifacts { archivesArtifacts 'target/your-project-1.0.0.jar' } } stage('Test') { steps { sh 'mvn test' } } stage('Deploy to Staging') { when { branch 'develop' } steps { sh """ scp target/your-project-1.0.0.jar staging-server:/opt/your-project/releases/ ssh staging-server "cd /opt/your-project && ./deploy/start.sh" """ } } stage('Deploy to Production') { when { branch 'main' } steps { input message: '确认部署到生产环境?', ok: '部署' sh """ scp target/your-project-1.0.0.jar production-server:/opt/your-project/releases/ ssh production-server "cd /opt/your-project && ./deploy/start.sh" """ } } } post { success { slackSend channel: '#deploy-notifications', message: "部署成功: ${env.JOB_NAME} #${env.BUILD_NUMBER}" } failure { slackSend channel: '#deploy-notifications', message: "部署失败: ${env.JOB_NAME} #${env.BUILD_NUMBER}" } }}
3. 蓝绿部署与金丝雀发布
蓝绿部署实现
在 Kubernetes 中实现蓝绿部署,只需修改 deployment.yaml 的标签和版本号:
apiVersion: apps/v1kind: Deploymentmetadata: name: your-project-v1 labels: app: your-project version: v1spec: # 配置不变...---apiVersion: apps/v1kind: Servicemetadata: name: your-projectspec: # 服务选择器根据当前活跃版本调整 selector: app: your-project version: v1
升级时创建新的 deployment 并更新服务选择器:
apiVersion: apps/v1kind: Deploymentmetadata: name: your-project-v2 labels: app: your-project version: v2spec: # 新版本配置...
金丝雀发布实现
使用 Istio 服务网格实现金丝雀发布,创建 virtualservice.yaml:
apiVersion: networking.istio.io/v1alpha3kind: VirtualServicemetadata: name: your-projectspec: hosts: - your-project.com http: - route: - destination: host: your-project-v1 port: number: 8080 weight: 90 - destination: host: your-project-v2 port: number: 8080 weight: 10
四、部署后的监控与问题排查
1. 系统监控配置
使用 Prometheus 和 Grafana 搭建监控系统,在 SpringBoot 项目中添加监控依赖:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId></dependency><dependency> <groupId>io.micrometer</groupId> <artifactId>micrometer-registry-prometheus</artifactId></dependency>
配置 application.yml:
management: endpoints: web: exposure: include: "*" metrics: export: prometheus: enabled: true step: 10s endpoint: health: show-details: always
在 Prometheus 配置中添加监控目标:
- job_name: 'your-project' metrics_path: '/actuator/prometheus' static_configs: - targets: ['your-project-server:8080']
2. 日志收集与分析
使用 ELK Stack 收集日志,在 SpringBoot 项目中添加 Logstash 依赖:
<dependency> <groupId>net.logstash.logback</groupId> <artifactId>logstash-logback-encoder</artifactId> <version>7.2.0</version></dependency>
添加 logback-spring.xml 配置:
<configuration> <appender name="LOGSTASH" > <destination>logstash-server:5044</destination> <encoder /> </appender> <root level="INFO"> <appender-ref ref="LOGSTASH" /> </root></configuration>
3. 常见问题排查命令
# 查看Java进程ps -ef | grep java# 查看CPU和内存使用情况top -p <PID># 查看JVM堆内存使用jmap -heap <PID># 查看线程状态jstack <PID> | grep -A 10 RUNNABLE# 查看应用日志tail -f /var/log/your-project/your-project.log# 查看Kubernetes pod状态kubectl get pods -n your-namespace# 查看容器日志kubectl logs your-pod-name -n your-namespace
五、实战案例:高并发系统部署优化
1. 案例背景
某电商平台订单系统,采用 SpringBoot 开发,日均订单量 100 万 +,高峰期 QPS 达 5000+,部署后出现以下问题:
-
高峰期 CPU 使用率持续 100%
-
偶尔出现 GC 超时导致的请求卡顿
-
数据库连接池经常达到最大连接数
2. 优化方案
JVM 参数优化
java -jar \-XX:MetaspaceSize=512m -XX:MaxMetaspaceSize=1024m \-XX:+UseG1GC -XX:G1HeapRegionSize=16m \-XX:InitialHeapSize=4g -XX:MaxHeapSize=8g \-XX:MaxTenuringThreshold=15 \-XX:+ExplicitGCInvokesConcurrent \-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/opt/your-project/heapdump \-XX:ErrorFile=/opt/your-project/hs_err_pid%p.log \-Dspring.config.location=/opt/your-project/application-prod.yml \/opt/your-project/releases/your-project-latest.jar