运维大规模分布式系统的比较重要的一个挑战是可以有能力指出关键问题所在。在没有证据支持某种说法的情况下,当故障出现时,总是责怪组件(通常是数据库)的偶然性问题是很常见的一件事。我们已经讨论过监控工具、图形化输出、以及报警metric的重要性,并使用分布式tracing系统(比如zikin)去正确的辨别复杂系统的根源问题。
一旦你把问题缩小到一个单一的系统上面,你会怎么做?通常我们都会说这个会具体问题具体对待。有的问题是临时的,比如坏盘。有的问题却涉及到人为引入的变化,比如部署或者是错误的配置。这些都是有直接简单的解决办法:换盘或者是回滚部署。
但是如果出现的问题超出简单变化的范畴,那怎么办?到现在为止还没有提到的是规模增长造成的问题。规模可以成为另一个困难的问题,因为复现这个问题一般情况下是很微妙且复杂的。这些挑战有时是通过吞吐量(每秒请求数)、大小(兆字节)或延迟(5ms p99)来衡量的。例如,如果数据库服务器能够在内存不足的情况下为每个请求提供服务,那么它可能获得极好的吞吐量。随着数据集大小的增加,随机查找越来越可能进入磁盘,从而降低吞吐量。Time Window Compaction Strategy 是解决规模问题的一个很好的例子,除非有数字表明,否则还是很难理解的。除非遇到很大量的数据,否则你不会体会到compaction带来的痛苦,下规模情况下,很难遇到什么问题。
在失败期间,我们经常会把机器以及他们的程序执行过程当做一个黑盒子。几十亿条指令每秒都在执行,但是我们却没有办法看到内部的奥秘。很幸运的是,我们并没有完全忽略机器在做什么。多年来我们已经有了debugger以及profiler工具。 Oracle的JDK也为我们提供了Java Flight Recorder,我们可以使用它来分析本地或者生产中运行的流程。
通过 flight recorder 进行profile是简单而直白的,但是想要翻译这个结果却需要一定的工作量。把上面的列表一一展开并查找需要的问题更消耗劳动力。 但是我们如果可以将信息可视化展出的话那么就更好了。 但是这却需要商业的license且仅能在Oracle的JDK上运行。
这就引入了我们上面列出的标题:一种可以展示可视化信息的方法,叫做火焰图。火焰图让我们可以快速的找出系统中的性能瓶颈。 由Brendan Gregg 发明。这也是一系列非常长的性能调整文章的第一部分,我们将在深入研究Cassandra的内部结构时再次提到它。
Swiss Java Knife
我们在本文中研究的方法将要用到Swiss Java Knife ,通常叫做SJK,用它来获取JVM的数据并生成火焰图。SJK是一个很不错的工具集,除了生成火焰图以外,我们可以使用它收集统计信息、监视线程以及执行各种其他诊断任务。它可以在MAC、Linux以及oracle JDK和Open JDK上工作。
我已经下载了jar,把它放在$home/bin中,并设置了一个shell函数来轻松调用它:
sjk(){
java -jar ~/bin/sjk-plus-0.8.jar "@"
}
在我的电脑上,我使用cassandra-stress进行压测,我已经部署好了我的数据库,并开始使用下面的命令压测:
cassandra-stress read n=1000000
在分析的第一步中,我们需要使用SJK的stcap特性捕获正在运行的java应用程序的堆栈帧。为此,我们需要传入进程id和将数据转储到的文件。转储是以二进制格式编写的,我们稍后可以查询:
sjk stcap -p 92541 -i 10ms -o dump.std
然后我们可以分析数据。如果我们只有一个终端,我们可以打印出分析的柱状图。如果有明显的问题,这一点本身就非常有用。在这种情况下,我们可以看到很多时间都花在sun.misc.unsafe.park上,这意味着线程只是在等待,停在:
$ sjk ssa -f dump.std --histo
Trc (%) Frm N Term (%) Frame
372447 96% 372447 0 0% java.lang.Thread.run(Thread.java:745)
309251 80% 309251 309251 80% sun.misc.Unsafe.park(Native Method)
259376 67% 259376 0 0% java.util.concurrent.locks.LockSupport.park(LockSupport.java:304)
254388 66% 254388 0 0% org.apache.cassandra.concurrent.SEPWorker.run(SEPWorker.java:87)
55709 14% 55709 0 0% java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
52374 13% 52374 0 0% org.apache.cassandra.concurrent.NamedThreadFactory$$Lambda$6/1758056825.run(Unknown Source)
52374 13% 52374 0 0% org.apache.cassandra.concurrent.NamedThreadFactory.lambda$threadLocalDeallocator$0(NamedThreadFactory.java:81)
44892 11% 44892 0 0% io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:138)
44887 11% 44887 0 0% java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
42398 11% 42398 0 0% io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:409)
42398 11% 42398 0 0% io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:858)
42398 11% 42398 0 0% io.netty.channel.nio.NioEventLoop.select(NioEventLoop.java:753)
42398 11% 42398 0 0% sun.nio.ch.KQueueArrayWrapper.poll(KQueueArrayWrapper.java:198)
42398 11% 42398 0 0% sun.nio.ch.KQueueSelectorImpl.doSelect(KQueueSelectorImpl.java:117)
42398 11% 42398 42398 11% sun.nio.ch.KQueueArrayWrapper.kevent0(Native Method)
42398 11% 42398 0 0% sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:86)
42398 11% 42398 0 0% sun.nio.ch.SelectorImpl.select(SelectorImpl.java:97)
然后我们就有了我们的stcap的dump,通过下面的命令,可以生成我们的火焰图:
sjk ssa --flame -f dump.std > flame-sjk.svg
当你使用浏览器打开svg的文件的时候,你可以看到下面的图:
如果打开机器上的flame图,可以将鼠标移到不同的部分上,查看方法调用和所用时间的百分比。横坐标长度越宽,在stack里出现的频率就越高。浏览图表很容易理解我们的程序在哪里花费时间。
这并不是生成火焰图的唯一技术。Brendan Gregg 有一长串的链接和参考资料,我建议详细阅读在他的火焰图页。我打算编写一个实用程序,将SJK格式导出为brendan在他的博客上使用的格式,因为它看起来更好一些,鼠标悬停更好,支持向下钻取,还有搜索功能。它们还支持不同的flame图,如果您要在不同的构建中进行性能比较,这是很好的方式。
我希望你喜欢这篇关于用火焰图可视化Cassandra文章。我们已经与我们合作过的团队多次使用这个工具来调整Cassandra的配置并优化性能。在本系列的下一篇文章中,我们将研究如何调整垃圾收集参数以最大化吞吐量,同时将延迟保持在最低限度。
译者注:
1.生成火焰图的方式很多,文章中说的是一种方式,可以参考Brendan Gregg 一系列文章;
2.上述是针对Cassandra生成的火焰图,对于其他的java平台软件也适用,比如HBase、Spark等;
3.可以生成c++ 等其他平台的软件的火焰图,不仅仅限于java程序,使用的profile工具不仅仅是SJK,也可以是perf、systemtap;
4.火焰图不仅仅限于cpu(on-cpu、off-cpu),还可以绘制出内存、磁盘等的火焰图。
翻译自:https://thelastpickle.com/blog/2018/01/16/cassandra-flame-graphs.html
入群邀约
为了营造一个开放的 Cassandra 技术交流环境,社区建立了微信群公众号和钉钉群,为广大用户提供专业的技术分享及问答,定期开展专家技术直播,欢迎大家加入。另外阿里云提供免费Cassandra试用:https://www.aliyun.com/product/cds