Spring Boot 部署
1. 部署概述
1.1 部署方式
| 方式 | 说明 | 适用场景 |
|---|---|---|
| JAR 包部署 | 内嵌服务器 | 传统部署、云服务器 |
| WAR 包部署 | 外部服务器 | 传统应用服务器 |
| Docker 容器 | 容器化部署 | 云原生、Kubernetes |
| 原生镜像 | GraalVM 编译 | 快速启动、低内存 |
1.2 构建工具
bash
# Maven
mvn clean package
# Gradle
gradle clean build2. JAR 包部署
2.1 构建配置
xml
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>2.2 运行 JAR
bash
# 基本运行
java -jar myapp.jar
# 指定配置
java -jar myapp.jar --spring.profiles.active=prod
# 指定端口
java -jar myapp.jar --server.port=8081
# 后台运行
nohup java -jar myapp.jar > app.log 2>&1 &
# 指定 JVM 参数
java -Xms512m -Xmx2048m -jar myapp.jar
# 指定环境变量
java -Dspring.datasource.url=jdbc:mysql://prod-db:3306/mydb -jar myapp.jar2.3 Systemd 服务
ini
# /etc/systemd/system/myapp.service
[Unit]
Description=My Spring Boot Application
After=syslog.target network.target
[Service]
User=myapp
ExecStart=/usr/bin/java -Xms512m -Xmx2048m -jar /opt/myapp/myapp.jar
SuccessExitStatus=143
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.targetbash
# 启用服务
sudo systemctl enable myapp
# 启动服务
sudo systemctl start myapp
# 查看状态
sudo systemctl status myapp
# 查看日志
sudo journalctl -u myapp -f3. Docker 部署
3.1 Dockerfile
dockerfile
# 多阶段构建
FROM eclipse-temurin:21-jdk-alpine AS builder
WORKDIR /app
COPY pom.xml .
COPY src ./src
RUN apk add --no-cache maven && \
mvn clean package -DskipTests
FROM eclipse-temurin:21-jre-alpine
WORKDIR /app
RUN addgroup -S spring && adduser -S spring -G spring
USER spring:spring
COPY --from=builder /app/target/*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]3.2 优化 Dockerfile
dockerfile
FROM eclipse-temurin:21-jre-alpine
WORKDIR /app
RUN addgroup -S spring && adduser -S spring -G spring
USER spring:spring
COPY target/*.jar app.jar
EXPOSE 8080
HEALTHCHECK --interval=30s --timeout=3s --start-period=60s --retries=3 \
CMD wget -q --spider http://localhost:8080/actuator/health || exit 1
ENTRYPOINT ["java", \
"-Xms256m", \
"-Xmx512m", \
"-XX:+UseContainerSupport", \
"-XX:MaxRAMPercentage=75.0", \
"-jar", "app.jar"]3.3 Docker Compose
yaml
version: '3.8'
services:
app:
build: .
ports:
- "8080:8080"
environment:
- SPRING_PROFILES_ACTIVE=prod
- SPRING_DATASOURCE_URL=jdbc:mysql://db:3306/mydb
- SPRING_DATASOURCE_USERNAME=root
- SPRING_DATASOURCE_PASSWORD=password
- SPRING_REDIS_HOST=redis
depends_on:
- db
- redis
healthcheck:
test: ["CMD", "wget", "-q", "--spider", "http://localhost:8080/actuator/health"]
interval: 30s
timeout: 3s
retries: 3
start_period: 60s
restart: always
db:
image: mysql:8.0
environment:
- MYSQL_ROOT_PASSWORD=password
- MYSQL_DATABASE=mydb
volumes:
- mysql_data:/var/lib/mysql
ports:
- "3306:3306"
redis:
image: redis:7-alpine
ports:
- "6379:6379"
volumes:
- redis_data:/data
volumes:
mysql_data:
redis_data:bash
# 启动服务
docker-compose up -d
# 查看日志
docker-compose logs -f app
# 停止服务
docker-compose down
# 重新构建
docker-compose up -d --build4. Kubernetes 部署
4.1 Deployment
yaml
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
labels:
app: myapp
spec:
replicas: 3
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: myapp:latest
ports:
- containerPort: 8080
env:
- name: SPRING_PROFILES_ACTIVE
value: "prod"
- name: SPRING_DATASOURCE_URL
valueFrom:
secretKeyRef:
name: myapp-secret
key: database-url
- name: SPRING_DATASOURCE_USERNAME
valueFrom:
secretKeyRef:
name: myapp-secret
key: database-username
- name: SPRING_DATASOURCE_PASSWORD
valueFrom:
secretKeyRef:
name: myapp-secret
key: database-password
resources:
requests:
memory: "512Mi"
cpu: "250m"
limits:
memory: "1Gi"
cpu: "500m"
livenessProbe:
httpGet:
path: /actuator/health/liveness
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /actuator/health/readiness
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
volumeMounts:
- name: config
mountPath: /config
readOnly: true
volumes:
- name: config
configMap:
name: myapp-config4.2 Service
yaml
# service.yaml
apiVersion: v1
kind: Service
metadata:
name: myapp
spec:
selector:
app: myapp
ports:
- port: 80
targetPort: 8080
type: ClusterIP
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: myapp-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: myapp.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: myapp
port:
number: 804.3 ConfigMap 和 Secret
yaml
# configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: myapp-config
data:
application.yml: |
spring:
datasource:
url: jdbc:mysql://mysql:3306/mydb
redis:
host: redis
---
# secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: myapp-secret
type: Opaque
stringData:
database-url: jdbc:mysql://mysql:3306/mydb
database-username: root
database-password: password4.4 HPA 自动扩缩容
yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: myapp-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: myapp
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 805. GraalVM 原生镜像
5.1 添加依赖
xml
<dependency>
<groupId>org.graalvm.buildtools</groupId>
<artifactId>jvm-metadata-repository</artifactId>
<version>0.3.8</version>
</dependency>5.2 构建配置
xml
<build>
<plugins>
<plugin>
<groupId>org.graalvm.buildtools</groupId>
<artifactId>native-maven-plugin</artifactId>
<configuration>
<buildArgs>
<buildArg>--no-fallback</buildArg>
<buildArg>-H:+ReportExceptionStackTraces</buildArg>
</buildArgs>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<id>process-aot</id>
<goals>
<goal>process-aot</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>5.3 构建原生镜像
bash
# 使用 GraalVM 构建
mvn -Pnative native:compile
# 使用 Spring Boot 构建
mvn -Pnative spring-boot:build-image5.4 运行原生镜像
bash
# 直接运行
./target/myapp
# 启动时间通常在 0.1 秒以内
# 内存占用通常在 50MB 以内6. 配置管理
6.1 外部配置
bash
# 配置文件位置
java -jar myapp.jar --spring.config.location=file:/etc/myapp/
# 额外配置文件
java -jar myapp.jar --spring.config.additional-location=file:/etc/myapp/
# 配置中心
java -jar myapp.jar --spring.config.import=optional:configserver:http://config-server:88886.2 环境变量配置
yaml
# application.yml
spring:
datasource:
url: ${DB_URL:jdbc:mysql://localhost:3306/mydb}
username: ${DB_USERNAME:root}
password: ${DB_PASSWORD:password}
redis:
host: ${REDIS_HOST:localhost}
port: ${REDIS_PORT:6379}bash
export DB_URL=jdbc:mysql://prod-db:3306/mydb
export DB_USERNAME=prod_user
export DB_PASSWORD=prod_password
java -jar myapp.jar7. 日志管理
7.1 日志配置
yaml
logging:
file:
name: /var/log/myapp/application.log
max-size: 100MB
max-history: 30
pattern:
file: "%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n"7.2 日志收集
yaml
# logback-spring.xml
<configuration>
<appender name="JSON" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>/var/log/myapp/application.json</file>
<encoder class="net.logstash.logback.encoder.LogstashEncoder"/>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>/var/log/myapp/application.%d{yyyy-MM-dd}.json</fileNamePattern>
<maxHistory>30</maxHistory>
</rollingPolicy>
</appender>
<root level="INFO">
<appender-ref ref="JSON"/>
</root>
</configuration>8. 性能调优
8.1 JVM 参数
bash
java -Xms512m \
-Xmx2048m \
-XX:+UseG1GC \
-XX:MaxGCPauseMillis=200 \
-XX:+HeapDumpOnOutOfMemoryError \
-XX:HeapDumpPath=/var/log/myapp/heapdump.hprof \
-XX:+PrintGCDetails \
-XX:+PrintGCDateStamps \
-Xloggc:/var/log/myapp/gc.log \
-jar myapp.jar8.2 容器资源限制
yaml
# Kubernetes
resources:
requests:
memory: "512Mi"
cpu: "250m"
limits:
memory: "1Gi"
cpu: "500m"bash
# Docker
docker run -m 1g --cpus=0.5 myapp:latest9. 小结
本章学习了 Spring Boot 部署的核心内容:
| 内容 | 要点 |
|---|---|
| JAR 部署 | 打包、运行、Systemd 服务 |
| Docker | Dockerfile、Docker Compose |
| Kubernetes | Deployment、Service、HPA |
| 原生镜像 | GraalVM、快速启动 |
| 配置管理 | 外部配置、环境变量 |
| 日志管理 | 日志配置、日志收集 |
| 性能调优 | JVM 参数、资源限制 |
下一章将学习微服务架构概述。