CPU 100% 案例排查实战指南

jstack+top+profiler三件套与代码问题反推方法论

📋 目录

  • 🚨 一、CPU 100%问题全景分析
  • 🔧 二、排查工具三件套深度使用
  • 🔁 三、死循环模式识别与定位
  • 🔒 四、锁竞争导致的CPU飙升
  • ♻️ 五、GC压力导致的CPU打满
  • 🔄 六、从CPU视角反推代码问题
  • 🚀 七、生产环境防御体系

🚨 一、CPU 100%问题全景分析

💡 CPU问题的四种根源

CPU 100%问题分类体系

CPU 100%问题
计算密集型
锁密集型
IO密集型
系统资源型
死循环
算法低效
无限递归
锁竞争
死锁
活锁
同步阻塞
资源等待
网络延迟
GC压力
上下文切换
内存缺页

🎯 CPU问题诊断框架

/**
 * CPU 100%诊断与分析框架
 * 系统化的问题定位体系
 */
@Component
@Slf4j
public class CPUDiagnosisFramework {
    
    /**
     * CPU诊断配置
     */
    @Data
    @Builder
    public static class CPUDiagnosisConfig {
        private final int sampleCount;          // 采样次数
        private final int sampleInterval;       // 采样间隔(ms)
        private final int topThreadCount;      // top线程数
        private final boolean includeGC;       // 包含GC分析
        private final boolean includeSystem;   // 包含系统分析
        private final String outputPath;       // 输出路径
        
        /**
         * 紧急诊断配置
         */
        public static CPUDiagnosisConfig emergencyConfig() {
            return CPUDiagnosisConfig.builder()
                .sampleCount(10)               // 快速采样10次
                .sampleInterval(1000)          // 每秒1次
                .topThreadCount(20)            // 查看前20个线程
                .includeGC(true)               // 包含GC分析
                .includeSystem(true)           // 包含系统分析
                .outputPath("/data/cpu-diagnosis")
                .build();
        }
        
        /**
         * 深度诊断配置
         */
        public static CPUDiagnosisConfig deepConfig() {
            return CPUDiagnosisConfig.builder()
                .sampleCount(30)               // 采样30次
                .sampleInterval(2000)          // 每2秒1次
                .topThreadCount(50)            // 查看前50个线程
                .includeGC(true)
                .includeSystem(true)
                .outputPath("/data/deep-diagnosis")
                .build();
        }
    }
    
    /**
     * CPU诊断引擎
     */
    @Component
    @Slf4j
    public class CPUDiagnosisEngine {
        private final ProcessInspector processInspector;
        private final ThreadAnalyzer threadAnalyzer;
        private final GCAnalyzer gcAnalyzer;
        private final SystemMonitor systemMonitor;
        
        /**
         * CPU问题诊断入口
         */
        public class CPUDiagnosisEntry {
            /**
             * 诊断CPU 100%问题
             */
            public CPUDiagnosisResult diagnoseCPU100(int pid, CPUDiagnosisConfig config) {
                long startTime = System.currentTimeMillis();
                
                try {
                    log.error("CPU 100%诊断开始: pid={}, time={}", 
                            pid, new Date(startTime));
                    
                    // 1. 收集诊断数据
                    CPUDiagnosisData data = collectDiagnosisData(pid, config);
                    
                    // 2. 分析问题根因
                    CPURootCause rootCause = analyzeRootCause(data, config);
                    
                    // 3. 生成修复建议
                    List<FixSuggestion> suggestions = generateFixSuggestions(rootCause);
                    
                    // 4. 生成诊断报告
                    CPUDiagnosisReport report = generateReport(data, rootCause, suggestions);
                    
                    long cost = System.currentTimeMillis() - startTime;
                    log.info("CPU诊断完成: cost={}ms, cause={}, confidence={}", 
                            cost, rootCause.getCategory(), rootCause.getConfidence());
                    
                    return CPUDiagnosisResult.success(report);
                    
                } catch (Exception e) {
                    log.error("CPU诊断失败", e);
                    return CPUDiagnosisResult.error("诊断失败: " + e.getMessage());
                }
            }
            
            /**
             * 收集诊断数据
             */
            private CPUDiagnosisData collectDiagnosisData(int pid, CPUDiagnosisConfig config) {
                CPUDiagnosisData data = new CPUDiagnosisData();
                
                // 1. 使用top命令收集进程CPU使用
                data.setProcessCpuUsage(processInspector.collectProcessCpu(pid, config));
                
                // 2. 收集线程级CPU使用
                data.setThreadCpuUsage(threadAnalyzer.collectThreadCpu(pid, config));
                
                // 3. 收集GC情况
                if (config.isIncludeGC()) {
                    data.setGcData(gcAnalyzer.collectGCMetrics(pid, config));
                }
                
                // 4. 收集系统指标
                if (config.isIncludeSystem()) {
                    data.setSystemMetrics(systemMonitor.collectSystemMetrics(config));
                }
                
                // 5. 收集jstack信息
                data.setThreadDumps(collectThreadDumps(pid, config));
                
                return data;
            }
            
            /**
             * 分析根因
             */
            private CPURootCause analyzeRootCause(CPUDiagnosisData data, CPUDiagnosisConfig config) {
                CPURootCause cause = new CPURootCause();
                
                // 1. 分析是否为GC导致
                if (isGCInducedCPU(data)) {
                    cause = analyzeGCInducedCPU(data);
                    return cause;
                }
                
                // 2. 分析线程热点
                ThreadHotspot hotspot = findThreadHotspot(data);
                
                // 3. 根据线程状态分析原因
                cause = analyzeByThreadState(hotspot, data);
                
                // 4. 计算置信度
                cause.setConfidence(calculateConfidence(cause, data));
                
                return cause;
            }
        }
        
        /**
         * 根本原因分类器
         */
        @Component
        @Slj4
        public class RootCauseClassifier {
            private final PatternMatcher patternMatcher;
            private final CallStackAnalyzer stackAnalyzer;
            
            /**
             * 根据线程状态分析原因
             */
            public class ThreadStateAnalyzer {
                /**
                 * 分析线程状态判断原因
                 */
                public CPURootCause analyzeByThreadState(ThreadHotspot hotspot, CPUDiagnosisData data) {
                    CPURootCause cause = new CPURootCause();
                    
                    // 1. RUNNABLE状态的CPU热点
                    if (hotspot.getState() == Thread.State.RUNNABLE) {
                        String stackTrace = hotspot.getStackTrace();
                        
                        if (isInfiniteLoop(stackTrace)) {
                            cause.setCategory(CPUCategory.INFINITE_LOOP);
                            cause.setDescription("检测到死循环");
                            cause.setConfidence(0.9);
                        } else if (isAlgorithmInefficient(stackTrace)) {
                            cause.setCategory(CPUCategory.INEFFICIENT_ALGORITHM);
                            cause.setDescription("算法效率低下");
                            cause.setConfidence(0.8);
                        } else if (isRecursiveLoop(stackTrace)) {
                            cause.setCategory(CPUCategory.RECURSIVE_LOOP);
                            cause.setDescription("无限递归");
                            cause.setConfidence(0.85);
                        } else {
                            cause.setCategory(CPUCategory.CPU_INTENSIVE);
                            cause.setDescription("计算密集型操作");
                            cause.setConfidence(0.7);
                        }
                    }
                    
                    // 2. BLOCKED状态的CPU热点
                    else if (hotspot.getState() == Thread.State.BLOCKED) {
                        cause.setCategory(CPUCategory.LOCK_CONTENTION);
                        cause.setDescription("锁竞争导致");
                        cause.setConfidence(0.75);
                    }
                    
                    // 3. WAITING/TIMED_WAITING状态
                    else if (hotspot.getState() == Thread.State.WAITING || 
                             hotspot.getState() == Thread.State.TIMED_WAITING) {
                        cause.setCategory(CPUCategory.RESOURCE_WAITING);
                        cause.setDescription("资源等待导致");
                        cause.setConfidence(0.6);
                    }
                    
                    return cause;
                }
                
                /**
                 * 检测死循环模式
                 */
                private boolean isInfiniteLoop(String stackTrace) {
                    // 常见的死循环模式
                    String[] loopPatterns = {
                        "while\\(true\\)",
                        "for\\(;;\\)",
                        "while\\(.*\\.hasNext\\(\\)\\)",
                        "for\\(int i=0; i<.*; i\\+\\+\\)", // 边界条件错误
                        "if\\(true\\)\\s*\\{"
                    };
                    
                    for (String pattern : loopPatterns) {
                        if (stackTrace.contains(pattern)) {
                            return true;
                        }
                    }
                    
                    // 检查调用栈深度
                    int stackDepth = countStackTraceDepth(stackTrace);
                    if (stackDepth > 100) { // 调用栈过深
                        return true;
                    }
                    
                    return false;
                }
            }
        }
    }
}

🔧 二、排查工具三件套深度使用

💡 工具链组合拳

三件套协同工作流程

开始排查
top命令定位
识别高CPU进程
获取进程PID
top -Hp PID
识别高CPU线程
线程ID转16进制
jstack PID
在jstack中查找线程
分析线程堆栈
Profiler验证
定位问题代码

🎯 工具深度使用指南

/**
 * 排查工具三件套实现
 * 生产环境CPU问题定位神器
 */
@Component
@Slf4j
public class CPUTroubleshootingTools {
    
    /**
     * top命令分析器
     */
    @Component
    @Slf4j
    public class TopCommandAnalyzer {
        private final ProcessExecutor executor;
        private final OutputParser parser;
        
        /**
         * top命令执行器
         */
        public class TopCommandExecutor {
            /**
             * 执行top命令收集数据
             */
            public TopResult executeTop(int pid, TopConfig config) {
                try {
                    // 构建top命令
                    String command = buildTopCommand(pid, config);
                    
                    // 执行命令
                    ProcessResult result = executor.execute(command, config.getTimeout());
                    
                    // 解析结果
                    TopResult topResult = parser.parseTopOutput(result.getOutput());
                    
                    log.debug("top命令执行完成: pid={}, samples={}", 
                            pid, topResult.getSamples().size());
                    
                    return topResult;
                    
                } catch (Exception e) {
                    log.error("top命令执行失败", e);
                    throw new ToolException("无法执行top命令", e);
                }
            }
            
            /**
             * 构建top命令
             */
            private String buildTopCommand(int pid, TopConfig config) {
                List<String> args = new ArrayList<>();
                args.add("top");
                
                // 批处理模式
                args.add("-b");
                
                // 输出次数
                args.add("-n");
                args.add(String.valueOf(config.getIterations()));
                
                // 延迟时间
                args.add("-d");
                args.add(config.getDelay() + "s");
                
                // 只显示指定进程
                if (pid > 0) {
                    args.add("-p");
                    args.add(String.valueOf(pid));
                }
                
                return String.join(" ", args);
            }
        }
        
        /**
         * top结果分析器
         */
        public class TopResultAnalyzer {
            /**
             * 分析top结果识别问题
             */
            public TopAnalysis analyzeTopResult(TopResult result) {
                TopAnalysis analysis = new TopAnalysis();
                
                // 1. 总体CPU使用率趋势
                analysis.setCpuTrend(analyzeCpuTrend(result));
                
                // 2. 进程CPU使用率
                analysis.setProcessCpu(analyzeProcessCpu(result));
                
                // 3. 负载分析
                analysis.setLoadAnalysis(analyzeLoad(result));
                
                // 4. 线程级分析
                if (result.hasThreadInfo()) {
                    analysis.setThreadAnalysis(analyzeThreads(result));
                }
                
                return analysis;
            }
            
            /**
             * 分析线程级CPU使用
             */
            private ThreadAnalysis analyzeThreads(TopResult result) {
                ThreadAnalysis analysis = new ThreadAnalysis();
                
                // 收集所有样本中的线程数据
                Map<Long, ThreadStats> threadStats = new HashMap<>();
                
                for (TopSample sample : result.getSamples()) {
                    for (ThreadInfo thread : sample.getThreads()) {
                        long tid = thread.getTid();
                        ThreadStats stats = threadStats.getOrDefault(tid, 
                            new ThreadStats(thread.getThreadName()));
                        stats.addSample(thread.getCpuPercent(), thread.getTime());
                        threadStats.put(tid, stats);
                    }
                }
                
                // 找出CPU使用率最高的线程
                List<ThreadStats> sortedStats = threadStats.values().stream()
                    .sorted(Comparator.comparingDouble(ThreadStats::getAvgCpu).reversed())
                    .collect(Collectors.toList());
                
                analysis.setAllThreads(sortedStats);
                
                // 识别异常线程
                List<ThreadStats> abnormalThreads = sortedStats.stream()
                    .filter(stats -> stats.getAvgCpu() > 10.0) // 超过10%
                    .collect(Collectors.toList());
                
                analysis.setAbnormalThreads(abnormalThreads);
                
                return analysis;
            }
        }
    }
    
    /**
     * jstack分析器
     */
    @Component
    @Slj4
    public class JStackAnalyzer {
        private final ThreadDumpCollector collector;
        private final StackTraceParser parser;
        private final ThreadGrouping grouper;
        
        /**
         * jstack执行与分析
         */
        public class JStackExecutor {
            /**
             * 执行jstack并分析
             */
            public JStackAnalysis analyzeJStack(int pid, boolean includeLocks) {
                try {
                    // 1. 收集线程转储
                    String threadDump = collector.collectThreadDump(pid);
                    
                    // 2. 解析线程转储
                    List<ParsedThread> threads = parser.parseThreadDump(threadDump);
                    
                    // 3. 线程分组分析
                    Map<ThreadGroup, List<ParsedThread>> groupedThreads = 
                        grouper.groupThreads(threads);
                    
                    // 4. 状态统计
                    Map<Thread.State, Long> stateCounts = threads.stream()
                        .collect(Collectors.groupingBy(ParsedThread::getState, Collectors.counting()));
                    
                    // 5. 锁分析
                    LockAnalysis lockAnalysis = null;
                    if (includeLocks) {
                        lockAnalysis = analyzeLocks(threads);
                    }
                    
                    return JStackAnalysis.builder()
                        .threadCount(threads.size())
                        .threads(threads)
                        .groupedThreads(groupedThreads)
                        .stateDistribution(stateCounts)
                        .lockAnalysis(lockAnalysis)
                        .rawDump(threadDump)
                        .build();
                    
                } catch (Exception e) {
                    log.error("jstack分析失败", e);
                    throw new ToolException("无法分析jstack输出", e);
                }
            }
            
            /**
             * 线程ID转换工具
             */
            public class ThreadIdConverter {
                /**
                 * 十进制转十六进制(jstack格式)
                 */
                public String toHex(long threadId) {
                    return "0x" + Long.toHexString(threadId);
                }
                
                /**
                 * 十六进制转十进制
                 */
                public long fromHex(String hexThreadId) {
                    if (hexThreadId.startsWith("0x")) {
                        hexThreadId = hexThreadId.substring(2);
                    }
                    return Long.parseLong(hexThreadId, 16);
                }
            }
            
            /**
             * 线程堆栈匹配
             */
            public class ThreadStackMatcher {
                /**
                 * 匹配top线程和jstack线程
                 */
                public List<MatchedThread> matchThreads(List<ThreadStats> topThreads, 
                                                       JStackAnalysis jstackAnalysis) {
                    List<MatchedThread> matched = new ArrayList<>();
                    
                    for (ThreadStats topThread : topThreads) {
                        String hexTid = toHex(topThread.getThreadId());
                        
                        // 在jstack中查找对应线程
                        Optional<ParsedThread> jstackThread = jstackAnalysis.getThreads().stream()
                            .filter(t -> t.getThreadId().equals(hexTid))
                            .findFirst();
                        
                        if (jstackThread.isPresent()) {
                            matched.add(new MatchedThread(topThread, jstackThread.get()));
                        } else {
                            log.warn("未找到匹配的jstack线程: tid={}", hexTid);
                        }
                    }
                    
                    return matched;
                }
            }
        }
    }
}

🔁 三、死循环模式识别与定位

💡 死循环典型模式

死循环检测与分类

graph TB
    A[死循环模式] --> B[显式死循环]
    A --> C[隐式死循环]
    A --> D[条件死循环]
    
    B --> B1[while(true)]
    B --> B2[for(;;)]
    B --> B3[递归无退出]
    
    C --> C1[集合遍历bug]
    C --> C2[迭代器失效]
    C --> C3[状态机卡死]
    
    D --> D1[边界条件错误]
    D --> D2[浮点数比较]
    D --> D3[并发修改]
    
    B1 --> E[检测方法: 堆栈分析]
    C1 --> E
    D1 --> E
    
    E --> F[定位工具: jstack+profiler]
    E --> G[修复策略: 添加退出条件]
    
    style A fill:#ffcdd2,stroke:#333
    style B1 fill:#c8e6c9,stroke:#333
    style D2 fill:#ffccbc,stroke:#333

🎯 死循环检测与修复

/**
 * 死循环检测与定位
 * 生产环境CPU 100%常见原因
 */
@Component
@Slf4j
public class InfiniteLoopDetection {
    
    /**
     * 死循环检测器
     */
    @Component
    @Slf4j
    public class InfiniteLoopDetector {
        private final CallStackAnalyzer stackAnalyzer;
        private final ExecutionTimeTracker timeTracker;
        
        /**
         * 死循环检测算法
         */
        public class LoopDetectionAlgorithm {
            /**
             * 检测死循环模式
             */
            public LoopDetectionResult detectInfiniteLoop(ParsedThread thread) {
                LoopDetectionResult result = new LoopDetectionResult();
                
                // 1. 分析调用栈
                StackTraceElement[] stackTrace = thread.getStackTrace();
                
                // 2. 检测常见死循环模式
                if (containsExplicitLoop(stackTrace)) {
                    result.setLoopType(LoopType.EXPLICIT);
                    result.setConfidence(0.9);
                    result.setPattern("显式死循环");
                } else if (containsImplicitLoop(stackTrace)) {
                    result.setLoopType(LoopType.IMPLICIT);
                    result.setConfidence(0.8);
                    result.setPattern("隐式死循环");
                } else if (containsRecursiveLoop(stackTrace)) {
                    result.setLoopType(LoopType.RECURSIVE);
                    result.setConfidence(0.85);
                    result.setPattern("无限递归");
                } else if (isLongRunning(stackTrace, thread)) {
                    result.setLoopType(LoopType.LONG_RUNNING);
                    result.setConfidence(0.7);
                    result.setPattern("长时间运行");
                }
                
                // 3. 定位循环代码位置
                if (result.getLoopType() != null) {
                    result.setLoopLocation(locateLoopCode(stackTrace));
                }
                
                return result;
            }
            
            /**
             * 检测显式死循环
             */
            private boolean containsExplicitLoop(StackTraceElement[] stackTrace) {
                // 检查堆栈中的方法名和行号
                for (StackTraceElement element : stackTrace) {
                    String methodName = element.getMethodName();
                    String className = element.getClassName();
                    
                    // 常见循环方法模式
                    if (methodName.contains("loop") || 
                        methodName.contains("iterate") ||
                        methodName.contains("process")) {
                        
                        // 检查是否在长时间运行
                        if (isLoopMethod(className, methodName)) {
                            return true;
                        }
                    }
                }
                return false;
            }
            
            /**
             * 定位循环代码
             */
            private CodeLocation locateLoopCode(StackTraceElement[] stackTrace) {
                // 优先查找业务代码
                for (StackTraceElement element : stackTrace) {
                    String className = element.getClassName();
                    
                    // 跳过系统类和库类
                    if (!isSystemClass(className) && !isLibraryClass(className)) {
                        return new CodeLocation(
                            className,
                            element.getMethodName(),
                            element.getFileName(),
                            element.getLineNumber()
                        );
                    }
                }
                
                // 如果找不到业务代码,返回最顶层的非系统代码
                for (StackTraceElement element : stackTrace) {
                    String className = element.getClassName();
                    if (!isSystemClass(className)) {
                        return new CodeLocation(
                            className,
                            element.getMethodName(),
                            element.getFileName(),
                            element.getLineNumber()
                        );
                    }
                }
                
                return null;
            }
        }
        
        /**
         * 死循环案例
         */
        @Component
        @Slj4
        public class InfiniteLoopCase {
            
            /**
             * 案例1: while(true)死循环
             */
            public class WhileTrueLoopCase {
                // 有问题的代码
                public class ProblematicCode {
                    public void processQueue() {
                        while (true) {  // 没有退出条件
                            Object task = queue.poll();
                            if (task != null) {
                                processTask(task);
                            }
                            // 问题: 队列为空时变成死循环
                        }
                    }
                    
                    /**
                     * 修复方案1: 添加超时
                     */
                    public class FixedWithTimeout {
                        public void processQueue() {
                            long startTime = System.currentTimeMillis();
                            long timeout = 10000; // 10秒超时
                            
                            while (System.currentTimeMillis() - startTime < timeout) {
                                Object task = queue.poll();
                                if (task != null) {
                                    processTask(task);
                                } else {
                                    Thread.sleep(100); // 避免CPU 100%
                                }
                            }
                        }
                    }
                    
                    /**
                     * 修复方案2: 添加退出条件
                     */
                    public class FixedWithCondition {
                        private volatile boolean running = true;
                        
                        public void processQueue() {
                            while (running) {
                                Object task = queue.poll();
                                if (task != null) {
                                    processTask(task);
                                } else {
                                    try {
                                        Thread.sleep(100);
                                    } catch (InterruptedException e) {
                                        Thread.currentThread().interrupt();
                                        break;
                                    }
                                }
                            }
                        }
                        
                        public void stop() {
                            running = false;
                        }
                    }
                }
            }
            
            /**
             * 案例2: 集合遍历死循环
             */
            public class CollectionLoopCase {
                // ConcurrentModification导致的隐式死循环
                public class ProblematicIteration {
                    private final List<String> data = new ArrayList<>();
                    
                    public void processData() {
                        // 错误: 在遍历时修改集合
                        for (String item : data) {
                            if (shouldRemove(item)) {
                                data.remove(item);  // 抛出ConcurrentModificationException
                            }
                        }
                    }
                    
                    /**
                     * 修复: 使用迭代器
                     */
                    public class FixedWithIterator {
                        public void processData() {
                            Iterator<String> iterator = data.iterator();
                            while (iterator.hasNext()) {
                                String item = iterator.next();
                                if (shouldRemove(item)) {
                                    iterator.remove();  // 安全的删除
                                }
                            }
                        }
                    }
                    
                    /**
                     * 修复: 使用Java 8 Stream
                     */
                    public class FixedWithStream {
                        public void processData() {
                            data.removeIf(this::shouldRemove);
                        }
                    }
                }
            }
            
            /**
             * 案例3: 递归死循环
             */
            public class RecursiveLoopCase {
                // 缺少退出条件的递归
                public class ProblematicRecursion {
                    public int calculate(int n) {
                        // 错误: 缺少退出条件
                        return n + calculate(n - 1);
                    }
                    
                    /**
                     * 修复: 添加基准条件
                     */
                    public class FixedRecursion {
                        public int calculate(int n) {
                            if (n <= 0) {  // 基准条件
                                return 0;
                            }
                            return n + calculate(n - 1);
                        }
                    }
                }
            }
        }
    }
}

🔒 四、锁竞争导致的CPU飙升

💡 锁竞争分析框架

/**
 * 锁竞争检测与分析
 * 高并发下的CPU问题根源
 */
@Component
@Slf4j
public class LockContentionDetection {
    
    /**
     * 锁竞争检测器
     */
    @Component
    @Slf4j
    public class LockContentionDetector {
        private final LockInfoCollector lockCollector;
        private final ThreadStateAnalyzer stateAnalyzer;
        
        /**
         * 锁竞争分析算法
         */
        public class LockContentionAnalysis {
            /**
             * 分析锁竞争问题
             */
            public LockContentionResult analyzeContention(List<ParsedThread> threads) {
                LockContentionResult result = new LockContentionResult();
                
                // 1. 统计BLOCKED状态线程
                List<ParsedThread> blockedThreads = threads.stream()
                    .filter(t -> t.getState() == Thread.State.BLOCKED)
                    .collect(Collectors.toList());
                
                result.setBlockedThreadCount(blockedThreads.size());
                
                // 2. 分析锁信息
                Map<String, LockInfo> lockInfos = extractLockInfo(blockedThreads);
                
                // 3. 找出热点锁
                List<LockHotspot> hotspots = findLockHotspots(lockInfos);
                
                result.setLockHotspots(hotspots);
                
                // 4. 分析死锁
                List<Deadlock> deadlocks = detectDeadlocks(threads);
                result.setDeadlocks(deadlocks);
                
                return result;
            }
            
            /**
             * 提取锁信息
             */
            private Map<String, LockInfo> extractLockInfo(List<ParsedThread> blockedThreads) {
                Map<String, LockInfo> lockMap = new HashMap<>();
                
                for (ParsedThread thread : blockedThreads) {
                    String lockInfo = thread.getLockInfo();
                    if (lockInfo != null) {
                        LockInfo info = lockMap.getOrDefault(lockInfo, new LockInfo(lockInfo));
                        info.addBlockedThread(thread);
                        lockMap.put(lockInfo, info);
                    }
                }
                
                return lockMap;
            }
            
            /**
             * 找出热点锁
             */
            private List<LockHotspot> findLockHotspots(Map<String, LockInfo> lockInfos) {
                return lockInfos.values().stream()
                    .filter(info -> info.getBlockedCount() > 1)  // 多个线程等待
                    .map(info -> new LockHotspot(
                        info.getLockName(),
                        info.getBlockedCount(),
                        info.getBlockedThreads()
                    ))
                    .sorted(Comparator.comparingInt(LockHotspot::getWaiterCount).reversed())
                    .collect(Collectors.toList());
            }
        }
        
        /**
         * 锁竞争案例
         */
        @Component
        @Slj4
        public class LockContentionCase {
            
            /**
             * 案例1: 全局锁竞争
             */
            public class GlobalLockCase {
                // 有问题的全局锁
                public class ProblematicGlobalLock {
                    private static final Object GLOBAL_LOCK = new Object();
                    
                    public void processRequest() {
                        synchronized (GLOBAL_LOCK) {  // 全局锁
                            // 处理请求...
                            heavyProcessing();
                        }
                    }
                    
                    // 问题: 所有请求都竞争同一把锁
                    
                    /**
                     * 修复: 使用分段锁
                     */
                    public class FixedWithStripedLock {
                        private final Striped<Lock> stripedLocks = Striped.lock(16);
                        
                        public void processRequest(String key) {
                            Lock lock = stripedLocks.get(key);
                            lock.lock();
                            try {
                                heavyProcessing();
                            } finally {
                                lock.unlock();
                            }
                        }
                    }
                    
                    /**
                     * 修复: 使用无锁数据结构
                     */
                    public class FixedWithLockFree {
                        private final ConcurrentHashMap<String, String> cache = 
                            new ConcurrentHashMap<>();
                        
                        public void processRequest(String key) {
                            // 无锁操作
                            cache.compute(key, (k, v) -> {
                                return processValue(v);
                            });
                        }
                    }
                }
            }
            
            /**
             * 案例2: 锁粒度过大
             */
            public class CoarseGrainedLockCase {
                // 锁粒度过大
                public class ProblematicCoarseLock {
                    private final List<Data> dataList = new ArrayList<>();
                    private final Object lock = new Object();
                    
                    public void updateData(int index, Data newData) {
                        synchronized (lock) {  // 锁住整个列表
                            Data oldData = dataList.get(index);
                            // 只更新一个元素,但锁住了整个列表
                            dataList.set(index, newData);
                        }
                    }
                    
                    /**
                     * 修复: 细化锁粒度
                     */
                    public class FixedWithFineGrainedLock {
                        private final Data[] dataArray;
                        private final Object[] locks;
                        
                        public FixedWithFineGrainedLock(int size) {
                            dataArray = new Data[size];
                            locks = new Object[size];
                            for (int i = 0; i < size; i++) {
                                locks[i] = new Object();
                            }
                        }
                        
                        public void updateData(int index, Data newData) {
                            synchronized (locks[index]) {  // 只锁需要的元素
                                dataArray[index] = newData;
                            }
                        }
                    }
                }
            }
        }
    }
}

♻️ 五、GC压力导致的CPU打满

💡 GC导致的CPU问题

/**
 * GC导致的CPU问题分析
 * Full GC频繁导致的CPU 100%
 */
@Component
@Slf4j
public class GCPressureAnalysis {
    
    /**
     * GC压力检测器
     */
    @Component
    @Slj4
    public class GCPressureDetector {
        private final GCLogAnalyzer gcAnalyzer;
        private final MemoryMonitor memoryMonitor;
        
        /**
         * GC压力分析
         */
        public class GCPressureAnalysis {
            /**
             * 分析GC导致的CPU问题
             */
            public GCPressureResult analyzeGCPressure(GCData gcData) {
                GCPressureResult result = new GCPressureResult();
                
                // 1. 分析GC频率
                double gcFrequency = calculateGCFrequency(gcData);
                result.setGcFrequency(gcFrequency);
                
                // 2. 分析GC耗时
                double gcTimeRatio = calculateGCTimeRatio(gcData);
                result.setGcTimeRatio(gcTimeRatio);
                
                // 3. 判断是否GC导致CPU高
                if (gcTimeRatio > 0.3) {  // GC时间超过30%
                    result.setGcInduced(true);
                    result.setSeverity(Severity.HIGH);
                    result.setDescription("GC耗时过高导致CPU打满");
                } else if (gcFrequency > 10) {  // 每分钟超过10次Full GC
                    result.setGcInduced(true);
                    result.setSeverity(Severity.MEDIUM);
                    result.setDescription("Full GC频繁导致CPU高");
                }
                
                return result;
            }
        }
        
        /**
         * GC优化策略
         */
        public class GCOptimization {
            /**
             * 优化GC参数降低CPU
             */
            public String generateGCOptions(GCPressureResult result) {
                List<String> options = new ArrayList<>();
                
                if (result.isGcInduced()) {
                    // 针对不同GC收集器优化
                    options.add("-XX:+UseG1GC");
                    options.add("-XX:MaxGCPauseMillis=200");
                    options.add("-XX:G1HeapRegionSize=4m");
                    options.add("-XX:ParallelGCThreads=4");
                    options.add("-XX:ConcGCThreads=2");
                    
                    // 增加堆大小减少GC频率
                    options.add("-Xmx4g");
                    options.add("-Xms4g");
                    
                    // 启用详细GC日志用于分析
                    options.add("-Xlog:gc*:file=gc.log:time,uptime,level,tags");
                }
                
                return String.join(" ", options);
            }
        }
    }
}

🔄 六、从CPU视角反推代码问题

💡 逆向分析方法论

从CPU热点反推代码问题

CPU热点
函数级分析
代码路径分析
数据特征分析
热点函数识别
调用频率分析
执行时间分析
调用链重构
条件分支分析
循环体分析
输入数据分析
数据结构分析
并发特征分析
问题模式识别
根因定位
优化方案

🎯 逆向分析实战

/**
 * 从CPU热点反推代码问题
 * 逆向工程思维解决性能问题
 */
@Component
@Slf4j
public class CPUReverseAnalysis {
    
    /**
     * 热点函数分析器
     */
    @Component
    @Slf4j
    public class HotspotFunctionAnalyzer {
        private final ProfilerDataParser profilerParser;
        private final SourceCodeAnalyzer sourceAnalyzer;
        
        /**
         * 热点函数分析
         */
        public class HotspotAnalysis {
            /**
             * 从CPU热点反推代码问题
             */
            public CodeProblem reverseEngineerFromHotspot(ProfilerData profilerData) {
                CodeProblem problem = new CodeProblem();
                
                // 1. 识别热点函数
                List<HotFunction> hotFunctions = identifyHotFunctions(profilerData);
                
                // 2. 分析热点模式
                for (HotFunction function : hotFunctions) {
                    // 分析函数特征
                    FunctionAnalysis analysis = analyzeFunction(function);
                    
                    // 根据特征分类问题
                    if (analysis.isLoopHeavy()) {
                        problem.setType(ProblemType.LOOP_OPTIMIZATION);
                    } else if (analysis.isLockHeavy()) {
                        problem.setType(ProblemType.LOCK_CONTENTION);
                    } else if (analysis.isIOWait()) {
                        problem.setType(ProblemType.IO_WAIT);
                    } else if (analysis.isAlgorithmInefficient()) {
                        problem.setType(ProblemType.ALGORITHM);
                    }
                }
                
                // 3. 定位具体代码位置
                problem.setLocations(locateProblematicCode(hotFunctions));
                
                return problem;
            }
        }
        
        /**
         * 代码模式识别
         */
        @Component
        @Slj4
        public class CodePatternRecognition {
            /**
             * 识别性能反模式
             */
            public class PerformanceAntiPatterns {
                /**
                 * 从调用栈识别反模式
                 */
                public AntiPattern recognizeAntiPattern(String stackTrace) {
                    // 1. 重复计算模式
                    if (containsRepeatedComputation(stackTrace)) {
                        return AntiPattern.REPEATED_COMPUTATION;
                    }
                    
                    // 2. 同步过度模式
                    if (containsExcessiveSynchronization(stackTrace)) {
                        return AntiPattern.EXCESSIVE_SYNCHRONIZATION;
                    }
                    
                    // 3. 内存滥用模式
                    if (containsMemoryAbuse(stackTrace)) {
                        return AntiPattern.MEMORY_ABUSE;
                    }
                    
                    // 4. IO阻塞模式
                    if (containsIOBlocking(stackTrace)) {
                        return AntiPattern.IO_BLOCKING;
                    }
                    
                    return AntiPattern.UNKNOWN;
                }
            }
        }
    }
}

🚀 七、生产环境防御体系

💡 多层级防护策略

CPU问题防御体系

防护层级 防护措施 实现方式
代码层 1. 代码审查
2. 静态分析
3. 单元测试
1. SonarQube
2. SpotBugs
3. JUnit
构建层 1. 性能测试
2. 压测验证
3. 基准测试
1. JMeter
2. Gatling
3. JMH
运行层 1. 监控告警
2. 熔断降级
3. 自动扩缩
1. Prometheus
2. Hystrix
3. Kubernetes HPA
应急层 1. 预案演练
2. 快速定位
3. 一键修复
1. 应急预案
2. 诊断工具包
3. 热修复

🎯 自动化监控方案

/**
 * CPU自动化监控与告警
 */
@Component
@Slf4j
public class CPUAutomatedMonitoring {
    
    @Scheduled(fixedRate = 10000)  // 每10秒监控一次
    public void monitorCPU() {
        double cpuUsage = getProcessCPUUsage();
        
        if (cpuUsage > 80.0) {  // 80%阈值
            log.warn("CPU使用率过高: {}%", cpuUsage);
            
            // 自动采集诊断数据
            if (shouldCollectDiagnostics(cpuUsage)) {
                collectDiagnosticData();
            }
            
            // 触发告警
            triggerAlert(cpuUsage);
            
            // 自动降级
            if (cpuUsage > 90.0) {
                enableDegradation();
            }
        }
    }
}

🎯 总结

💡 CPU问题排查核心要点

排查流程黄金法则

  1. 快速定位:使用top快速定位高CPU进程和线程
  2. 深入分析:使用jstack分析线程堆栈,找到热点代码
  3. 验证确认:使用Profiler验证分析结果,定位根本原因
  4. 制定方案:根据问题类型制定针对性的优化方案
  5. 验证效果:优化后验证CPU使用率是否恢复正常

📊 工具使用速查表

工具 使用场景 关键命令
top 快速定位高CPU进程/线程 top -Hp <pid>
jstack 线程堆栈分析 jstack <pid> > thread.dump
jstat GC情况分析 jstat -gcutil <pid> 1000
Async Profiler 方法级CPU分析 ./profiler.sh -d 30 -f profile.html <pid>
Arthas 动态诊断 thread -n 3

🚀 生产环境最佳实践

CPU问题防护清单

  1. 监控告警:建立完善的CPU监控告警体系
  2. 应急预案:制定CPU 100%的应急处理流程
  3. 工具准备:预装排查工具,确保随时可用
  4. 压测验证:定期进行压力测试,评估系统极限
  5. 代码规范:建立性能敏感的编码规范
  6. 知识沉淀:建立CPU问题案例库,团队共享

洞察:CPU 100%问题看似可怕,但只要掌握了系统化的排查方法,就能快速定位和解决。真正的专业性不仅体现在能解决已知问题,更体现在能够预防未知问题。建立完善的监控体系、规范的应急流程和团队的知识共享,是应对CPU问题的根本之道。


如果觉得本文对你有帮助,请点击 👍 点赞 + ⭐ 收藏 + 💬 留言支持!

讨论话题

  1. 你遇到过哪些印象深刻的CPU 100%案例?
  2. 有什么独特的CPU问题排查技巧?
  3. 如何建立团队的CPU问题应急响应机制?

相关资源推荐

  • 📚 https://book.douban.com/subject/27189914/
  • 🔧 https://github.com/brendangregg/FlameGraph
  • 💻 https://github.com/example/cpu-troubleshooting

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐