前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >垃圾收集不健康的JVM,这是一种主动方法

垃圾收集不健康的JVM,这是一种主动方法

原创
作者头像
可大可小
修改于 2020-03-23 10:16:49
修改于 2020-03-23 10:16:49
1.5K00
代码可运行
举报
运行总次数:0
代码可运行

Netflix的云数据工程团队运行各种JVM应用程序,包括诸如Cassandra和Elasticsearch之类的流行数据存储。尽管我们大多数集群在分配给它们的内存下都能稳定运行,但有时“死亡查询”或数据存储区本身的错误将导致内存使用失控,这可能触发垃圾回收(GC)循环甚至运行JVM内存不足。

我们已经对jvmkill进行了补救,以纠正这种情况:jvmkill是使用JVMTI API 在JVM进程中运行的代理。当JVM内存不足或无法产生线程时,jvmkill介入并杀死整个过程。我们将jvmkill与-XX:HeapDumpOnOutOfMemoryError Hotspot标志结合使用,以便我们可以在事后再分析堆,目的是了解为什么我们会用光资源。对于我们的应用程序,这种情况是理想的:内存不足的JVM无法前进,并且一旦jvmkill介入,systemd将从干净的状态重新启动失败的进程。

即使使用jvmkill保护我们,我们仍然遇到JVM的问题,这些JVM几乎(但不是完全)内存不足。这些Java进程一遍又一遍地执行GC,在暂停之间几乎没有做任何有用的工作。由于JVM不是100%占用资源,因此jvmkill不会发现问题。另一方面,我们的客户很快注意到其数据存储节点的吞吐量通常下降了四个数量级。

为了说明这种行为,我们可以通过要求Cassandra几次将整个数据集加载到内存中来演示针对CassandraJVM¹的“死亡查询”:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
cqlsh> PAGING OFF
Disabled Query paging.
cqlsh> SELECT * FROM large_ks.large_table;
OperationTimedOut: errors={}, last_host=some host
cqlsh> SELECT * FROM large_ks.large_table;
Warning: schema version mismatch detected, which might be caused by DOWN nodes; if this is not the case, check the schema versions of your nodes in system.local and system.peers.
Schema metadata was not refreshed. See log for details.

然后,我们使用jstat和GC日志来观察机器确实处于GC死亡螺旋中:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ sudo -u cassandra jstat -gcutil $(pgrep -f Cassandra) 100ms
S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT
0.00 100.00 100.00 100.00  97.96  95.10     21    8.678    11  140.498  149.176
0.00 100.00 100.00 100.00  97.96  95.10     21    8.678    11  140.498  149.176
0.00 100.00 100.00 100.00  97.96  95.10     21    8.678    11  140.498  149.176
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ grep "stopped" gclog | tail
2019-03-05T02:59:15.111+0000: 1057.680: Total time for which application threads were stopped: 18.0113457 seconds, Stopping threads took: 0.0001798 seconds
2019-03-05T02:59:16.159+0000: 1058.728: Total time for which application threads were stopped: 1.0472826 seconds, Stopping threads took: 0.0001542 seconds
2019-03-05T02:59:40.461+0000: 1083.030: Total time for which application threads were stopped: 24.3016592 seconds, Stopping threads took: 0.0001809 seconds
2019-03-05T03:00:16.263+0000: 1118.832: Total time for which application threads were stopped: 35.8020625 seconds, Stopping threads took: 0.0001307 seconds
2019-03-05T03:00:51.599+0000: 1154.168: Total time for which application threads were stopped: 35.3361231 seconds, Stopping threads took: 0.0001517 seconds
2019-03-05T03:01:09.470+0000: 1172.039: Total time for which application threads were stopped: 17.8703301 seconds, Stopping threads took: 0.0002151 seconds

从GC日志数据中,我们可以清楚地看到重复的20秒钟以上的暂停,并且我们可以使用GCViewer工具以图形方式解释日志中存在的数据:

在这种情况下,JVM当然无法满足我们的性能目标,并且恢复的希望很小。这种死亡螺旋一直持续到我们的值班工程师通过杀死受影响的JVM采取行动为止。在被翻页太多次之后,我们决定出现此问题:

  1. 很容易识别
  2. 有一个简单的解决方案
  3. 受益于快速干预

换句话说,我们认为我们需要自动化人类先前手动执行的政变。

解决方案:主动识别并杀死不良的JVM

我们真的很喜欢jvmkill方法,因此我们研究了扩展jvmkill来添加所需行为的方法。jvmkill挂接ResourceExhausted JVMTI回调,根据JVM自己对资源耗尽的评估,向患病的JVM发送SIGKILL。不幸的是,这个简单的分类器无法很好地应对灰色故障模式,在这种模式下,JVM花费大量时间进行垃圾回收,但它并没有耗尽资源。我们还检查了现有的JVM选项,例如GCHeapFreeLimit,GCTimeLimit,OnOutOfMemoryError,ExitOnOutOfMemoryError和CrashOnOutOfMemoryError。我们发现这些选项或者不能在所有的JVM和垃圾收集器上一致地工作,难以调整或理解,或者根本就不能在各种情况下工作。。由于调整现有JVM的资源消耗分类器的性质不一致且困难/不可能,因此我们决定构建自己的分类器以对其进行补充。

我们的解决方案jvmquake始于晚上沉思,“这到底有多难?” 我们首先想到的是,对于任何给定的工作负载,JVM应该将其大部分时间用于运行程序代码,而不是暂停GC。如果程序时间所占的比例低于某个水平的时间太长,则JVM显然是不健康的,应该将其杀死。

我们通过将JVM暂停GC的时间建模为“债务”来实现此想法。如果JVM花200毫秒的GC时间,它将增加200毫秒的债务计数器。运行程序代码所花费的时间“偿还”了所有累积的债务,并在零时停止,因此,如果同一程序然后运行≥200ms,其债务计数器将降至零。如果JVM花费的运行时间与GCing的时间之比超过1:1(即吞吐量> 50%),则其债务将趋于零。另一方面,如果其吞吐量不到50%,其债务将趋于无限。这种“债务计数器”方法类似于用于跟踪程序吞吐量的漏斗算法。在这种情况下,我们以与GC时间成比例的速率添加水,并与应用程序运行时间成比例地删除水:

随着JVM债务计数器的增加,我们越来越确信它是不健康的,最终我们获得了足够的信心来采取某些措施。例如,应用jvmquake的真实世界的GC螺旋可能类似于

如果jvmquake附加在此JVM上,它将在虚线处停止。

我们确定了一个可调整的阈值,默认值为30秒,这很宽松:如果JVM在其债务计数器超过30秒时完成了GC,jvmquake将终止该进程。我们通过挂钩GarbageCollectionStartGarbageCollectionFinish JVMTI回调来测量这些值。

除了债务阈值外,我们还添加了两个可调参数:

  • runtime_weight:将乘数应用于花费在运行程序代码上的时间,以便我们可以实现除1:1(50%吞吐量)以外的吞吐量目标。例如,runtime_weight为2表示目标是1:2(吞吐量为33%)。更一般而言,x的runtime_weight表示1:x比率(100%/(x + 1)吞吐量)。服务器JVM通常以超过95%的吞吐量运行,因此,即使最低50%的吞吐量也是相当保守的。
  • 行动:jvmkill只会向该进程发送SIGKILL,但是在jvmquake中,我们添加了有意OOM JVM以及在SIGKILL之前向自己发送任意信号的功能。在下一节中,我们将解释为什么可能需要执行这些其他操作。

应用jvmquake之后,如果我们对Cassandra节点运行相同的死亡查询,现在我们看到:

就像以前一样,JVM开始进入GC的死循环,但是这次jvmquake注意到JVM累积了30倍的GC债务(以4:1的运行时权重)并停止了JVM。与其像JVM那样被永久杀死,不如将其永久固定。

不要丢掉证据!

当我们使用jvmkill或手动终止JVM时,我们总是有机会分别使用-XX:HeapDumpOnOutOfMemoryError或jmap来收集堆转储。这些堆转储对于调试事实之后调试内存泄漏的根本原因至关重要。不幸的是,当jvmquake将SIGKILL发送到尚未遇到OutOfMemoryError的JVM时,这些方法都不起作用。我们对此的解决方案很简单:jvmquake触发时,它会激活一个线程,该线程有意将堆上的大型数组分配给JVM的OOM。这将触发-XX:HeapDumpOnOutOfMemoryError功能,并最终终止该进程。

但是,这有一个严重的问题:Java堆转储被写入并存储在磁盘上,如果我们反复执行自动终止操作,可能会填满磁盘。因此,我们开始研究获取OS本地核心转储而不是JVM特定的堆转储的方法。我们意识到,如果我们可以让一个不健康的JVM发送自己的SIGABRT而不是SIGKILL,则Linux内核将自动为我们编写一个核心转储。我们喜欢这种方法,因为它是所有语言运行时(包括尤其是node.js和Python)的标准配置,最重要的是因为它允许我们收集甚至非常大的核心/堆转储并将其写入管道,而无需向驱动器提供额外的磁盘空间。储存它们。

当Linux进行核心转储时,默认行为是在崩溃的进程的工作目录中写入一个名为“ core”的文件。为了防止写入核心文件会导致磁盘空间不足的情况,Linux对写入的核心文件的大小提供了资源限制(ulimit -c)。默认资源限制为零,因此内核根本不写入任何核心文件。但是,使用kernel.core_pattern sysctl,可以指定应将核心转储通过管道传输到的程序(请参见核心手册页中的“将核心转储管道传输到程序” )。在此界面之后,我们编写了一个脚本来压缩核心文件并执行流传输上载到S3,并与有关崩溃程序的元数据一起存储到S3。

流上传完成后,systemd将重新启动OOMed JVM。这是一个折衷:我们将核心文件同步上传到S3,而不必考虑是否需要在本地存储核心文件。实际上,我们能够在不到两分钟的时间内可靠地上传16GB核心转储。

告诉我出了什么问题

现在已经捕获了核心转储文件,我们可以对其进行检查以显示出问题的根源–是错误的查询,硬件问题还是配置问题?在大多数情况下,原因可以从使用的类及其大小中确定。

我们的团队已将jvmquake部署到我们所有的Java数据存储中。到目前为止,它已减轻了数十次事件(每次仅几分钟),并提高了一些我们最重要的生产数据库集群的可用性。此外,流核心转储和脱机转换工具使我们能够调试和修复Cassandra和Elasticsearch数据存储产品中的复杂错误,以便我们的应用程序获得所需的“始终可用”的数据存储。我们已经将许多补丁添加回了社区,我们期待着发现并解决更多的问题。

脚注

¹特别是Cassandra 2.1.19,具有大约20GiB的数据和12GiB的堆。在本实验中,我们关闭了DynamicEndpointSnitch,以确保查询可以路由到本地副本,并关闭分页以确保该节点将整个数据集保存在内存中

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
Tesseract OCR初探
Refer from http://hellosure.github.io/ocr/2014/10/11/tesseract-ocr/
全栈程序员站长
2022/07/25
7.6K0
Tesseract OCR初探
OpenCV Python + Tesseract-OCR轻松实现中文识别
下载Tesseract-OCR 5.0.0-alpha.20201127安装包并安装!然后在环境变量中添加
小白学视觉
2021/01/06
10.6K0
OpenCV Python + Tesseract-OCR轻松实现中文识别
javaCV文字识别篇汇总:Tesseract介绍,Java如何使用Tesseract识别字符,如何使用Tesseract训练中文数据模型,Tesseract支持哪些格式标注数据
Tesseract 是一个开源的 OCR(光学字符识别)引擎,最初由惠普实验室开发,后来由 Google 接管并开源。OCR 是一种将图像中的文本转换为可编辑文本的技术,它可以自动识别图像或扫描文档中的文字,并将其转换为数字形式。
csdn博主eguid_1
2024/05/26
1.7K0
tesseract-ocr 实现图片识别功能
http://blog.sina.com.cn/s/blog_56d988430102w37c.html
bear_fish
2018/09/19
6.1K0
tesseract-ocr 实现图片识别功能
【.NET】使用OpenCV和tesseract-ocr引擎实现识别图片文字内容
https://tesseract-ocr.github.io/tessdoc/Installation.html
Wesky
2024/08/13
5680
【.NET】使用OpenCV和tesseract-ocr引擎实现识别图片文字内容
Java使用Tesseract-OCR实战
tesseract-ocr-w64-setup-v5.3.0.20221214.exe 选择安装目录,下一步,下一步默认安装
九转成圣
2024/04/10
6210
[AI测试]python文字图像识别tesseract
github官网:https://github.com/tesseract-ocr/tesseract
梦无矶小仔
2023/09/08
1.7K0
[AI测试]python文字图像识别tesseract
C#使用Tesseract C++ API过程记录
Tesseract 是一个开源的光学字符识别(OCR)引擎,最初由 Hewlett-Packard(惠普)实验室开发,后来由 Google 收购并继续维护和开源贡献。Tesseract 可以识别多种语言的文字,广泛应用于将图片或扫描文档中的文本内容转换成可编辑的文本格式。随着深度学习技术的发展,Tesseract 也整合了基于深度神经网络的 OCR 模型,提升其识别准确率,特别是对于复杂排版和手写体的识别效果有所改善。
郑子铭
2025/02/19
2010
C#使用Tesseract C++ API过程记录
使用Tesseract-OCR训练文字识别记录
部分图片可能由于背景颜色关系,导致此张图片无法识别,可跳过继续下一张识别。
bear_fish
2018/09/19
3.1K0
使用Tesseract-OCR训练文字识别记录
R+OCR︱借助tesseract包实现图片文本提取功能
参数: image 图片文件路径,支持png、tiff、jpeg等格式 engine tesseract引擎,通过函数tesseract()来创建 language 训练数据的语言字符简写,默认为英语(eng) datapath 训练数据的路径,模型为系统库 options tesseract引擎的相关参数,默认为NULL,可查看文档 cache 可以使用训练数据的缓存版本,默认为TRUE
悟乙己
2019/05/26
2.6K0
tesseract-ocr识别英文和中文图片文字以及扫描图片实例讲解
本文参考http://blog.sina.com.cn/s/blog_4aa166780101cji7.html实现,在这里感谢该文章的作者。 OCR(Optical Character Recognition):光学字符识别,是指对图片文件中的文字进行分析识别,获取的过程。 Tesseract:开源的OCR识别引擎,初期Tesseract引擎由HP实验室研发,后来贡献给了开源软件业,后经由Google进行改进,消除bug,优化,重新发布。当前版本为3.02 项目下载地址为:http://jaist.dl.
朱晓霞
2018/04/18
8.7K1
tesseract-ocr识别英文和中文图片文字以及扫描图片实例讲解
tesseract-ocr验证码识别
下载安装tesseract-ocr-setup-3.02.02 训练工具jTessBoxEditor-2.3.0 下载地址
丁D
2022/08/12
1.6K0
tesseract-ocr验证码识别
开源免费图片文字识别 OCR 工具 tesseract v4.1.0 的 Docker 镜像制作与使用
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
耕耘实录
2019/09/18
5.1K0
爬取微信公众号所有历史文章 - (03) python结合tesseract-ocr做图文识别
前面我们讲到了adb的封装,里面具体讲到到了在一副图片中寻找目标的坐标并点击。这篇文章我们讲讲对一副图片的特定区域做截取,并利用开源库做图纹识别。
efonfighting
2019/08/02
1.5K0
爬取微信公众号所有历史文章 - (03) python结合tesseract-ocr做图文识别
教程 | Adrian小哥教程:如何使用Tesseract和OpenCV执行OCR和文本识别
本教程将介绍如何使用 OpenCV OCR。我们将使用 OpenCV、Python 和 Tesseract 执行文本检测和文本识别。
机器之心
2018/10/22
4.1K0
教程 | Adrian小哥教程:如何使用Tesseract和OpenCV执行OCR和文本识别
Tesseract-OCR 4.1.0 安装和使用— windows及CentOS
 OCR(Optical character recognition) —— 光学文字识别,是图像处理的一个重要分支,中文的识别具有一定挑战性,特别是手写体和草书的识别,是重要和热门的科学研究方向
NaughtyCat
2020/10/09
3.9K1
Tesseract-OCR 4.1.0 安装和使用— windows及CentOS
Python 实现识别弱图片验证码
目前,很多网站为了防止爬虫肆意模拟浏览器登录,采用增加验证码的方式来拦截爬虫。验证码的形式有多种,最常见的就是图片验证码。其他验证码的形式有音频验证码,滑动验证码等。图片验证码越来越高级,识别难度也大幅提高,就算人为输入也经常会输错。本文主要讲解识别弱图片验证码。
猴哥yuri
2018/08/16
4.2K0
开源OCR引擎Tesseract
知名的开源OCR引擎Tesseract 3.0版本日前发布,可以在项目网站下载:http://code.google.com/p/tesseract-ocr, 新版本支持中文,中文语言包定义http:
张善友
2018/01/30
8.4K0
tesseract-ocr的使用
——显示出tesseract的版本号则表示安装,及环境变量配置成功。否则根据提示检查安装失败原因
搁浅同学
2022/07/21
1.3K0
利用tess-two和cv4j实现简单的ocr功能、
Tesseract是Ray Smith于1985到1995年间在惠普布里斯托实验室开发的一个OCR引擎,曾经在1995 UNLV精确度测试中名列前茅。但1996年后基本停止了开发。2006年,Google邀请Smith加盟,重启该项目。目前项目的许可证是Apache 2.0。该项目目前支持Windows、Linux和Mac OS等主流平台。但作为一个引擎,它只提供命令行工具。 现阶段的Tesseract由Google负责维护,是最好的开源OCR Engine之一,并且支持中文。
fengzhizi715
2018/08/24
1.5K0
利用tess-two和cv4j实现简单的ocr功能、
推荐阅读
相关推荐
Tesseract OCR初探
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档