Java虚拟线程实战指南 - 第4部分:生产环境部署指南

生产环境部署策略

在生产环境中部署虚拟线程应用需要谨慎规划。基于我的实际部署经验,这里分享一套完整的部署策略。

渐进式部署方案

@Configuration
@EnableConfigurationProperties(DeploymentConfig.class)
@Slf4j
public class VirtualThreadDeploymentConfiguration {

    private final DeploymentConfig deploymentConfig;

    public VirtualThreadDeploymentConfiguration(DeploymentConfig deploymentConfig) {
        this.deploymentConfig = deploymentConfig;
    }

    /**
     * 渐进式虚拟线程启用策略
     * 根据部署阶段逐步启用虚拟线程功能
     */
    @Bean
    @ConditionalOnProperty(name = "deployment.virtual-threads.strategy", havingValue = "progressive")
    public VirtualThreadDeploymentManager progressiveDeploymentManager() {
        return new VirtualThreadDeploymentManager(deploymentConfig);
    }

    /**
     * 蓝绿部署支持
     */
    @Bean
    @ConditionalOnProperty(name = "deployment.strategy", havingValue = "blue-green")
    public BlueGreenDeploymentController blueGreenController() {
        return new BlueGreenDeploymentController(deploymentConfig);
    }

    /**
     * 金丝雀部署支持
     */
    @Bean
    @ConditionalOnProperty(name = "deployment.strategy", havingValue = "canary")
    public CanaryDeploymentController canaryController() {
        return new CanaryDeploymentController(deploymentConfig);
    }
}

@Component
@Slf4j
public class VirtualThreadDeploymentManager {

    private final DeploymentConfig config;
    private final AtomicReference<DeploymentPhase> currentPhase;
    private final MeterRegistry meterRegistry;

    public VirtualThreadDeploymentManager(DeploymentConfig config) {
        this.config = config;
        this.currentPhase = new AtomicReference<>(DeploymentPhase.TRADITIONAL);
        this.meterRegistry = Metrics.globalRegistry;
    }

    /**
     * 启动渐进式部署
     */
    @EventListener(ApplicationReadyEvent.class)
    public void startProgressiveDeployment() {
        if (!config.getVirtualThreads().isProgressiveEnabled()) {
            return;
        }

        log.info("启动虚拟线程渐进式部署");

        // 阶段1:传统线程池(基线)
        schedulePhaseTransition(DeploymentPhase.TRADITIONAL, Duration.ofMinutes(5));

        // 阶段2:部分启用虚拟线程(10%流量)
        schedulePhaseTransition(DeploymentPhase.PARTIAL_VIRTUAL, Duration.ofMinutes(15));

        // 阶段3:大部分启用虚拟线程(50%流量)
        schedulePhaseTransition(DeploymentPhase.MOSTLY_VIRTUAL, Duration.ofMinutes(30));

        // 阶段4:完全启用虚拟线程(100%流量)
        schedulePhaseTransition(DeploymentPhase.FULL_VIRTUAL, Duration.ofMinutes(60));
    }

    private void schedulePhaseTransition(DeploymentPhase phase, Duration delay) {
        CompletableFuture.delayedExecutor(delay.toMillis(), TimeUnit.MILLISECONDS)
            .execute(() -> transitionToPhase(phase));
    }

    /**
     * 阶段转换逻辑
     */
    private void transitionToPhase(DeploymentPhase targetPhase) {
        var currentPhaseValue = currentPhase.get();

        log.info("准备从阶段 {} 转换到阶段 {}", currentPhaseValue, targetPhase);

        // 检查当前阶段的健康状况
        var healthCheck = performHealthCheck(currentPhaseValue);
        if (!healthCheck.isHealthy()) {
            log.error("健康检查失败,停止阶段转换: {}", healthCheck.getIssues());
            rollbackToPreviousPhase();
            return;
        }

        // 执行阶段转换
        try {
            executePhaseTransition(targetPhase);
            currentPhase.set(targetPhase);

            log.info("成功转换到阶段: {}", targetPhase);
            recordPhaseTransition(targetPhase, true);

        } catch (Exception e) {
            log.error("阶段转换失败", e);
            recordPhaseTransition(targetPhase, false);
            rollbackToPreviousPhase();
        }
    }

    /**
     * 执行具体的阶段转换
     */
    private void executePhaseTransition(DeploymentPhase phase) {
        switch (phase) {
            case TRADITIONAL -> configureTraditionalThreads();
            case PARTIAL_VIRTUAL -> configurePartialVirtualThreads();
            case MOSTLY_VIRTUAL -> configureMostlyVirtualThreads();
            case FULL_VIRTUAL -> configureFullVirtualThreads();
        }
    }

    private void configureTraditionalThreads() {
        // 配置传统线程池
        log.info("配置传统线程池模式");
        System.setProperty("spring.threads.virtual.enabled", "false");
    }

    private void configurePartialVirtualThreads() {
        // 10%的请求使用虚拟线程
        log.info("配置部分虚拟线程模式(10%流量)");
        System.setProperty("spring.threads.virtual.enabled", "true");
        System.setProperty("app.virtual-threads.traffic-percentage", "10");
    }

    private void configureMostlyVirtualThreads() {
        // 50%的请求使用虚拟线程
        log.info("配置大部分虚拟线程模式(50%流量)");
        System.setProperty("app.virtual-threads.traffic-percentage", "50");
    }

    private void configureFullVirtualThreads() {
        // 100%的请求使用虚拟线程
        log.info("配置完全虚拟线程模式(100%流量)");
        System.setProperty("app.virtual-threads.traffic-percentage", "100");
    }

    /**
     * 健康检查
     */
    private HealthCheckResult performHealthCheck(DeploymentPhase phase) {
        var issues = new ArrayList<String>();

        // 检查响应时间
        var avgResponseTime = getAverageResponseTime();
        if (avgResponseTime.toMillis() > config.getHealthCheck().getMaxResponseTimeMs()) {
            issues.add("平均响应时间过高: " + avgResponseTime.toMillis() + "ms");
        }

        // 检查错误率
        var errorRate = getErrorRate();
        if (errorRate > config.getHealthCheck().getMaxErrorRate()) {
            issues.add("错误率过高: " + String.format("%.2f%%", errorRate * 100));
        }

        // 检查内存使用
        var memoryUsage = getMemoryUsage();
        if (memoryUsage > config.getHealthCheck().getMaxMemoryUsage()) {
            issues.add("内存使用率过高: " + String.format("%.1f%%", memoryUsage * 100));
        }

        // 检查线程固定情况
        var pinningRate = getThreadPinningRate();
        if (pinningRate > config.getHealthCheck().getMaxPinningRate()) {
            issues.add("线程固定率过高: " + String.format("%.2f%%", pinningRate * 100));
        }

        return HealthCheckResult.builder()
            .phase(phase)
            .isHealthy(issues.isEmpty())
            .issues(issues)
            .timestamp(Instant.now())
            .build();
    }

    private void rollbackToPreviousPhase() {
        var current = currentPhase.get();
        var previous = getPreviousPhase(current);

        log.warn("回滚到前一阶段: {} -> {}", current, previous);

        try {
            executePhaseTransition(previous);
            currentPhase.set(previous);
            recordRollback(current, previous);
        } catch (Exception e) {
            log.error("回滚失败", e);
        }
    }

    private DeploymentPhase getPreviousPhase(DeploymentPhase current) {
        return switch (current) {
            case FULL_VIRTUAL -> DeploymentPhase.MOSTLY_VIRTUAL;
            case MOSTLY_VIRTUAL -> DeploymentPhase.PARTIAL_VIRTUAL;
            case PARTIAL_VIRTUAL -> DeploymentPhase.TRADITIONAL;
            case TRADITIONAL -> DeploymentPhase.TRADITIONAL;
        };
    }

    // 监控指标收集方法
    private Duration getAverageResponseTime() {
        // 实际实现需要从监控系统获取
        return Duration.ofMillis((long) (Math.random() * 1000));
    }

    private double getErrorRate() {
        // 实际实现需要从监控系统获取
        return Math.random() * 0.1; // 0-10%
    }

    private double getMemoryUsage() {
        var runtime = Runtime.getRuntime();
        return (double) (runtime.totalMemory() - runtime.freeMemory()) / runtime.maxMemory();
    }

    private double getThreadPinningRate() {
        // 实际实现需要分析JFR数据
        return Math.random() * 0.05; // 0-5%
    }

    private void recordPhaseTransition(DeploymentPhase phase, boolean success) {
        meterRegistry.counter("deployment.phase.transition",
            "phase", phase.name(),
            "success", String.valueOf(success))
            .increment();
    }

    private void recordRollback(DeploymentPhase from, DeploymentPhase to) {
        meterRegistry.counter("deployment.rollback",
            "from", from.name(),
            "to", to.name())
            .increment();
    }

    // 数据类定义
    public enum DeploymentPhase {
        TRADITIONAL, PARTIAL_VIRTUAL, MOSTLY_VIRTUAL, FULL_VIRTUAL
    }

    @Builder
    public record HealthCheckResult(
        DeploymentPhase phase,
        boolean isHealthy,
        List<String> issues,
        Instant timestamp
    ) {}
}

容器化部署优化

@Configuration
@Slf4j
public class ContainerOptimizationConfiguration {

    /**
     * 容器环境下的虚拟线程优化配置
     */
    @Bean
    @ConditionalOnProperty(name = "deployment.environment", havingValue = "container")
    public ContainerOptimizer containerOptimizer() {
        return new ContainerOptimizer();
    }
}

@Component
@Slf4j
public class ContainerOptimizer {

    /**
     * 容器启动时的优化配置
     */
    @EventListener(ApplicationReadyEvent.class)
    public void optimizeForContainer() {
        log.info("开始容器环境优化配置");

        // 检测容器资源限制
        var containerResources = detectContainerResources();
        log.info("检测到容器资源: {}", containerResources);

        // 优化JVM参数
        optimizeJvmParameters(containerResources);

        // 优化虚拟线程配置
        optimizeVirtualThreadConfiguration(containerResources);

        // 配置健康检查
        configureHealthChecks();

        log.info("容器环境优化配置完成");
    }

    /**
     * 检测容器资源限制
     */
    private ContainerResources detectContainerResources() {
        var runtime = Runtime.getRuntime();

        // 检测CPU限制
        var availableProcessors = runtime.availableProcessors();

        // 检测内存限制
        var maxMemory = runtime.maxMemory();

        // 检测是否在容器中运行
        var isInContainer = detectContainerEnvironment();

        // 读取容器资源限制(如果可用)
        var cpuLimit = readCpuLimit();
        var memoryLimit = readMemoryLimit();

        return ContainerResources.builder()
            .isInContainer(isInContainer)
            .availableProcessors(availableProcessors)
            .maxMemory(maxMemory)
            .cpuLimit(cpuLimit)
            .memoryLimit(memoryLimit)
            .build();
    }

    private boolean detectContainerEnvironment() {
        // 检查常见的容器环境标识
        return System.getenv("KUBERNETES_SERVICE_HOST") != null ||
               System.getenv("DOCKER_CONTAINER") != null ||
               Files.exists(Paths.get("/.dockerenv"));
    }

    private Optional<Double> readCpuLimit() {
        try {
            // 读取cgroup CPU限制
            var cpuQuotaPath = Paths.get("/sys/fs/cgroup/cpu/cpu.cfs_quota_us");
            var cpuPeriodPath = Paths.get("/sys/fs/cgroup/cpu/cpu.cfs_period_us");

            if (Files.exists(cpuQuotaPath) && Files.exists(cpuPeriodPath)) {
                var quota = Long.parseLong(Files.readString(cpuQuotaPath).trim());
                var period = Long.parseLong(Files.readString(cpuPeriodPath).trim());

                if (quota > 0) {
                    return Optional.of((double) quota / period);
                }
            }
        } catch (Exception e) {
            log.debug("无法读取CPU限制", e);
        }

        return Optional.empty();
    }

    private Optional<Long> readMemoryLimit() {
        try {
            // 读取cgroup内存限制
            var memoryLimitPath = Paths.get("/sys/fs/cgroup/memory/memory.limit_in_bytes");

            if (Files.exists(memoryLimitPath)) {
                var limit = Long.parseLong(Files.readString(memoryLimitPath).trim());

                // 检查是否是实际限制(不是默认的巨大值)
                if (limit < Long.MAX_VALUE / 2) {
                    return Optional.of(limit);
                }
            }
        } catch (Exception e) {
            log.debug("无法读取内存限制", e);
        }

        return Optional.empty();
    }

    /**
     * 优化JVM参数
     */
    private void optimizeJvmParameters(ContainerResources resources) {
        if (!resources.isInContainer()) {
            return;
        }

        var recommendations = new ArrayList<String>();

        // CPU相关优化
        if (resources.cpuLimit().isPresent()) {
            var cpuLimit = resources.cpuLimit().get();
            var recommendedParallelism = Math.max(1, (int) Math.ceil(cpuLimit));

            System.setProperty("jdk.virtualThreadScheduler.parallelism",
                String.valueOf(recommendedParallelism));

            recommendations.add("设置虚拟线程调度器并行度: " + recommendedParallelism);
        }

        // 内存相关优化
        if (resources.memoryLimit().isPresent()) {
            var memoryLimit = resources.memoryLimit().get();
            var recommendedMaxPoolSize = Math.min(256, (int) (memoryLimit / (1024 * 1024 * 8))); // 8MB per carrier thread

            System.setProperty("jdk.virtualThreadScheduler.maxPoolSize",
                String.valueOf(recommendedMaxPoolSize));

            recommendations.add("设置最大载体线程池大小: " + recommendedMaxPoolSize);
        }

        log.info("JVM参数优化建议: {}", recommendations);
    }

    /**
     * 优化虚拟线程配置
     */
    private void optimizeVirtualThreadConfiguration(ContainerResources resources) {
        // 根据容器资源调整虚拟线程配置
        var config = VirtualThreadContainerConfig.builder()
            .maxConcurrentTasks(calculateMaxConcurrentTasks(resources))
            .taskQueueSize(calculateTaskQueueSize(resources))
            .monitoringInterval(Duration.ofSeconds(30))
            .build();

        log.info("虚拟线程容器配置: {}", config);
    }

    private int calculateMaxConcurrentTasks(ContainerResources resources) {
        // 基于可用内存计算最大并发任务数
        var maxMemory = resources.maxMemory();
        var estimatedTaskMemory = 1024 * 1024; // 假设每个任务占用1MB内存

        return (int) Math.min(100000, maxMemory / estimatedTaskMemory / 10); // 保留90%内存给其他用途
    }

    private int calculateTaskQueueSize(ContainerResources resources) {
        // 基于CPU核心数计算任务队列大小
        return resources.availableProcessors() * 1000;
    }

    /**
     * 配置容器健康检查
     */
    private void configureHealthChecks() {
        // 配置Kubernetes就绪探针
        configureReadinessProbe();

        // 配置Kubernetes存活探针
        configureLivenessProbe();

        // 配置启动探针
        configureStartupProbe();
    }

    private void configureReadinessProbe() {
        // 就绪探针检查应用是否准备好接收流量
        log.info("配置就绪探针: /actuator/health/readiness");
    }

    private void configureLivenessProbe() {
        // 存活探针检查应用是否还在运行
        log.info("配置存活探针: /actuator/health/liveness");
    }

    private void configureStartupProbe() {
        // 启动探针给应用更多时间来启动
        log.info("配置启动探针: /actuator/health/startup");
    }

    // 数据类定义
    @Builder
    public record ContainerResources(
        boolean isInContainer,
        int availableProcessors,
        long maxMemory,
        Optional<Double> cpuLimit,
        Optional<Long> memoryLimit
    ) {}

    @Builder
    public record VirtualThreadContainerConfig(
        int maxConcurrentTasks,
        int taskQueueSize,
        Duration monitoringInterval
    ) {}
}

Kubernetes部署配置

# kubernetes-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: virtual-thread-app
  labels:
    app: virtual-thread-app
    version: v1
spec:
  replicas: 3
  selector:
    matchLabels:
      app: virtual-thread-app
  template:
    metadata:
      labels:
        app: virtual-thread-app
        version: v1
    spec:
      containers:
      - name: app
        image: your-registry/virtual-thread-app:latest
        ports:
        - containerPort: 8080

        # 资源限制 - 关键配置
        resources:
          requests:
            memory: "2Gi"
            cpu: "1000m"
          limits:
            memory: "4Gi"
            cpu: "2000m"

        # JVM参数优化
        env:
        - name: JAVA_OPTS
          value: >-
            -server
            -Xms2g -Xmx3g
            -XX:+UseZGC
            -XX:+UnlockExperimentalVMOptions
            -Djdk.virtualThreadScheduler.parallelism=16
            -Djdk.virtualThreadScheduler.maxPoolSize=128
            -XX:+FlightRecorder
            -XX:StartFlightRecording=duration=300s,filename=/tmp/app-performance.jfr

        # 健康检查配置
        readinessProbe:
          httpGet:
            path: /actuator/health/readiness
            port: 8080
          initialDelaySeconds: 30
          periodSeconds: 10
          timeoutSeconds: 5
          failureThreshold: 3

        livenessProbe:
          httpGet:
            path: /actuator/health/liveness
            port: 8080
          initialDelaySeconds: 60
          periodSeconds: 30
          timeoutSeconds: 10
          failureThreshold: 3

        startupProbe:
          httpGet:
            path: /actuator/health/startup
            port: 8080
          initialDelaySeconds: 10
          periodSeconds: 5
          timeoutSeconds: 3
          failureThreshold: 30

        # 卷挂载
        volumeMounts:
        - name: jfr-data
          mountPath: /tmp
        - name: config
          mountPath: /app/config

      volumes:
      - name: jfr-data
        emptyDir: {}
      - name: config
        configMap:
          name: virtual-thread-config

---
apiVersion: v1
kind: Service
metadata:
  name: virtual-thread-service
spec:
  selector:
    app: virtual-thread-app
  ports:
  - protocol: TCP
    port: 80
    targetPort: 8080
  type: ClusterIP

---
apiVersion: v1
kind: ConfigMap
metadata:
  name: virtual-thread-config
data:
  application.yml: |
    spring:
      threads:
        virtual:
          enabled: true

    app:
      virtual-threads:
        web:
          enabled: true
          max-connections: 10000
        async:
          enabled: true
        scheduled:
          enabled: true
          core-pool-size: 5

    management:
      endpoints:
        web:
          exposure:
            include: health,metrics,prometheus
      endpoint:
        health:
          probes:
            enabled: true
          show-details: always
      metrics:
        export:
          prometheus:
            enabled: true

---
# HorizontalPodAutoscaler for auto-scaling
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: virtual-thread-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: virtual-thread-app
  minReplicas: 3
  maxReplicas: 20
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70
  - type: Resource
    resource:
      name: memory
      target:
        type: Utilization
        averageUtilization: 80
  behavior:
    scaleUp:
      stabilizationWindowSeconds: 60
      policies:
      - type: Percent
        value: 100
        periodSeconds: 15
    scaleDown:
      stabilizationWindowSeconds: 300
      policies:
      - type: Percent
        value: 10
        periodSeconds: 60

监控和告警配置

@Component
@Slf4j
public class ProductionMonitoringSetup {

    private final MeterRegistry meterRegistry;
    private final NotificationService notificationService;

    /**
     * 生产环境监控配置
     */
    @PostConstruct
    public void setupProductionMonitoring() {
        log.info("配置生产环境监控");

        // 配置关键指标监控
        setupKeyMetricsMonitoring();

        // 配置告警规则
        setupAlertingRules();

        // 配置仪表板
        setupDashboards();

        log.info("生产环境监控配置完成");
    }

    /**
     * 关键指标监控
     */
    private void setupKeyMetricsMonitoring() {
        // 虚拟线程数量监控
        Gauge.builder("app.virtual.threads.active")
            .description("当前活跃的虚拟线程数量")
            .register(meterRegistry, this, ProductionMonitoringSetup::getActiveVirtualThreadCount);

        // 载体线程池监控
        Gauge.builder("app.virtual.threads.carrier.pool.size")
            .description("载体线程池大小")
            .register(meterRegistry, this, ProductionMonitoringSetup::getCarrierThreadPoolSize);

        // 线程固定率监控
        Gauge.builder("app.virtual.threads.pinning.rate")
            .description("线程固定率")
            .register(meterRegistry, this, ProductionMonitoringSetup::getThreadPinningRate);

        // 任务队列长度监控
        Gauge.builder("app.virtual.threads.queue.size")
            .description("任务队列长度")
            .register(meterRegistry, this, ProductionMonitoringSetup::getTaskQueueSize);
    }

    /**
     * 告警规则配置
     */
    private void setupAlertingRules() {
        // 高内存使用率告警
        scheduleAlert("memory_usage_high", Duration.ofMinutes(1), () -> {
            var memoryUsage = getMemoryUsagePercentage();
            if (memoryUsage > 85) {
                return AlertCondition.builder()
                    .triggered(true)
                    .severity(AlertSeverity.WARNING)
                    .message("内存使用率过高: " + String.format("%.1f%%", memoryUsage))
                    .build();
            }
            return AlertCondition.notTriggered();
        });

        // 线程固定率告警
        scheduleAlert("thread_pinning_high", Duration.ofMinutes(2), () -> {
            var pinningRate = getThreadPinningRate();
            if (pinningRate > 0.1) { // 10%
                return AlertCondition.builder()
                    .triggered(true)
                    .severity(AlertSeverity.CRITICAL)
                    .message("线程固定率过高: " + String.format("%.2f%%", pinningRate * 100))
                    .build();
            }
            return AlertCondition.notTriggered();
        });

        // 响应时间告警
        scheduleAlert("response_time_high", Duration.ofMinutes(1), () -> {
            var avgResponseTime = getAverageResponseTime();
            if (avgResponseTime.toMillis() > 5000) { // 5秒
                return AlertCondition.builder()
                    .triggered(true)
                    .severity(AlertSeverity.WARNING)
                    .message("平均响应时间过高: " + avgResponseTime.toMillis() + "ms")
                    .build();
            }
            return AlertCondition.notTriggered();
        });
    }

    private void scheduleAlert(String alertName, Duration interval, Supplier<AlertCondition> condition) {
        var scheduler = Executors.newScheduledThreadPool(1);

        scheduler.scheduleAtFixedRate(() -> {
            try {
                var alert = condition.get();
                if (alert.isTriggered()) {
                    handleAlert(alertName, alert);
                }
            } catch (Exception e) {
                log.error("告警检查失败: {}", alertName, e);
            }
        }, 0, interval.toSeconds(), TimeUnit.SECONDS);
    }

    private void handleAlert(String alertName, AlertCondition condition) {
        log.warn("触发告警: {} - {}", alertName, condition.message());

        // 发送通知
        var alert = Alert.builder()
            .name(alertName)
            .severity(condition.severity())
            .message(condition.message())
            .timestamp(Instant.now())
            .build();

        notificationService.sendAlert(alert);

        // 记录告警指标
        meterRegistry.counter("app.alerts.triggered", "alert", alertName).increment();
    }

    /**
     * 仪表板配置
     */
    private void setupDashboards() {
        // 这里可以配置Grafana仪表板或其他监控仪表板
        log.info("配置监控仪表板");

        // 导出Prometheus指标
        exportPrometheusMetrics();
    }

    private void exportPrometheusMetrics() {
        // 配置Prometheus指标导出
        log.info("配置Prometheus指标导出");
    }

    // 指标收集方法
    private double getActiveVirtualThreadCount() {
        return Thread.getAllStackTraces().keySet().stream()
            .mapToDouble(thread -> thread.isVirtual() ? 1 : 0)
            .sum();
    }

    private double getCarrierThreadPoolSize() {
        // 实际实现需要访问内部API
        return Runtime.getRuntime().availableProcessors() * 2;
    }

    private double getThreadPinningRate() {
        // 实际实现需要分析JFR数据
        return Math.random() * 0.05; // 模拟数据
    }

    private double getTaskQueueSize() {
        // 实际实现需要访问任务队列
        return Math.random() * 1000; // 模拟数据
    }

    private double getMemoryUsagePercentage() {
        var runtime = Runtime.getRuntime();
        return (double) (runtime.totalMemory() - runtime.freeMemory()) / runtime.maxMemory() * 100;
    }

    private Duration getAverageResponseTime() {
        // 实际实现需要从监控系统获取
        return Duration.ofMillis((long) (Math.random() * 2000));
    }

    // 数据类定义
    @Builder
    public record AlertCondition(
        boolean triggered,
        AlertSeverity severity,
        String message
    ) {
        public static AlertCondition notTriggered() {
            return new AlertCondition(false, null, null);
        }

        public boolean isTriggered() {
            return triggered;
        }
    }

    @Builder
    public record Alert(
        String name,
        AlertSeverity severity,
        String message,
        Instant timestamp
    ) {}

    public enum AlertSeverity {
        INFO, WARNING, CRITICAL
    }
}


本文为第4部分,详细介绍了虚拟线程在生产环境中的部署策略。

关键要点:

  • 采用渐进式部署策略,逐步启用虚拟线程
  • 针对容器环境进行专门优化
  • 配置完整的Kubernetes部署文件
  • 建立全面的监控和告警体系
  • 重视健康检查和自动扩缩容

接下来的最后一部分将包含:

  • 第5部分:实际案例分析与总结