社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Elasticsearch

聊聊elasticsearch的DeadlockAnalyzer

go4it • 4 年前 • 281 次点击  
阅读 5

聊聊elasticsearch的DeadlockAnalyzer

本文主要研究一下elasticsearch的DeadlockAnalyzer

DeadlockAnalyzer

elasticsearch-7.0.1/server/src/main/java/org/elasticsearch/monitor/jvm/DeadlockAnalyzer.java

public class DeadlockAnalyzer {

    private static final Deadlock NULL_RESULT[] = new Deadlock[0];
    private final ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();

    private static DeadlockAnalyzer INSTANCE = new DeadlockAnalyzer();

    public static DeadlockAnalyzer deadlockAnalyzer() {
        return INSTANCE;
    }

    private DeadlockAnalyzer() {

    }

    public Deadlock[] findDeadlocks() {
        long deadlockedThreads[] = threadBean.findMonitorDeadlockedThreads();
        if (deadlockedThreads == null || deadlockedThreads.length == 0) {
            return NULL_RESULT;
        }
        Map<Long, ThreadInfo> threadInfoMap = createThreadInfoMap(deadlockedThreads);
        Set<LinkedHashSet<ThreadInfo>> cycles = calculateCycles(threadInfoMap);
        Set<LinkedHashSet<ThreadInfo>> chains = calculateCycleDeadlockChains(threadInfoMap, cycles);
        cycles.addAll(chains);
        return createDeadlockDescriptions(cycles);
    }


    private Deadlock[] createDeadlockDescriptions(Set<LinkedHashSet<ThreadInfo>> cycles) {
        Deadlock result[] = new Deadlock[cycles.size()];
        int count = 0;
        for (LinkedHashSet<ThreadInfo> cycle : cycles) {
            ThreadInfo asArray[] = cycle.toArray(new ThreadInfo[cycle.size()]);
            Deadlock d = new Deadlock(asArray);
            result[count++] = d;
        }
        return result;
    }


    private Set<LinkedHashSet<ThreadInfo>> calculateCycles(Map<Long, ThreadInfo> threadInfoMap) {
        Set<LinkedHashSet<ThreadInfo>> cycles = new HashSet<>();
        for (Map.Entry<Long, ThreadInfo> entry : threadInfoMap.entrySet()) {
            LinkedHashSet<ThreadInfo> cycle = new LinkedHashSet<>();
            for (ThreadInfo t = entry.getValue(); !cycle.contains(t); t = threadInfoMap.get(Long.valueOf(t.getLockOwnerId()))) {
                cycle.add(t);
            }

            if (!cycles.contains(cycle)) {
                cycles.add(cycle);
            }
        }
        return cycles;
    }


    private Set<LinkedHashSet<ThreadInfo>> calculateCycleDeadlockChains(Map<Long, ThreadInfo> threadInfoMap,
            Set<LinkedHashSet<ThreadInfo>> cycles) {
        ThreadInfo allThreads[] = threadBean.getThreadInfo(threadBean.getAllThreadIds());
        Set<LinkedHashSet<ThreadInfo>> deadlockChain = new HashSet<>();
        Set<Long> knownDeadlockedThreads = threadInfoMap.keySet();
        for (ThreadInfo threadInfo : allThreads) {
            Thread.State state = threadInfo.getThreadState();
            if (state == Thread.State.BLOCKED && !knownDeadlockedThreads.contains(threadInfo.getThreadId())) {
                for (LinkedHashSet<ThreadInfo> cycle : cycles) {
                    if (cycle.contains(threadInfoMap.get(Long.valueOf(threadInfo.getLockOwnerId())))) {
                        LinkedHashSet<ThreadInfo> chain = new LinkedHashSet<>();
                        ThreadInfo node = threadInfo;
                        while (!chain.contains(node)) {
                            chain.add(node);
                            node = threadInfoMap.get(Long.valueOf(node.getLockOwnerId()));
                        }
                        deadlockChain.add(chain);
                    }
                }

            }
        }

        return deadlockChain;
    }


    private Map<Long, ThreadInfo> createThreadInfoMap(long threadIds[]) {
        ThreadInfo threadInfos[] = threadBean.getThreadInfo(threadIds);
        Map<Long, ThreadInfo> threadInfoMap = new HashMap<>();
        for (ThreadInfo threadInfo : threadInfos) {
            threadInfoMap.put(threadInfo.getThreadId(), threadInfo);
        }
        return unmodifiableMap(threadInfoMap);
    }

    //......
}
复制代码
  • DeadlockAnalyzer提供了findDeadlocks方法用于返回死锁线程的信息,该方法通过ThreadMXBean的findMonitorDeadlockedThreads方法获取deadlockedThreads数组,如果该数组为null或空,则返回NULL_RESULT,否则往下计算
  • createThreadInfoMap方法根据threadIds从ThreadMXBean获取对应的threadInfo信息,然后组装成threadId与threadInfo的map;calculateCycles方法则是遍历该map,然后根据threadInfo的getLockOwnerId()构建cycles
  • calculateCycleDeadlockChains方法则根据threadInfoMap及cycles构建cycleDeadlockChains,添加到cycles中,最后通过createDeadlockDescriptions方法构建Deadlock数组

Deadlock

elasticsearch-7.0.1/server/src/main/java/org/elasticsearch/monitor/jvm/DeadlockAnalyzer.java

    public static class Deadlock {
        private final ThreadInfo members[];
        private final String description;
        private final Set<Long> memberIds;

        public Deadlock(ThreadInfo[] members) {
            this.members = members;

            Set<Long> builder = new HashSet<>();
            StringBuilder sb = new StringBuilder();
            for (int x = 0; x < members.length; x++) {
                ThreadInfo ti = members[x];
                sb.append(ti.getThreadName());
                sb.append(" > ");
                if (x == members.length - 1) {
                    sb.append(ti.getLockOwnerName());
                }
                builder.add(ti.getThreadId());
            }
            this.description = sb.toString();
            this.memberIds = unmodifiableSet(builder);
        }

        public ThreadInfo[] members() {
            return members;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;

            Deadlock deadlock = (Deadlock) o;

            if (memberIds != null ? !memberIds.equals(deadlock.memberIds) : deadlock.memberIds != null) return false;

            return true;
        }

        @Override
        public int hashCode() {
            int result = members != null ? Arrays.hashCode(members) : 0;
            result = 31 * result + (description != null ? description.hashCode() : 0);
            result = 31 * result + (memberIds != null ? memberIds.hashCode() : 0);
            


    
return result;
        }

        @Override
        public String toString() {
            return description;
        }
    }
复制代码
  • Deadlock包含了members、description、memberIds三个属性,其构造器会根据members来构建description

小结

  • DeadlockAnalyzer提供了findDeadlocks方法用于返回死锁线程的信息,该方法通过ThreadMXBean的findMonitorDeadlockedThreads方法获取deadlockedThreads数组,如果该数组为null或空,则返回NULL_RESULT,否则往下计算
  • createThreadInfoMap方法根据threadIds从ThreadMXBean获取对应的threadInfo信息,然后组装成threadId与threadInfo的map;calculateCycles方法则是遍历该map,然后根据threadInfo的getLockOwnerId()构建cycles
  • calculateCycleDeadlockChains方法则根据threadInfoMap及cycles构建cycleDeadlockChains,添加到cycles中,最后通过createDeadlockDescriptions方法构建Deadlock数组

doc

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/33483
 
281 次点击