jstack调试_增压的jstack:如何以100mph的速度调试服务器

jstack调试

霹雳舞

使用jstack调试实时Java生产服务器的指南

jstack就像U2一样-从时间的黎明就一直在我们身边,我们似乎无法摆脱它 。 除了笑话,到目前为止,jstack是您的工具库中用于调试实时生产服务器的最方便的工具之一。 即便如此,我仍然觉得它在情况恶化时能够将您从火中扑灭的能力仍未得到充分利用,因此我想分享一些方法,您可以在对抗生产错误的战争中将其增强为更强大的武器。

jstack的核心是一个超级简单的工具,它向您显示在目标JVM中运行的所有Java线程的堆栈跟踪。 只需通过一个pid将其指向JVM进程即可获得该时间点所有线程堆栈跟踪的打印输出。 这使您能够回答“这个服务器在做什么?”这个古老的问题,并使您更进一步地了解它为什么真正在做它。 关于jstack的最大优点是它轻巧-它不会给JVM增加任何性能开销,也不会更改其执行状态(与调试器或探查器不同)。

由于没有什么是完美的 ,因此jstack有两个明显的缺点。 第一个是jstack除了调用堆栈外没有为您提供任何变量状态,这意味着尽管您可能正在查看堆栈,但您不知道将其置于何处的状态。 一个很好的例子是查看挂起的JVM,其中jstack会向您显示大量线程正在执行数据库查询或等待获得连接。

这可能意味着某些查询执行时间太长,导致其他线程要么等待连接,要么被拒绝。 在这里,您真的想知道正在执行哪个查询(或其查询参数是什么),这会导致速度降低以及何时开始。 当然,在很多情况下,这只是一个示例,其中某些线程被阻塞并降低了应用程序的吞吐量。 但是不幸的是,使用jstack时,因为您没有获得任何变量状态,所以您无法真正确定应归咎于哪个线程。 还是可以吗?

jstack的第二个缺点是它不是永远在线的工具。 这意味着当问题发生时,您必须在那里-在生产中这是罕见的事件。 在不断重启VM的弹性环境中,情况更是如此。

好的部分到了–让我们看一下两种技术,它们可以帮助我们克服这两个缺点,并使一个好的工具真正变得很棒。

创建有状态线程数据

第一个问题是如何向jstack打印输出添加状态? 答案简单而强大-线程名称。 尽管许多人错误地认为线程名称是不可变的,或者是操作系统确定的属性,但实际上,每个线程具有可变的且非常重要的特征。 这也是进入您的jstack流的关键所在。

实际的应用程序就像日志记录一样,一旦它通过诸如servlet,actor或Scheduler之类的入口点输入代码,就应该控制线程名。 此时,您需要将其名称设置为一个有意义的值,该值可以帮助您了解执行上下文和相关参数,从而可以帮助您隔离事务及其内容。

这很可能包括–

  1. 线程的用途(例如,处理消息,响应用户请求等)。
  2. 事务ID,使您能够识别跨不同机器和应用程序部分的此特定数据流。
  3. 参数值,例如servlet参数或要出队的消息的ID。
  4. 获得线程控制的时间。 对于使用jstack观察它们时,确切地知道代码中的哪些线程被卡住,最后一项至关重要。
Thread.currentThread().setName(Context + TID + Params + current Time,..);

这些数据将意味着查看打印输出(例如下面的打印输出实际上并不能告诉我们任何线程在做什么或为什么)与提供信息的输出之间的区别:

Object.wait()中的“ pool-1-thread-1”#17 prio = 5 os_prio = 31 tid = 0x00007f9d620c9800 nid = 0x6d03 [0x000000013ebcc000]

将此与以下线程打印输出进行比较:

“队列处理线程,MessageID:AB5CAD,类型:AnalyzeGraph,队列:ACTIVE_PROD,Transaction_ID:5678956,开始时间:2014/10/8 18:34”

#17 prio = 5 os_prio = 31 tid = 0x00007f9d620c9800 nid = 0x6d03 in Object.wait()[0x000000013ebcc000]

您在这里看到的是对该线程实际作用的更全面的解释。 您可以从AWS队列中轻松查看其出队消息,它正在分析该消息,其类型,ID和交易ID。 最后,但并非最不重要–线程何时开始对其进行处理。 这可以帮助您非常快速地将注意力集中在那些被卡住的线程上,并查看它们所处的状态。从那以后,在本地进行优化和重现变得更加容易。

这里的替代方案是要么希望日志文件中有数据,而且能够将日志中的数据关联到该确切线程。 另一种选择是在生产环境中本地或远程连接调试器。 既不是很愉快又很费时间。

在线程名称中写入此信息也有助于传统日志记录。 即使大多数日志记录框架提供了可以添加到日志中的基于线程的上下文,您也必须确保正确配置它。 使用线程名称还可以确保您将在日志中拥有所需的所有数据。

注意:某些人可能会说线程名称不可调整或更改。 从我多年的个人经验以及许多同事的经验来看,我是一个很小的信徒。

使jstack始终在线

当使用jstack时,我们面临的第二个挑战是,就像调试器一样,它是在问题发生时必须手动操作以捕获损坏状态的一种工具。 但是,当服务器挂起或低于或低于某个特定阈值时,有一种更活跃的方法可以使用jstack自动生成打印输出。 关键是要以编程方式调用jstack,就像在满足特定应用程序条件时从JVM中的任何日志记录功能一样。
这里的两个主要挑战是何时以及如何实现。

如何以编程方式激活jstack?

由于jstack是一个普通的OS进程,因此调用它非常简单。 您要做的就是激活jstack进程并将其指向您自己。 这里的关键是如何从JVM中获取进程的pid。 实际上,没有标准的Java API可以做到这一点( 至少要等到Java 9才能实现 )。 这是完成工作的一小段代码(尽管不是文档api的一部分):

String mxName = ManagementFactory.getRuntimeMXBean().getName();int index = mxName.indexOf(PID_SEPERATOR);String result;if (index != -1) {result = mxName.substring(0, index);
} else {throw new IllegalStateException("Could not acquire pid using " + mxName);
}

另一个小挑战是将jstack输出定向到您的日志中。 使用输出流检流器也很容易设置。 在此处查看有关如何将您调用的进程输出的输出数据定向到日志文件或输出流中的示例。

尽管可以使用getAllStackTraces在内部捕获正在运行的线程的堆栈跟踪,但出于多种原因,我更喜欢通过运行jstack来执行此操作。 首先,这是我通常希望在正在运行的应用程序外部进行的操作(即使JVM正在参与提供信息),以确保我不会通过进行内省性调用来影响应用程序的稳定性。 另一个原因是,jstack在功能方面更为强大,例如向您显示本机框架和锁定状态,而这在JVM中是不可用的。

什么时候激活jstack?

您需要做出的第二个决定是在什么条件下您希望JVM记录jstack。 当服务器低于或高于特定处理(即请求或消息处理)阈值时,可能会在预热期之后执行此操作。 您可能还需要确保每次激活之间都花费足够的时间。 只是为了确保您不会在低负载或高负载下泛滥日志。

您将在此处使用的模式是从JVM中加载看门狗线程,该线程可以定期查看应用程序的吞吐量状态(例如,最近两分钟内处理的消息数),并确定是否对屏幕进行“截屏”。线程状态将很有帮助,在这种情况下,它将激活jstack并将其记录到文件中。

设置此线程的名称以包含目标和实际吞吐量状态,因此当您执行自动jstack快照时,您可以确切地看到看门狗线程决定这样做的原因。 由于这只会每隔几分钟发生一次,因此该过程没有实际的性能开销,尤其是与所提供的数据质量相比。

以下是显示此模式的片段。 每当处理一条消息时,startScheduleTask加载一个看门狗线程以定期检查吞吐量值,该吞吐量值使用Java 8 并发加法器递增。

public void startScheduleTask() {scheduler.scheduleAtFixedRate(new Runnable() {public void run() {checkThroughput();}}, APP_WARMUP, POLLING_CYCLE, TimeUnit.SECONDS);
}private void checkThroughput()
{int throughput = adder.intValue(); //the adder in inc’d when a message is processedif (throughput < MIN_THROUGHPUT) {Thread.currentThread().setName("Throughput jstack thread: " + throughput);System.err.println("Minimal throughput failed: exexuting jstack");executeJstack(); //see the code on github to see how this is done}adder.reset();
}
  • 在此处可以找到从代码中抢先调用jstack的完整源代码。

翻译自: https://www.javacodegeeks.com/2014/10/supercharged-jstack-how-to-debug-your-servers-at-100mph.html

jstack调试

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/339170.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C/C 输入输出缓冲区

【导读】&#xff1a;本文介绍C与C 输入输出缓冲的一些操作与特性。以下是正文&#xff08;1&#xff09;c 中cin、cout&#xff0c;cerr和c的stdin、stdout、stderr都是同步的&#xff0c;即iostream 对象和 and cstdio流是同步的&#xff0c;同步关系如下&#xff1a;同步即表…

python输入input数组_python怎么输入数组

python怎么输入数组&#xff1f; python输入数组 一维数组&#xff1a;arr input("") //输入一个一维数组&#xff0c;每个数之间使空格隔开 num [int(n) for n in arr.split()] //将输入每个数以空格键隔开做成数组 print(num) //打印数组 一维数组输入输出示例&a…

eclipse 扩展_Eclipse扩展的轻量级集成测试

eclipse 扩展最近&#xff0c;我为Eclipse扩展点评估引入了一个小助手。 辅助程序努力减少通用编程步骤的样板代码&#xff0c;同时增加开发指导和可读性。 这篇文章是希望的后续文章&#xff0c;它显示了如何将实用程序与AssertJ定制断言结合使用&#xff0c;以编写针对Eclip…

深入理解右值引用,move语义和完美转发

move语义最原始的左值和右值定义可以追溯到C语言时代&#xff0c;左值是可以出现在赋值符的左边和右边&#xff0c;然而右值只能出现在赋值符的右边。在C 里&#xff0c;这种方法作为初步判断左值或右值还是可以的&#xff0c;但不只是那么准确了。你要说C 中的右值到底是什么&…

java future用法_纯干货:Java学习过程中的21个知识点和技术点

我们在Java学习过程中要学会抓重点&#xff0c;善于总结&#xff0c;Java学习过程中常见的21个知识点和技术点你知道吗&#xff1f;下面和千锋广州小编一起来看看吧&#xff01;1. JVM相关对于刚刚接触Java的人来说&#xff0c;JVM相关的知识不一定需要理解很深&#xff0c;对此…

如何优雅地检测类型/表达式有效性?

注1&#xff1a;本文至少需要编译器支持C 11。注2&#xff1a;本文不考虑使用宏。一、老办法在写C 的时候&#xff0c;有时候可能需要检查一个类是否有特定的成员类型&#xff0c;例如&#xff1a;// 检查 T::type 是否存在&#xff0c;存在则 value 为 true&#xff0c;否则为…

swagger api文档_带有Swagger的Spring Rest API –公开文档

swagger api文档创建API文档后&#xff0c;将其提供给涉众很重要。 在理想情况下&#xff0c;此发布的文档将足够灵活以解决任何最后的更改&#xff0c;并且易于分发&#xff08;就成本以及完成此操作所需的时间而言&#xff09;。 为了使之成为可能&#xff0c;我们将利用我在…

nuxt解决首屏加载慢问题_一个 Node 脚本让你的前端项目加载速度飞起来

写在最前面我的原创什么声明变成什么鬼了……前言随着前端三大框架的盛行&#xff0c;越来越多的前后端分离项目在服务器上跑了起来&#xff0c;随之而来&#xff0c;开发者也慢慢发现了这种开发模式所带来的弊端&#xff0c;其中之一就是首屏加载速度特别慢&#xff0c;因为虽…

数据库连接配置tomcat_Tomcat到Wildfly:配置数据库连接

数据库连接配置tomcat该摘录摘自《 从Tomcat到WildFly 》一书&#xff0c;您将在其中学习如何将现有的Tomcat体系结构移植到WildFly&#xff0c;包括服务器配置和在其顶部运行的应用程序。 WildFly是完全兼容的Java Enterprise Edition 7容器&#xff0c;与Tomcat相比&#xf…

左值、右值、左值引用、右值引用

【导读】&#xff1a;本文主要详细介绍了左值、右值、左值引用、右值引用以及move、完美转发。左值和右值左值&#xff08;left-values&#xff09;&#xff0c;缩写&#xff1a;lvalues右值&#xff08;right-values&#xff09;&#xff0c;缩写&#xff1a;rvalues直接上官网…

wxpython界面切换_wxpython实现按钮切换界面的方法

本文实例为大家分享了wxpython按钮切换界面的具体实现代码&#xff0c;供大家参考&#xff0c;具体内容如下 #-*- coding:utf-8 -*- import wx class TestFrame(wx.Frame): def __init__(self): wx.Frame.__init__(self,None,-1,u登陆,size(370,280),stylewx.MINIMIZE_BOX| wx.…

jboss 4.3.0_JBoss BPM Suite 6.0.3版本的5个实用技巧

jboss 4.3.0上周&#xff0c;红帽发布了JBoss BPM Suite的下一个版本&#xff0c;标记为6.0.3 &#xff0c;已订阅的用户可以在其客户门户中使用。 如果您对本发行版中的新增功能感到好奇&#xff0c;请在客户门户网站上在线查看发行说明和其余文档 。 我们正在寻找一些简单的…

C 条件变量使用详解

condition_variable介绍在C 11中&#xff0c;我们可以使用条件变量&#xff08;condition_variable&#xff09;实现多个线程间的同步操作&#xff1b;当条件不满足时&#xff0c;相关线程被一直阻塞&#xff0c;直到某种条件出现&#xff0c;这些线程才会被唤醒。其主要成员函…

pannel添加的子窗体很大_超简单的地瓜粉焖子做法全解,零失败

总以为做焖子是一项很大的工程&#xff0c;如果朋友知道你会做焖子定会用惊叹的语气崇拜你&#xff0c;想多一项厨艺吗&#xff0c;想让家人吃上自己亲手做的焖子吗&#xff1f;使用艺琳农场的地瓜粉一定让你出手不凡的&#xff0c;超简单&#xff0c;往下看哦新手为了担心霍霍…

多线程队列的算法优化

【导读】&#xff1a;本文主要讲解多线程队列的优化。多线程队列&#xff08;Concurrent Queue&#xff09;的使用场合非常多&#xff0c;高性能服务器中的消息队列&#xff0c;并行算法中的Work Stealing等都离不开它。对于一个队列来说有两个最主要的动作&#xff1a;添加&am…

linux 文件大小_整理 | Linux下列出目录内容命令

IT服务圈儿有温度、有态度的IT自媒体平台来源&#xff1a;良许Linux(ID&#xff1a;liangxuxiansheng)在 Linux 中&#xff0c;有非常多的命令可以让我们用来执行各种各样的任务。当我们想要像使用文件浏览器一样列出一个目录下的内容时&#xff0c;大家第一时间想到的是 ls 命…

多线程程序中操作的原子性

0. 背景原子操作就是不可再分的操作。在多线程程序中原子操作是一个非常重要的概念&#xff0c;它常常用来实现一些同步机制&#xff0c;同时也是一些常见的多线程Bug的源头。本文主要讨论了三个问题&#xff1a;1. 多线程程序中对变量的读写操作是否是原子的&#xff1f;2. 多…

.net mvc actionresult 返回字符串_ASP.NET Core中的Action的返回值类型

在Asp.net Core之前所有的Action返回值都是ActionResult&#xff0c;Json(),File()等方法返回的都是ActionResult的子类。并且Core把MVC跟WebApi合并之后Action的返回值体系也有了很大的变化。ActionResult类ActionResult类是最常用的返回值类型。基本沿用了之前Asp.net MVC的那…

.jdeveloper_在JDeveloper 12.1.3中为WebSocket使用Java API

.jdeveloper介绍 最新版本的JDeveloper 12c&#xff08;12.1.3.0&#xff09;和WebLogic Server 12.1.3一起提供了一些新的Java EE 7功能。 其中之一是对用于WebSocket的JSR 356 Java API的支持。 实际上&#xff0c;从12.1.2.0版本开始就支持WebSocket协议&#xff08;RFC 645…

为什么程序员需要关心顺序一致性,而不是 Cache 一致性?

本文所讨论的计算机模型是Shared Memory Multiprocessor&#xff0c;即我们现在常见的共享内存的多核CPU。本文适合的对象是想用C 或者Java进行多线程编程的程序员。本文主要包括对Sequential Consistency和Cache Coherence的概念性介绍并给出了一些相关例子&#xff0c;目的是…