1. 性能基准测试
1.1 性能指标定义
# 性能测试框架
from enum import Enum
from dataclasses import dataclass
from typing import List, Dict, Optional
import time
import psutil
import threading
class MetricType(Enum):
"""指标类型"""
STARTUP_TIME = "startup_time" # 启动时间
MEMORY_USAGE = "memory_usage" # 内存使用
RESPONSE_TIME = "response_time" # 响应时间
THROUGHPUT = "throughput" # 吞吐量
CPU_USAGE = "cpu_usage" # CPU 使用率
BINARY_SIZE = "binary_size" # 二进制大小
FIRST_REQUEST = "first_request" # 首次请求时间
class RuntimeMode(Enum):
"""运行时模式"""
JVM = "jvm" # JVM 模式
NATIVE = "native" # 原生模式
CONTAINER_JVM = "container_jvm" # 容器 JVM
CONTAINER_NATIVE = "container_native" # 容器原生
@dataclass
class PerformanceMetric:
"""性能指标"""
metric_type: MetricType
value: float
unit: str
timestamp: float
runtime_mode: RuntimeMode
description: Optional[str] = None
@dataclass
class BenchmarkConfig:
"""基准测试配置"""
app_name: str
runtime_modes: List[RuntimeMode]
test_duration: int = 60 # 秒
warmup_duration: int = 30 # 秒
concurrent_users: int = 10
request_rate: int = 100 # 每秒请求数
memory_sample_interval: float = 1.0 # 秒
@dataclass
class BenchmarkResult:
"""基准测试结果"""
config: BenchmarkConfig
metrics: List[PerformanceMetric]
start_time: float
end_time: float
success: bool
errors: List[str]
class PerformanceBenchmark:
"""性能基准测试器"""
def __init__(self, config: BenchmarkConfig):
self.config = config
self.metrics: List[PerformanceMetric] = []
self.monitoring = False
def measure_startup_time(self, runtime_mode: RuntimeMode, command: str) -> float:
"""测量启动时间"""
print(f"测量 {runtime_mode.value} 模式启动时间...")
start_time = time.time()
# 模拟启动过程
if runtime_mode == RuntimeMode.JVM:
# JVM 启动较慢
time.sleep(3.5)
elif runtime_mode == RuntimeMode.NATIVE:
# 原生启动很快
time.sleep(0.1)
elif runtime_mode == RuntimeMode.CONTAINER_JVM:
# 容器 JVM 启动
time.sleep(4.0)
elif runtime_mode == RuntimeMode.CONTAINER_NATIVE:
# 容器原生启动
time.sleep(0.2)
startup_time = time.time() - start_time
metric = PerformanceMetric(
metric_type=MetricType.STARTUP_TIME,
value=startup_time,
unit="seconds",
timestamp=time.time(),
runtime_mode=runtime_mode,
description=f"应用启动时间 ({runtime_mode.value})"
)
self.metrics.append(metric)
return startup_time
def measure_memory_usage(self, runtime_mode: RuntimeMode, duration: int) -> List[float]:
"""测量内存使用"""
print(f"测量 {runtime_mode.value} 模式内存使用...")
memory_samples = []
def monitor_memory():
start_time = time.time()
while self.monitoring and (time.time() - start_time) < duration:
# 模拟内存使用
if runtime_mode == RuntimeMode.JVM:
# JVM 内存使用较高
memory_mb = 150 + (time.time() - start_time) * 2
elif runtime_mode == RuntimeMode.NATIVE:
# 原生内存使用较低
memory_mb = 25 + (time.time() - start_time) * 0.5
elif runtime_mode == RuntimeMode.CONTAINER_JVM:
# 容器 JVM
memory_mb = 180 + (time.time() - start_time) * 2.5
elif runtime_mode == RuntimeMode.CONTAINER_NATIVE:
# 容器原生
memory_mb = 35 + (time.time() - start_time) * 0.8
memory_samples.append(memory_mb)
metric = PerformanceMetric(
metric_type=MetricType.MEMORY_USAGE,
value=memory_mb,
unit="MB",
timestamp=time.time(),
runtime_mode=runtime_mode
)
self.metrics.append(metric)
time.sleep(self.config.memory_sample_interval)
self.monitoring = True
monitor_thread = threading.Thread(target=monitor_memory)
monitor_thread.start()
# 等待监控完成
time.sleep(duration)
self.monitoring = False
monitor_thread.join()
return memory_samples
def measure_response_time(self, runtime_mode: RuntimeMode, requests: int) -> List[float]:
"""测量响应时间"""
print(f"测量 {runtime_mode.value} 模式响应时间...")
response_times = []
for i in range(requests):
start_time = time.time()
# 模拟请求处理
if runtime_mode == RuntimeMode.JVM:
# JVM 响应时间
processing_time = 0.05 + (i % 10) * 0.01
elif runtime_mode == RuntimeMode.NATIVE:
# 原生响应时间
processing_time = 0.02 + (i % 10) * 0.005
else:
# 容器模式
processing_time = 0.08 + (i % 10) * 0.015
time.sleep(processing_time)
response_time = time.time() - start_time
response_times.append(response_time * 1000) # 转换为毫秒
metric = PerformanceMetric(
metric_type=MetricType.RESPONSE_TIME,
value=response_time * 1000,
unit="ms",
timestamp=time.time(),
runtime_mode=runtime_mode
)
self.metrics.append(metric)
return response_times
def run_benchmark(self) -> BenchmarkResult:
"""运行完整基准测试"""
print(f"开始性能基准测试: {self.config.app_name}")
start_time = time.time()
errors = []
try:
for runtime_mode in self.config.runtime_modes:
print(f"\n=== 测试 {runtime_mode.value} 模式 ===")
# 启动时间测试
startup_time = self.measure_startup_time(runtime_mode, "")
print(f"启动时间: {startup_time:.3f}s")
# 内存使用测试
memory_samples = self.measure_memory_usage(runtime_mode, 30)
avg_memory = sum(memory_samples) / len(memory_samples)
print(f"平均内存使用: {avg_memory:.1f}MB")
# 响应时间测试
response_times = self.measure_response_time(runtime_mode, 100)
avg_response = sum(response_times) / len(response_times)
print(f"平均响应时间: {avg_response:.2f}ms")
except Exception as e:
errors.append(str(e))
end_time = time.time()
return BenchmarkResult(
config=self.config,
metrics=self.metrics,
start_time=start_time,
end_time=end_time,
success=len(errors) == 0,
errors=errors
)
def generate_report(self, result: BenchmarkResult) -> str:
"""生成性能报告"""
report = f"""
=== Spring Native 性能基准测试报告 ===
应用名称: {result.config.app_name}
测试时间: {time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(result.start_time))}
测试时长: {result.end_time - result.start_time:.1f}s
测试状态: {'成功' if result.success else '失败'}
=== 性能对比 ===
"""
# 按运行时模式分组统计
mode_stats = {}
for metric in result.metrics:
mode = metric.runtime_mode
if mode not in mode_stats:
mode_stats[mode] = {}
metric_type = metric.metric_type
if metric_type not in mode_stats[mode]:
mode_stats[mode][metric_type] = []
mode_stats[mode][metric_type].append(metric.value)
# 生成对比表格
for mode, stats in mode_stats.items():
report += f"\n{mode.value.upper()} 模式:\n"
for metric_type, values in stats.items():
if values:
avg_value = sum(values) / len(values)
min_value = min(values)
max_value = max(values)
unit = "ms" if metric_type == MetricType.RESPONSE_TIME else \
"MB" if metric_type == MetricType.MEMORY_USAGE else "s"
report += f" {metric_type.value}: 平均 {avg_value:.2f}{unit}, "
report += f"最小 {min_value:.2f}{unit}, 最大 {max_value:.2f}{unit}\n"
if result.errors:
report += "\n=== 错误信息 ===\n"
for error in result.errors:
report += f"- {error}\n"
return report
# 使用示例
config = BenchmarkConfig(
app_name="spring-native-demo",
runtime_modes=[RuntimeMode.JVM, RuntimeMode.NATIVE],
test_duration=60,
concurrent_users=10
)
benchmark = PerformanceBenchmark(config)
result = benchmark.run_benchmark()
report = benchmark.generate_report(result)
print(report)
1.2 启动时间优化
// 启动时间优化配置
@SpringBootApplication
@EnableConfigurationProperties
public class OptimizedApplication {
public static void main(String[] args) {
// 启动时间优化
System.setProperty("spring.backgroundpreinitializer.ignore", "true");
System.setProperty("spring.jmx.enabled", "false");
System.setProperty("spring.main.lazy-initialization", "true");
SpringApplication app = new SpringApplication(OptimizedApplication.class);
// 禁用不必要的功能
app.setLazyInitialization(true);
app.setRegisterShutdownHook(false);
app.setLogStartupInfo(false);
// 设置启动监听器
app.addListeners(new StartupTimeListener());
app.run(args);
}
// 启动时间监听器
public static class StartupTimeListener implements ApplicationListener<ApplicationReadyEvent> {
private static final long startTime = System.currentTimeMillis();
@Override
public void onApplicationEvent(ApplicationReadyEvent event) {
long duration = System.currentTimeMillis() - startTime;
System.out.printf("应用启动完成,耗时: %d ms%n", duration);
// 记录启动指标
recordStartupMetrics(duration);
}
private void recordStartupMetrics(long duration) {
// 记录到监控系统
System.setProperty("app.startup.time", String.valueOf(duration));
// 输出详细信息
Runtime runtime = Runtime.getRuntime();
long totalMemory = runtime.totalMemory();
long freeMemory = runtime.freeMemory();
long usedMemory = totalMemory - freeMemory;
System.out.printf("启动后内存使用: %d MB%n", usedMemory / 1024 / 1024);
System.out.printf("可用处理器数: %d%n", runtime.availableProcessors());
}
}
}
1.3 内存使用优化
// 内存优化配置
@Configuration
@ConditionalOnProperty(name = "app.optimization.memory.enabled", havingValue = "true")
public class MemoryOptimizationConfig {
@Bean
@Primary
public ObjectMapper optimizedObjectMapper() {
return new ObjectMapper()
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false)
.setSerializationInclusion(JsonInclude.Include.NON_NULL)
.registerModule(new JavaTimeModule());
}
@Bean
public CacheManager optimizedCacheManager() {
CaffeineCacheManager cacheManager = new CaffeineCacheManager();
cacheManager.setCaffeine(Caffeine.newBuilder()
.maximumSize(1000)
.expireAfterWrite(Duration.ofMinutes(10))
.recordStats());
return cacheManager;
}
@Bean
@ConditionalOnMissingBean
public TaskExecutor optimizedTaskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(2);
executor.setMaxPoolSize(4);
executor.setQueueCapacity(100);
executor.setThreadNamePrefix("async-");
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.initialize();
return executor;
}
@EventListener
public void handleMemoryWarning(MemoryWarningEvent event) {
// 内存警告处理
System.gc(); // 建议垃圾回收
// 清理缓存
CacheManager cacheManager = event.getApplicationContext().getBean(CacheManager.class);
cacheManager.getCacheNames().forEach(name -> {
Cache cache = cacheManager.getCache(name);
if (cache != null) {
cache.clear();
}
});
}
// 内存监控
@Component
public static class MemoryMonitor {
private final ApplicationEventPublisher eventPublisher;
private final MeterRegistry meterRegistry;
public MemoryMonitor(ApplicationEventPublisher eventPublisher, MeterRegistry meterRegistry) {
this.eventPublisher = eventPublisher;
this.meterRegistry = meterRegistry;
// 注册内存指标
Gauge.builder("jvm.memory.used.ratio")
.register(meterRegistry, this, MemoryMonitor::getMemoryUsageRatio);
}
@Scheduled(fixedRate = 5000) // 每5秒检查一次
public void checkMemoryUsage() {
double usageRatio = getMemoryUsageRatio();
if (usageRatio > 0.8) { // 内存使用超过80%
eventPublisher.publishEvent(new MemoryWarningEvent(this, usageRatio));
}
}
private double getMemoryUsageRatio() {
Runtime runtime = Runtime.getRuntime();
long totalMemory = runtime.totalMemory();
long freeMemory = runtime.freeMemory();
return (double) (totalMemory - freeMemory) / totalMemory;
}
}
// 内存警告事件
public static class MemoryWarningEvent extends ApplicationEvent {
private final double usageRatio;
public MemoryWarningEvent(Object source, double usageRatio) {
super(source);
this.usageRatio = usageRatio;
}
public double getUsageRatio() {
return usageRatio;
}
public ApplicationContext getApplicationContext() {
return (ApplicationContext) getSource();
}
}
}
2. 监控集成
2.1 Micrometer 集成
// 监控配置
@Configuration
@EnableConfigurationProperties(MonitoringProperties.class)
public class MonitoringConfig {
@Bean
@ConditionalOnMissingBean
public MeterRegistry meterRegistry() {
return new PrometheusMeterRegistry(PrometheusConfig.DEFAULT);
}
@Bean
public TimedAspect timedAspect(MeterRegistry meterRegistry) {
return new TimedAspect(meterRegistry);
}
@Bean
public CountedAspect countedAspect(MeterRegistry meterRegistry) {
return new CountedAspect(meterRegistry);
}
// 自定义指标
@Bean
public ApplicationMetrics applicationMetrics(MeterRegistry meterRegistry) {
return new ApplicationMetrics(meterRegistry);
}
// JVM 指标
@Bean
public JvmMetrics jvmMetrics() {
return new JvmMetrics();
}
// 系统指标
@Bean
public SystemMetrics systemMetrics() {
return new SystemMetrics();
}
}
// 应用指标
@Component
public class ApplicationMetrics {
private final Counter requestCounter;
private final Timer responseTimer;
private final Gauge memoryGauge;
private final DistributionSummary requestSizeSummary;
public ApplicationMetrics(MeterRegistry meterRegistry) {
this.requestCounter = Counter.builder("http.requests.total")
.description("HTTP 请求总数")
.register(meterRegistry);
this.responseTimer = Timer.builder("http.request.duration")
.description("HTTP 请求处理时间")
.register(meterRegistry);
this.memoryGauge = Gauge.builder("application.memory.used")
.description("应用内存使用量")
.register(meterRegistry, this, ApplicationMetrics::getUsedMemory);
this.requestSizeSummary = DistributionSummary.builder("http.request.size")
.description("HTTP 请求大小分布")
.register(meterRegistry);
}
public void incrementRequestCount(String method, String uri, int status) {
requestCounter.increment(
Tags.of(
"method", method,
"uri", uri,
"status", String.valueOf(status)
)
);
}
public Timer.Sample startTimer() {
return Timer.start();
}
public void recordResponseTime(Timer.Sample sample, String method, String uri) {
sample.stop(responseTimer.tag("method", method).tag("uri", uri));
}
public void recordRequestSize(long size) {
requestSizeSummary.record(size);
}
private double getUsedMemory() {
Runtime runtime = Runtime.getRuntime();
return runtime.totalMemory() - runtime.freeMemory();
}
}
// 监控拦截器
@Component
public class MetricsInterceptor implements HandlerInterceptor {
private final ApplicationMetrics applicationMetrics;
private final ThreadLocal<Timer.Sample> timerSample = new ThreadLocal<>();
public MetricsInterceptor(ApplicationMetrics applicationMetrics) {
this.applicationMetrics = applicationMetrics;
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
Timer.Sample sample = applicationMetrics.startTimer();
timerSample.set(sample);
// 记录请求大小
long contentLength = request.getContentLengthLong();
if (contentLength > 0) {
applicationMetrics.recordRequestSize(contentLength);
}
return true;
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
Timer.Sample sample = timerSample.get();
if (sample != null) {
String method = request.getMethod();
String uri = request.getRequestURI();
int status = response.getStatus();
// 记录响应时间
applicationMetrics.recordResponseTime(sample, method, uri);
// 记录请求计数
applicationMetrics.incrementRequestCount(method, uri, status);
timerSample.remove();
}
}
}
2.2 健康检查
// 健康检查配置
@Component
public class CustomHealthIndicator implements HealthIndicator {
private final UserRepository userRepository;
private final RedisTemplate<String, String> redisTemplate;
public CustomHealthIndicator(UserRepository userRepository,
@Autowired(required = false) RedisTemplate<String, String> redisTemplate) {
this.userRepository = userRepository;
this.redisTemplate = redisTemplate;
}
@Override
public Health health() {
Health.Builder builder = new Health.Builder();
try {
// 检查数据库连接
checkDatabase(builder);
// 检查 Redis 连接
if (redisTemplate != null) {
checkRedis(builder);
}
// 检查内存使用
checkMemory(builder);
// 检查磁盘空间
checkDiskSpace(builder);
builder.up();
} catch (Exception e) {
builder.down(e);
}
return builder.build();
}
private void checkDatabase(Health.Builder builder) {
try {
long userCount = userRepository.count();
builder.withDetail("database", "UP")
.withDetail("userCount", userCount);
} catch (Exception e) {
builder.withDetail("database", "DOWN")
.withDetail("error", e.getMessage());
throw e;
}
}
private void checkRedis(Health.Builder builder) {
try {
redisTemplate.opsForValue().set("health:check", "OK", Duration.ofSeconds(10));
String result = redisTemplate.opsForValue().get("health:check");
if ("OK".equals(result)) {
builder.withDetail("redis", "UP");
} else {
builder.withDetail("redis", "DOWN")
.withDetail("error", "Redis 响应异常");
throw new RuntimeException("Redis 健康检查失败");
}
} catch (Exception e) {
builder.withDetail("redis", "DOWN")
.withDetail("error", e.getMessage());
throw e;
}
}
private void checkMemory(Health.Builder builder) {
Runtime runtime = Runtime.getRuntime();
long totalMemory = runtime.totalMemory();
long freeMemory = runtime.freeMemory();
long usedMemory = totalMemory - freeMemory;
double usageRatio = (double) usedMemory / totalMemory;
builder.withDetail("memory", Map.of(
"total", totalMemory / 1024 / 1024 + "MB",
"used", usedMemory / 1024 / 1024 + "MB",
"free", freeMemory / 1024 / 1024 + "MB",
"usage", String.format("%.2f%%", usageRatio * 100)
));
if (usageRatio > 0.9) {
throw new RuntimeException("内存使用率过高: " + String.format("%.2f%%", usageRatio * 100));
}
}
private void checkDiskSpace(Health.Builder builder) {
File root = new File("/");
long totalSpace = root.getTotalSpace();
long freeSpace = root.getFreeSpace();
long usedSpace = totalSpace - freeSpace;
double usageRatio = (double) usedSpace / totalSpace;
builder.withDetail("disk", Map.of(
"total", totalSpace / 1024 / 1024 / 1024 + "GB",
"used", usedSpace / 1024 / 1024 / 1024 + "GB",
"free", freeSpace / 1024 / 1024 / 1024 + "GB",
"usage", String.format("%.2f%%", usageRatio * 100)
));
if (usageRatio > 0.9) {
throw new RuntimeException("磁盘空间不足: " + String.format("%.2f%%", usageRatio * 100));
}
}
}
// 自定义健康检查端点
@RestController
@RequestMapping("/actuator")
public class CustomHealthController {
private final HealthEndpoint healthEndpoint;
private final ApplicationMetrics applicationMetrics;
public CustomHealthController(HealthEndpoint healthEndpoint, ApplicationMetrics applicationMetrics) {
this.healthEndpoint = healthEndpoint;
this.applicationMetrics = applicationMetrics;
}
@GetMapping("/health/detailed")
public ResponseEntity<Map<String, Object>> detailedHealth() {
HealthComponent health = healthEndpoint.health();
Map<String, Object> response = new HashMap<>();
response.put("status", health.getStatus().getCode());
response.put("timestamp", Instant.now());
response.put("details", health.getDetails());
// 添加运行时信息
Runtime runtime = Runtime.getRuntime();
response.put("runtime", Map.of(
"processors", runtime.availableProcessors(),
"totalMemory", runtime.totalMemory() / 1024 / 1024 + "MB",
"freeMemory", runtime.freeMemory() / 1024 / 1024 + "MB",
"maxMemory", runtime.maxMemory() / 1024 / 1024 + "MB"
));
// 添加应用信息
response.put("application", Map.of(
"name", "spring-native-demo",
"version", "1.0.0",
"profile", System.getProperty("spring.profiles.active", "default"),
"startTime", ManagementFactory.getRuntimeMXBean().getStartTime()
));
HttpStatus status = health.getStatus() == Status.UP ? HttpStatus.OK : HttpStatus.SERVICE_UNAVAILABLE;
return ResponseEntity.status(status).body(response);
}
@GetMapping("/metrics/summary")
public ResponseEntity<Map<String, Object>> metricsSummary() {
Map<String, Object> metrics = new HashMap<>();
// JVM 指标
MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean();
MemoryUsage heapUsage = memoryBean.getHeapMemoryUsage();
MemoryUsage nonHeapUsage = memoryBean.getNonHeapMemoryUsage();
metrics.put("jvm", Map.of(
"heap", Map.of(
"used", heapUsage.getUsed() / 1024 / 1024 + "MB",
"committed", heapUsage.getCommitted() / 1024 / 1024 + "MB",
"max", heapUsage.getMax() / 1024 / 1024 + "MB"
),
"nonHeap", Map.of(
"used", nonHeapUsage.getUsed() / 1024 / 1024 + "MB",
"committed", nonHeapUsage.getCommitted() / 1024 / 1024 + "MB"
),
"gc", getGcInfo()
));
// 系统指标
OperatingSystemMXBean osBean = ManagementFactory.getOperatingSystemMXBean();
metrics.put("system", Map.of(
"processors", osBean.getAvailableProcessors(),
"loadAverage", osBean.getSystemLoadAverage(),
"arch", osBean.getArch(),
"os", osBean.getName() + " " + osBean.getVersion()
));
return ResponseEntity.ok(metrics);
}
private Map<String, Object> getGcInfo() {
Map<String, Object> gcInfo = new HashMap<>();
for (GarbageCollectorMXBean gcBean : ManagementFactory.getGarbageCollectorMXBeans()) {
gcInfo.put(gcBean.getName(), Map.of(
"collectionCount", gcBean.getCollectionCount(),
"collectionTime", gcBean.getCollectionTime() + "ms"
));
}
return gcInfo;
}
}
3. 性能调优配置
3.1 应用配置优化
# application-performance.yml
spring:
application:
name: spring-native-demo
# 数据源优化
datasource:
hikari:
minimum-idle: 2
maximum-pool-size: 10
idle-timeout: 300000
max-lifetime: 1800000
connection-timeout: 20000
validation-timeout: 5000
leak-detection-threshold: 60000
# JPA 优化
jpa:
hibernate:
ddl-auto: none
properties:
hibernate:
jdbc:
batch_size: 20
fetch_size: 50
cache:
use_second_level_cache: true
use_query_cache: true
region:
factory_class: org.hibernate.cache.jcache.JCacheRegionFactory
order_inserts: true
order_updates: true
batch_versioned_data: true
# Web 优化
servlet:
multipart:
max-file-size: 10MB
max-request-size: 10MB
# 缓存配置
cache:
type: caffeine
caffeine:
spec: maximumSize=1000,expireAfterWrite=10m
# 异步配置
task:
execution:
pool:
core-size: 2
max-size: 4
queue-capacity: 100
keep-alive: 60s
thread-name-prefix: async-
scheduling:
pool:
size: 2
thread-name-prefix: scheduling-
# 监控配置
management:
endpoints:
web:
exposure:
include: health,info,metrics,prometheus
base-path: /actuator
endpoint:
health:
show-details: always
show-components: always
metrics:
enabled: true
metrics:
export:
prometheus:
enabled: true
distribution:
percentiles-histogram:
http.server.requests: true
percentiles:
http.server.requests: 0.5,0.9,0.95,0.99
# 日志配置
logging:
level:
com.example.demo: INFO
org.springframework: WARN
org.hibernate: WARN
pattern:
console: "%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n"
file: "%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n"
file:
name: logs/spring-native-demo.log
max-size: 100MB
max-history: 30
# 应用特定配置
app:
optimization:
memory:
enabled: true
startup:
lazy-initialization: true
cache:
enabled: true
ttl: 600 # 10分钟
performance:
monitoring:
enabled: true
interval: 5000 # 5秒
gc:
optimization: true
3.2 JVM 参数优化
#!/bin/bash
# jvm-tuning.sh - JVM 参数调优脚本
echo "=== JVM 参数调优配置 ==="
# 基础内存配置
JVM_MEMORY_OPTS="
-Xms512m
-Xmx1g
-XX:MetaspaceSize=128m
-XX:MaxMetaspaceSize=256m
-XX:CompressedClassSpaceSize=64m
"
# 垃圾收集器配置 (G1GC)
JVM_GC_OPTS="
-XX:+UseG1GC
-XX:MaxGCPauseMillis=200
-XX:G1HeapRegionSize=16m
-XX:G1NewSizePercent=30
-XX:G1MaxNewSizePercent=40
-XX:G1MixedGCCountTarget=8
-XX:InitiatingHeapOccupancyPercent=45
-XX:G1MixedGCLiveThresholdPercent=85
-XX:G1HeapWastePercent=5
"
# 性能优化配置
JVM_PERFORMANCE_OPTS="
-XX:+UnlockExperimentalVMOptions
-XX:+UseCGroupMemoryLimitForHeap
-XX:+UseStringDeduplication
-XX:+OptimizeStringConcat
-XX:+UseCompressedOops
-XX:+UseCompressedClassPointers
-XX:+TieredCompilation
-XX:TieredStopAtLevel=4
-XX:+UseCodeCacheFlushing
-XX:ReservedCodeCacheSize=128m
-XX:InitialCodeCacheSize=64m
"
# 诊断和监控配置
JVM_MONITORING_OPTS="
-XX:+PrintGC
-XX:+PrintGCDetails
-XX:+PrintGCTimeStamps
-XX:+PrintGCApplicationStoppedTime
-XX:+PrintStringDeduplicationStatistics
-Xloggc:logs/gc.log
-XX:+UseGCLogFileRotation
-XX:NumberOfGCLogFiles=5
-XX:GCLogFileSize=10M
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=logs/heapdump.hprof
-XX:+PrintCommandLineFlags
"
# 安全配置
JVM_SECURITY_OPTS="
-Djava.security.egd=file:/dev/./urandom
-Dfile.encoding=UTF-8
-Duser.timezone=Asia/Shanghai
"
# 网络配置
JVM_NETWORK_OPTS="
-Djava.net.preferIPv4Stack=true
-Dsun.net.useExclusiveBind=false
"
# 组合所有参数
JVM_OPTS="$JVM_MEMORY_OPTS $JVM_GC_OPTS $JVM_PERFORMANCE_OPTS $JVM_MONITORING_OPTS $JVM_SECURITY_OPTS $JVM_NETWORK_OPTS"
# 输出配置
echo "JVM 优化参数:"
echo "$JVM_OPTS" | tr ' ' '\n' | grep -v '^$' | sort
# 保存到文件
echo "$JVM_OPTS" > jvm-opts.txt
echo "JVM 参数已保存到 jvm-opts.txt"
# 生成启动脚本
cat > start-optimized.sh << EOF
#!/bin/bash
# 优化后的启动脚本
JAR_FILE="target/spring-native-demo-1.0.0.jar"
JVM_OPTS="$JVM_OPTS"
echo "使用优化参数启动应用..."
java \$JVM_OPTS -jar \$JAR_FILE
EOF
chmod +x start-optimized.sh
echo "优化启动脚本已生成: start-optimized.sh"
3.3 原生镜像优化参数
#!/bin/bash
# native-optimization.sh - 原生镜像优化参数
echo "=== 原生镜像优化配置 ==="
# 基础优化参数
NATIVE_BASE_OPTS="
--no-fallback
--install-exit-handlers
--enable-url-protocols=http,https
--enable-all-security-services
"
# 内存优化
NATIVE_MEMORY_OPTS="
-J-Xmx8g
-J-Xms4g
-J-XX:+UseG1GC
-J-XX:MaxGCPauseMillis=100
"
# 编译优化
NATIVE_COMPILE_OPTS="
-O3
--gc=G1
--enable-monitoring=heapdump,jfr
--verbose
--report-unsupported-elements-at-runtime
"
# 静态链接优化
NATIVE_STATIC_OPTS="
--static
--libc=musl
"
# 调试优化
NATIVE_DEBUG_OPTS="
-H:+ReportExceptionStackTraces
-H:+PrintAnalysisCallTree
-H:+PrintImageObjectTree
-H:PrintFlags=+
"
# 特定优化
NATIVE_SPECIFIC_OPTS="
-H:+RemoveUnusedSymbols
-H:+DeleteLocalSymbols
-H:+StripDebugInfo
-H:+CompactStrings
-H:+UseServiceLoaderFeature
-H:+InlineBeforeAnalysis
-H:MaxRuntimeCompileMethods=1000
"
# 反射优化
NATIVE_REFLECTION_OPTS="
-H:ReflectionConfigurationFiles=META-INF/native-image/reflect-config.json
-H:ResourceConfigurationFiles=META-INF/native-image/resource-config.json
-H:SerializationConfigurationFiles=META-INF/native-image/serialization-config.json
-H:DynamicProxyConfigurationFiles=META-INF/native-image/proxy-config.json
"
# 组合所有参数
NATIVE_OPTS="$NATIVE_BASE_OPTS $NATIVE_MEMORY_OPTS $NATIVE_COMPILE_OPTS $NATIVE_STATIC_OPTS $NATIVE_DEBUG_OPTS $NATIVE_SPECIFIC_OPTS $NATIVE_REFLECTION_OPTS"
# 输出配置
echo "原生镜像优化参数:"
echo "$NATIVE_OPTS" | tr ' ' '\n' | grep -v '^$' | sort
# 保存到文件
echo "$NATIVE_OPTS" > native-opts.txt
echo "原生镜像参数已保存到 native-opts.txt"
# 生成构建脚本
cat > build-optimized-native.sh << EOF
#!/bin/bash
# 优化的原生镜像构建脚本
set -e
APP_NAME="spring-native-demo"
MAIN_CLASS="com.example.demo.Application"
CLASSPATH="target/classes:target/lib/*"
NATIVE_OPTS="$NATIVE_OPTS"
echo "开始构建优化的原生镜像..."
# 清理之前的构建
rm -f target/\$APP_NAME
# 构建原生镜像
native-image \\\n --class-path \$CLASSPATH \\\n \$NATIVE_OPTS \\\n \$MAIN_CLASS \\\n target/\$APP_NAME
echo "原生镜像构建完成: target/\$APP_NAME"
# 显示文件信息
if [ -f "target/\$APP_NAME" ]; then
echo "文件大小: \$(du -h target/\$APP_NAME | cut -f1)"
echo "文件权限: \$(ls -l target/\$APP_NAME | cut -d' ' -f1)"
fi
EOF
chmod +x build-optimized-native.sh
echo "优化构建脚本已生成: build-optimized-native.sh"
# 生成性能测试脚本
cat > performance-test.sh << EOF
#!/bin/bash
# 性能测试脚本
set -e
APP_NAME="spring-native-demo"
JAR_FILE="target/\$APP_NAME-1.0.0.jar"
NATIVE_FILE="target/\$APP_NAME"
echo "=== 性能对比测试 ==="
# 测试 JAR 启动时间
if [ -f "\$JAR_FILE" ]; then
echo "测试 JAR 启动时间..."
time java -jar \$JAR_FILE --help > /dev/null 2>&1 || true
fi
# 测试原生镜像启动时间
if [ -f "\$NATIVE_FILE" ]; then
echo "测试原生镜像启动时间..."
time ./\$NATIVE_FILE --help > /dev/null 2>&1 || true
fi
# 文件大小对比
echo "\n=== 文件大小对比 ==="
if [ -f "\$JAR_FILE" ]; then
echo "JAR 文件: \$(du -h \$JAR_FILE | cut -f1)"
fi
if [ -f "\$NATIVE_FILE" ]; then
echo "原生镜像: \$(du -h \$NATIVE_FILE | cut -f1)"
fi
EOF
chmod +x performance-test.sh
echo "性能测试脚本已生成: performance-test.sh"
通过本章的学习,你已经掌握了 Spring Native 的性能调优和监控方法。接下来我们将学习容器化部署和生产环境最佳实践。