惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

C
Cisco Blogs
Schneier on Security
Schneier on Security
T
Tor Project blog
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
T
Tenable Blog
C
Cyber Attacks, Cyber Crime and Cyber Security
T
Threat Research - Cisco Blogs
C
CERT Recently Published Vulnerability Notes
Security Latest
Security Latest
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
NISL@THU
NISL@THU
L
Lohrmann on Cybersecurity
Scott Helme
Scott Helme
Webroot Blog
Webroot Blog
Project Zero
Project Zero
Google Online Security Blog
Google Online Security Blog
The Last Watchdog
The Last Watchdog
Spread Privacy
Spread Privacy
Hacker News: Ask HN
Hacker News: Ask HN
PCI Perspectives
PCI Perspectives
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
W
WeLiveSecurity
Attack and Defense Labs
Attack and Defense Labs
D
Darknet – Hacking Tools, Hacker News & Cyber Security
N
News | PayPal Newsroom
Help Net Security
Help Net Security
The Hacker News
The Hacker News
H
Heimdal Security Blog
O
OpenAI News
S
Security @ Cisco Blogs
N
News and Events Feed by Topic
Cyberwarzone
Cyberwarzone
Simon Willison's Weblog
Simon Willison's Weblog
G
GRAHAM CLULEY
www.infosecurity-magazine.com
www.infosecurity-magazine.com
博客园 - 叶小钗
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
Hacker News - Newest:
Hacker News - Newest: "LLM"
T
Tailwind CSS Blog
大猫的无限游戏
大猫的无限游戏
A
Arctic Wolf
I
Intezer
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
S
Security Affairs
P
Proofpoint News Feed
S
Secure Thoughts
腾讯CDC
Google DeepMind News
Google DeepMind News
量子位
罗磊的独立博客

Hi,I`m lan

MCP协议新进展: 使用 Streamable HTTP 替换当前的 HTTP+SSE 实现。-liangyuanpeng 的博客 我的 AI 员工们开发的微信小程序上线了!-liangyuanpeng 的博客 | liangyuanpeng's Blog liangyuanpeng 的博客 | liangyuanpeng's Blog vercel 记录-liangyuanpeng 的博客 | liangyuanpeng's Blog liangyuanpeng 的博客 | liangyuanpeng's Blog [长期更新]cocos creator问题列表-liangyuanpeng 的博客 | liangyuanpeng's Blog go问题列表记录-liangyuanpeng 的博客 | liangyuanpeng's Blog liangyuanpeng 的博客 | liangyuanpeng's Blog node镜像的更多选择-liangyuanpeng 的博客 | liangyuanpeng's Blog liangyuanpeng 的博客 | liangyuanpeng's Blog liangyuanpeng 的博客 | liangyuanpeng's Blog containerd 中的弃用警告 - 为 2.0 做好准备!-liangyuanpeng 的博客 liangyuanpeng 的博客 | liangyuanpeng's Blog kep-1880-多服务CIDR-liangyuanpeng 的博客 | liangyuanpeng's Blog [长期更新]argoworkflow 的一些实践和思考-liangyuanpeng 的博客 | liangyuanpeng's Blog liangyuanpeng 的博客 | liangyuanpeng's Blog liangyuanpeng 的博客 | liangyuanpeng's Blog 将Etcd作为一个kubernetes sig来运作-liangyuanpeng 的博客 | liangyuanpeng's Blog liangyuanpeng 的博客 | liangyuanpeng's Blog argoworkflow 云原生工作流引擎-liangyuanpeng 的博客 | liangyuanpeng's Blog liangyuanpeng 的博客 | liangyuanpeng's Blog liangyuanpeng 的博客 | liangyuanpeng's Blog kubecon china 2023将在上海举办-liangyuanpeng 的博客 | liangyuanpeng's Blog liangyuanpeng 的博客 | liangyuanpeng's Blog liangyuanpeng 的博客 | liangyuanpeng's Blog liangyuanpeng 的博客 | liangyuanpeng's Blog liangyuanpeng 的博客 | liangyuanpeng's Blog liangyuanpeng 的博客 | liangyuanpeng's Blog liangyuanpeng 的博客 | liangyuanpeng's Blog liangyuanpeng 的博客 | liangyuanpeng's Blog 从零到 Kubernetes 子项目负责人-liangyuanpeng 的博客 | liangyuanpeng's Blog liangyuanpeng 的博客 | liangyuanpeng's Blog Kubernetes HPA:定制指标实现有效的CPU和内存扩展-liangyuanpeng 的博客 | liangyuanpeng's Blog JFrog 向 CD 基金会授予开源 Pyrsia-liangyuanpeng 的博客 helmchart发布v2.10.1-liangyuanpeng 的博客 | liangyuanpeng's Blog liangyuanpeng 的博客 | liangyuanpeng's Blog ingress浅试-liangyuanpeng 的博客 | liangyuanpeng's Blog gateway-liangyuanpeng 的博客 | liangyuanpeng's Blog 1.24.0发布-liangyuanpeng 的博客 | liangyuanpeng's Blog liangyuanpeng 的博客 | liangyuanpeng's Blog liangyuanpeng 的博客 | liangyuanpeng's Blog liangyuanpeng 的博客 | liangyuanpeng's Blog 部署去ZK后的Apache Pulsar-liangyuanpeng 的博客 | liangyuanpeng's Blog liangyuanpeng 的博客 | liangyuanpeng's Blog 用GO开发Envoy wasm filter-liangyuanpeng 的博客 | liangyuanpeng's Blog 用Rust开发Envoy wasm filter-liangyuanpeng 的博客 | liangyuanpeng's Blog liangyuanpeng 的博客 | liangyuanpeng's Blog liangyuanpeng 的博客 | liangyuanpeng's Blog liangyuanpeng 的博客 | liangyuanpeng's Blog liangyuanpeng 的博客 | liangyuanpeng's Blog liangyuanpeng 的博客 | liangyuanpeng's Blog v1.18.3发布-liangyuanpeng 的博客 | liangyuanpeng's Blog v1.20.0-beta.1发布-liangyuanpeng 的博客 | liangyuanpeng's Blog liangyuanpeng 的博客 | liangyuanpeng's Blog Bookkeeper-liangyuanpeng 的博客 | liangyuanpeng's Blog liangyuanpeng 的博客 | liangyuanpeng's Blog liangyuanpeng 的博客 | liangyuanpeng's Blog Bookkeeper开发环境搭建-liangyuanpeng 的博客 | liangyuanpeng's Blog liangyuanpeng 的博客 | liangyuanpeng's Blog liangyuanpeng 的博客 | liangyuanpeng's Blog liangyuanpeng 的博客 | liangyuanpeng's Blog liangyuanpeng 的博客 | liangyuanpeng's Blog webhook开发技巧-liangyuanpeng 的博客 | liangyuanpeng's Blog 部署在线的lank8s webhook之后,不再为k8s.gcr.io/gcr.io镜像苦恼-liangyuanpeng 的博客 | liangyuanpeng's Blog liangyuanpeng 的博客 | liangyuanpeng's Blog 部署metrics-server,把kubectl top用起来-liangyuanpeng 的博客 | liangyuanpeng's Blog v1.9.0发布-liangyuanpeng 的博客 | liangyuanpeng's Blog v1.19.1发布-liangyuanpeng 的博客 | liangyuanpeng's Blog liangyuanpeng 的博客 | liangyuanpeng's Blog liangyuanpeng 的博客 | liangyuanpeng's Blog KubeSphere使用Contour Ingress作为项目网关-liangyuanpeng 的博客 | liangyuanpeng's Blog liangyuanpeng 的博客 | liangyuanpeng's Blog liangyuanpeng 的博客 | liangyuanpeng's Blog 宣布Contour v1.13.0-liangyuanpeng 的博客 | liangyuanpeng's Blog [了解Rust基金会]介绍Mark Rousskov-liangyuanpeng 的博客 | liangyuanpeng's Blog [了解Rust基金会]介绍Tyler Mandry-liangyuanpeng 的博客 | liangyuanpeng's Blog [了解Rust基金会]介绍Bobby Holley-liangyuanpeng 的博客 | liangyuanpeng's Blog liangyuanpeng 的博客 | liangyuanpeng's Blog liangyuanpeng 的博客 | liangyuanpeng's Blog liangyuanpeng 的博客 | liangyuanpeng's Blog liangyuanpeng 的博客 | liangyuanpeng's Blog liangyuanpeng 的博客 | liangyuanpeng's Blog liangyuanpeng 的博客 | liangyuanpeng's Blog [了解Rust基金会]介绍Shane Miller-liangyuanpeng 的博客 | liangyuanpeng's Blog liangyuanpeng 的博客 | liangyuanpeng's Blog liangyuanpeng 的博客 | liangyuanpeng's Blog liangyuanpeng 的博客 | liangyuanpeng's Blog liangyuanpeng 的博客 | liangyuanpeng's Blog liangyuanpeng 的博客 | liangyuanpeng's Blog liangyuanpeng 的博客 | liangyuanpeng's Blog prometheus-liangyuanpeng 的博客 | liangyuanpeng's Blog liangyuanpeng 的博客 | liangyuanpeng's Blog liangyuanpeng 的博客 | liangyuanpeng's Blog liangyuanpeng 的博客 | liangyuanpeng's Blog 使用Cloudflare pages部署静态博客-liangyuanpeng 的博客 | liangyuanpeng's Blog liangyuanpeng 的博客 | liangyuanpeng's Blog liangyuanpeng 的博客 | liangyuanpeng's Blog liangyuanpeng 的博客 | liangyuanpeng's Blog liangyuanpeng 的博客 | liangyuanpeng's Blog liangyuanpeng 的博客 | liangyuanpeng's Blog
liangyuanpeng 的博客 | liangyuanpeng's Blog
2021-04-14 · via Hi,I`m lan

TOC

前言

SpringBoot2.x 引入了 Micrometer,重点支持了 tag,而 tag 是 prometheus 和 influxdb 这类新兴监控存储相关中间件天然特性.

而本文主要讲述检测程序中是否有死锁发生,这部分使用的是 dropwizard-metrics 的 metrics-healthchecks 来实现的.

死锁检测配置

首先引入对应的包依赖,maven:

  <dependency>
            <groupId>io.dropwizard.metrics</groupId>
            <artifactId>metrics-healthchecks</artifactId>
            <version>4.1.19</version>
  </dependency>
  <dependency>
            <groupId>io.dropwizard.metrics</groupId>
            <artifactId>metrics-jvm</artifactId>
            <version>4.1.19</version>
  </dependency>
String healthCheckName = "thread_dead_lock";
HealthCheckRegistry healthCheckRegistry = new HealthCheckRegistry();
healthCheckRegistry.register(healthCheckName,new ThreadDeadlockHealthCheck());  
healthCheckRegistry.runHealthCheck(healthCheckName).isHealthy();

这样就加入了一个死锁检测,每次运行healthCheckRegistry.runHealthCheck(healthCheckName).isHealthy()时就可以知道当前程序是否有死锁了.

    protected  final ScheduledThreadPoolExecutor SCHEDULE_EXECUTOR = new ScheduledThreadPoolExecutor(1);
    public io.micrometer.core.instrument.MeterRegistry meterRegistry;
...
            AtomicInteger current = new AtomicInteger(healthCheckRegistry.runHealthCheck(healthCheckName).isHealthy()?1:0);
            SCHEDULE_EXECUTOR.scheduleAtFixedRate(()->{
                if(meterRegistry.find(healthCheckName).gauge()==null){
                    meterRegistry.gauge(healthCheckName,current);
                }else{
                    HealthCheck.Result result = healthCheckRegistry.runHealthCheck(healthCheckName);
                    if(!result.isHealthy()){
                        log.error("run healthCheck:"+result.getMessage());
                    }
                    current.set(result.isHealthy()?1:0);
                }
            },0,30, TimeUnit.SECONDS);

这样就可以定时检测程序中是否有死锁存在,如果有,thread_dead_lock这个 metrics 会显示为 0.也可以通过HealthCheck.Result result这个对象,把死锁相关信息打印在程序 log 中,这样可以将信息收集到专门的日志系统去.比如 Elasticsearch.

原理

需要配置的内容和编写的代码并不多,只需要少量代码就可以做到检测程序死锁了.那么这一切是如何做到的呢?一起来看一下.

首先从最外面的入口点进源码看看逻辑.

点进ThreadDeadlockHealthCheck类看看有什么代码,可以看到只有很少的代码,有一个重写的check方法:

public class ThreadDeadlockHealthCheck extends HealthCheck {
    private final ThreadDeadlockDetector detector;

    /**
     * Creates a new health check.
     */
    public ThreadDeadlockHealthCheck() {
        this(new ThreadDeadlockDetector());
    }

    /**
     * Creates a new health check with the given detector.
     *
     * @param detector a thread deadlock detector
     */
    public ThreadDeadlockHealthCheck(ThreadDeadlockDetector detector) {
        this.detector = detector;
    }

    @Override
    protected Result check() throws Exception {
        final Set<String> threads = detector.getDeadlockedThreads();
        if (threads.isEmpty()) {
            return Result.healthy();
        }
        return Result.unhealthy(threads.toString());
    }
}

getDeadlockedThreads方法名可以看明白这个方法是获取当前死锁线程集合.点进去看看是如何获取的.感觉离原理越来越近了.

public Set<String> getDeadlockedThreads() {
        final long[] ids = threads.findDeadlockedThreads();
        if (ids != null) {
            final Set<String> deadlocks = new HashSet<>();
            for (ThreadInfo info : threads.getThreadInfo(ids, MAX_STACK_TRACE_DEPTH)) {
                final StringBuilder stackTrace = new StringBuilder();
                for (StackTraceElement element : info.getStackTrace()) {
                    stackTrace.append("\t at ")
                            .append(element.toString())
                            .append(String.format("%n"));
                }

                deadlocks.add(
                        String.format("%s locked on %s (owned by %s):%n%s",
                                info.getThreadName(),
                                info.getLockName(),
                                info.getLockOwnerName(),
                                stackTrace.toString()
                        )
                );
            }
            return Collections.unmodifiableSet(deadlocks);
        }
        return Collections.emptySet();
    }

点进去后发现是通过final long[] ids = threads.findDeadlockedThreads();获取到死锁的线程 id 数字,看看threads变量是一个什么东西.

private final ThreadMXBean threads;

可以看到这是 ThreadMXBean 提供的方法,而这个类是java.lang.management包下的.这个包是JDK提供的一些用于检测 JVM 状态的 API 类.可以拿到当前 JVM 的内存,GC,线程,class 等各种信息.

我们这里是用的其中一种MXBean类:ThreadMXBean,来获取线程相关的信息.感兴趣的可以自己去研究下,例如获取内存信息的一个类:MemoryMXBean,这里不展开讲述.

细心的同学可以发现我们目前已经拿到了死锁线程的ID数组,如果数组有内容其实就说明当前程序有发生死锁.

后面的逻辑是拿一些死锁线程具体的信息,例如线程名,锁名,锁持有者.

因此对于没有接入或不希望接入dropwizard.metrics的同学来说,完全可以自己实现一个检测程序是否有死锁的逻辑.

总结

对于当前没有检测死锁的程序来说,发生死锁时所产生的未知影响是很大的.而如果程序能够自己定时检测是否有死锁并且发生时能够快速的发出警告,很大程度上可以避免一些不必要的损失.

如果你的程序当前还没有死锁检测,赶紧偷偷加上监控死锁的逻辑,然后惊艳所有人!!!

微信公众号

扫描下面的二维码关注我们的微信公众号,第一时间查看最新内容。同时也可以关注我的Github,看看我都在了解什么技术,在页面底部可以找到我的Github。

wechat-qrcode