前言
生产环境的应用需要关注安全性、性能、可维护性等多个方面。遵循最佳实践可以降低风险、提升稳定性。本文将介绍 Spring Boot 生产最佳实践。
配置管理
1. 敏感信息保护
# ✅ 推荐 - 使用环境变量
spring:
datasource:
url: jdbc:mysql://${DB_HOST}:${DB_PORT}/${DB_NAME}
username: ${DB_USERNAME}
password: ${DB_PASSWORD}
# ❌ 不推荐 - 硬编码
spring:
datasource:
url: jdbc:mysql://localhost:3306/demo
username: root
password: 123456
2. 配置中心
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
# bootstrap.yml
spring:
cloud:
nacos:
config:
server-addr: nacos:8848
file-extension: yaml
namespace: ${NAMESPACE:prod}
group: DEFAULT_GROUP
3. 配置加密
<dependency>
<groupId>com.github.ulisesbocchio</groupId>
<artifactId>jasypt-spring-boot-starter</artifactId>
</dependency>
jasypt:
encryptor:
password: ${JASYPT_PASSWORD}
spring:
datasource:
password: ENC(加密后的密码)
安全加固
1. 端点安全
management:
endpoints:
web:
exposure:
include: health,info,prometheus
endpoint:
health:
show-details: never
server:
port: 9090
address: 127.0.0.1
@Configuration
@EnableWebSecurity
public class ActuatorSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.securityMatcher(EndpointRequest.toAnyEndpoint())
.authorizeHttpRequests(authorize -> authorize
.requestMatchers(EndpointRequest.to("health", "info")).permitAll()
.anyRequest().hasRole("ADMIN")
)
.httpBasic(Customizer.withDefaults());
return http.build();
}
}
2. 请求防护
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.csrf(csrf -> csrf
.ignoringRequestMatchers("/api/**")
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
)
.headers(headers -> headers
.contentSecurityPolicy(policy -> policy
.policyDirectives("default-src 'self'")
)
.frameOptions(frame -> frame.deny())
.xssProtection(xss -> xss.enable(true))
);
return http.build();
}
}
3. 依赖安全
# 检查依赖漏洞
mvn org.owasp:dependency-check-maven:check
# 使用安全版本
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>4.0.0</version> <!-- 使用最新安全版本 -->
</dependency>
性能优化
1. JVM 调优
# 生产环境 JVM 参数
java -Xms4g -Xmx4g \
-XX:MetaspaceSize=256m \
-XX:MaxMetaspaceSize=512m \
-XX:+UseG1GC \
-XX:MaxGCPauseMillis=200 \
-XX:+HeapDumpOnOutOfMemoryError \
-XX:HeapDumpPath=/var/log/heapdump.hprof \
-jar app.jar
2. 连接池优化
spring:
datasource:
hikari:
maximum-pool-size: 20
minimum-idle: 5
connection-timeout: 30000
idle-timeout: 600000
max-lifetime: 1800000
leak-detection-threshold: 60000
3. 缓存策略
@Configuration
@EnableCaching
public class CacheConfig {
@Bean
public CacheManager cacheManager() {
CaffeineCacheManager cacheManager = new CaffeineCacheManager();
cacheManager.setCaffeine(Caffeine.newBuilder()
.initialCapacity(100)
.maximumSize(10000)
.expireAfterWrite(10, TimeUnit.MINUTES)
.recordStats()
);
return cacheManager;
}
}
@Service
public class UserService {
@Cacheable(value = "users", key = "#id")
public UserDTO getUserById(Long id) {
return userRepository.findById(id)
.map(this::convertToDTO)
.orElse(null);
}
@CachePut(value = "users", key = "#user.id")
public UserDTO updateUser(UserDTO user) {
return userRepository.save(convert(user));
}
@CacheEvict(value = "users", key = "#id")
public void deleteUser(Long id) {
userRepository.deleteById(id);
}
}
4. 异步处理
@Configuration
@EnableAsync
public class AsyncConfig {
@Bean
public Executor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(10);
executor.setMaxPoolSize(50);
executor.setQueueCapacity(100);
executor.setThreadNamePrefix("async-");
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
return executor;
}
}
@Service
public class NotificationService {
@Async
public CompletableFuture<Void> sendEmail(String to, String content) {
// 异步发送邮件
emailService.send(to, content);
return CompletableFuture.completedFuture(null);
}
}
运维监控
1. 健康检查
management:
health:
livenessState:
enabled: true
readinessState:
enabled: true
endpoint:
health:
probes:
enabled: true
# Kubernetes 探针
livenessProbe:
httpGet:
path: /actuator/health/liveness
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /actuator/health/readiness
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
2. 指标监控
management:
metrics:
export:
prometheus:
enabled: true
tags:
application: ${spring.application.name}
environment: ${spring.profiles.active}
3. 日志管理
logging:
level:
root: INFO
com.example.demo: INFO
pattern:
console: "%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n"
file:
name: /var/log/app/app.log
max-size: 100MB
max-history: 30
total-size-cap: 10GB
<!-- Logback 配置 -->
<configuration>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>/var/log/app/app.log</file>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>/var/log/app/app.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<maxFileSize>100MB</maxFileSize>
<maxHistory>30</maxHistory>
</rollingPolicy>
</appender>
<root level="INFO">
<appender-ref ref="FILE"/>
</root>
</configuration>
4. 链路追踪
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
spring:
cloud:
sleuth:
sampler:
probability: 0.1 # 10% 采样
部署实践
1. Docker 优化
# 多阶段构建
FROM maven:3.9-eclipse-temurin-21 AS build
WORKDIR /app
COPY . .
RUN mvn clean package -DskipTests
FROM eclipse-temurin:21-jre-alpine
WORKDIR /app
COPY --from=build /app/target/*.jar app.jar
# 非 root 用户
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
USER appuser
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]
2. Kubernetes 部署
apiVersion: apps/v1
kind: Deployment
metadata:
name: demo
spec:
replicas: 3
selector:
matchLabels:
app: demo
template:
spec:
containers:
- name: demo
image: demo:1.0.0
ports:
- containerPort: 8080
resources:
requests:
memory: "512Mi"
cpu: "250m"
limits:
memory: "1Gi"
cpu: "500m"
livenessProbe:
httpGet:
path: /actuator/health/liveness
port: 8080
initialDelaySeconds: 30
readinessProbe:
httpGet:
path: /actuator/health/readiness
port: 8080
initialDelaySeconds: 10
3. 滚动更新
spec:
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
容灾备份
1. 数据库备份
#!/bin/bash
# backup.sh
BACKUP_DIR="/backup/mysql"
DATE=$(date +%Y%m%d_%H%M%S)
mysqldemo -h localhost -u root -pPASSWORD demo > ${BACKUP_DIR}/demo_${DATE}.sql
# 保留最近 7 天备份
find ${BACKUP_DIR} -name "demo_*.sql" -mtime +7 -delete
2. 多活架构
# 多数据源配置
spring:
datasource:
dynamic:
primary: master
datasource:
master:
url: jdbc:mysql://master:3306/demo
slave:
url: jdbc:mysql://slave:3306/demo
3. 限流降级
@Service
public class OrderService {
@SentinelResource(value = "createOrder",
blockHandler = "handleBlock",
fallback = "handleFallback")
public Order createOrder(OrderCreateDTO dto) {
// 业务逻辑
}
public Order handleBlock(OrderCreateDTO dto, BlockException ex) {
log.warn("限流:{}", dto);
return null;
}
public Order handleFallback(OrderCreateDTO dto, Throwable ex) {
log.error("降级:{}", dto, ex);
return null;
}
}
最佳实践清单
上线前检查
- [ ] 代码审查通过
- [ ] 单元测试通过
- [ ] 集成测试通过
- [ ] 性能测试通过
- [ ] 安全扫描通过
- [ ] 配置检查完成
- [ ] 监控告警配置
- [ ] 备份策略配置
- [ ] 回滚方案准备
- [ ] 应急预案准备
运维检查
- [ ] CPU 使用率 < 70%
- [ ] 内存使用率 < 80%
- [ ] 磁盘使用率 < 80%
- [ ] 错误率 < 0.1%
- [ ] 响应时间 < 500ms
- [ ] 数据库连接正常
- [ ] 缓存命中率 > 90%
- [ ] 日志正常无异常
总结
生产最佳实践要点:
- ✅ 配置管理 - 敏感信息、配置中心
- ✅ 安全加固 - 端点安全、请求防护
- ✅ 性能优化 - JVM、连接池、缓存
- ✅ 运维监控 - 健康检查、指标、日志
- ✅ 部署实践 - Docker、K8s、滚动更新
- ✅ 容灾备份 - 备份、多活、限流降级
遵循最佳实践,保障生产稳定。