本站提供互联网编程技术交流分享,部分技术教程不断更新中,请随时关注或联系我寻求帮助 ,同时也欢迎有兴趣的朋友进行投稿。

解决Skywalking对应的ES的CPU很高的问题

ELK 熊哥club 415℃ 1评论

结论

原因1:ES的新生代配置的太小,yong gc频率很高, 1s一次yonggc
解决方案:手动设置新生代、老年代比例 -XX:NewRatio=1

原因2:ES的索引没有配置为高性能写模式( 这个配置立杆见影 )
解决方案:对skywalking对应的index添加如下配置

 “index.merge.scheduler.max_thread_count” : “1”,
“index.refresh_interval” : “30s”,
“index.translog.durability” : “async”,
“index.translog.sync_interval” : “120s”

原因3: skywalking的agent上传JVM状态信息过于频繁,导致产生大量的ES request(这个不是主要原因)
解决方案: 修改agent代码,设置JVM上传频率为30s一次

环境

ES实例:4核 * 14G, 只有一台实例,基于docker起的
OAPServer:只有一台,512M
agent节点:也就是JVM实例大概50个

解决过程

agent 上传JVM信息太频繁

遇到的现象是,已经把oap-server的sample比例设置为1%了,可以看到skywalking中追踪的数据很少,但是发现ES所占CPU依然很高

image.png

修改oapServer把写入ES的BulkRequest的log级别修改为debug模式,发现短时间内的确有大量的Request

image.png

通过分析oapServer的堆栈发现:几乎所有的Request都是Metric相关的(service_relation_server_p90、instance_jvm_memory等等),而这里面的绝大部分又都是jvm相关的

jvisualvm

查看源码发现,jvm信息是通过单独的grpc接口上传到oapServer的,并且是1S收集一次, 1S上传一次,如此高频率的收集jvm数据,每一次收集的有多个指标(memory cpu gc),每个指标又根据分钟、小时、天、月更新多个index,就会导致产生大量的UpdateRequest对象,假设有50台JVM实例,每上传一次JVM数据产生18个Request,就会导致 50 * 18 = 900 个Request,也就是说,在没有处理任何TraceSegment的情况下,每秒就要产生900个Request

image.png

我这次是直接把1s修改成了30s,重新打包agent,部署、重启,查看日志发现发送到ES的Request相对来说是少了一些,但是ES的cpu占用并没有下降很多大概从300%下降至250%左右

ES的新生代配置的太小

由于我们是直接用docker起的ES,用的官方的镜像,官方镜像用的JDK12,在这个docker容器中jmap jstat并不能用,好在ES直接把gclog打印到了文件中,查看gclog才发现yonggc是如此的频繁,甚至不到1s一次

[2019-07-30T11:03:20.242+0000][1][gc,start     ] GC(158) Pause Young (Allocation Failure)
[2019-07-30T11:03:20.242+0000][1][gc,task      ] GC(158) Using 4 workers of 4 for evacuation
[2019-07-30T11:03:20.258+0000][1][gc,age       ] GC(158) Desired survivor size 17432576 bytes, new threshold 6 (max threshold 6)
[2019-07-30T11:03:20.258+0000][1][gc,age       ] GC(158) Age table with threshold 6 (max threshold 6)
[2019-07-30T11:03:20.258+0000][1][gc,age       ] GC(158) – age   1:     954344 bytes,     954344 total
[2019-07-30T11:03:20.258+0000][1][gc,age       ] GC(158) – age   2:       4864 bytes,     959208 total
[2019-07-30T11:03:20.258+0000][1][gc,age       ] GC(158) – age   3:       2256 bytes,     961464 total
[2019-07-30T11:03:20.258+0000][1][gc,age       ] GC(158) – age   4:     391800 bytes,    1353264 total
[2019-07-30T11:03:20.258+0000][1][gc,age       ] GC(158) – age   5:     119784 bytes,    1473048 total
[2019-07-30T11:03:20.258+0000][1][gc,age       ] GC(158) – age   6:       1456 bytes,    1474504 total
[2019-07-30T11:03:20.258+0000][1][gc,heap      ] GC(158) ParNew: 275195K->2126K(306688K)
[2019-07-30T11:03:20.258+0000][1][gc,heap      ] GC(158) CMS: 798450K->798452K(3853568K)
[2019-07-30T11:03:20.258+0000][1][gc,metaspace ] GC(158) Metaspace: 85950K->85950K(1128448K)
[2019-07-30T11:03:20.258+0000][1][gc           ] GC(158) Pause Young (Allocation Failure) 1048M->781M(4062M) 15.861ms
[2019-07-30T11:03:20.258+0000][1][gc,cpu       ] GC(158) User=0.06s Sys=0.00s Real=0.02s
[2019-07-30T11:03:20.258+0000][1][safepoint    ] Leaving safepoint region
[2019-07-30T11:03:20.258+0000][1][safepoint    ] Total time for which application threads were stopped: 0.0163155 seconds, Stopping threads took: 0.0001191 seconds
[2019-07-30T11:03:20.642+0000][1][safepoint    ] Application time: 0.3842620 seconds
[2019-07-30T11:03:20.642+0000][1][safepoint    ] Entering safepoint region: GenCollectForAllocation
[2019-07-30T11:03:20.643+0000][1][gc,start     ] GC(159) Pause Young (Allocation Failure)
[2019-07-30T11:03:20.643+0000][1][gc,task      ] GC(159) Using 4 workers of 4 for evacuation
[2019-07-30T11:03:20.659+0000][1][gc,age       ] GC(159) Desired survivor size 17432576 bytes, new threshold 6 (max threshold 6)
[2019-07-30T11:03:20.659+0000][1][gc,age       ] GC(159) Age table with threshold 6 (max threshold 6)
[2019-07-30T11:03:20.659+0000][1][gc,age       ] GC(159) – age   1:    1309016 bytes,    1309016 total
[2019-07-30T11:03:20.659+0000][1][gc,age       ] GC(159) – age   2:      38944 bytes,    1347960 total
[2019-07-30T11:03:20.659+0000][1][gc,age       ] GC(159) – age   3:       2616 bytes,    1350576 total
[2019-07-30T11:03:20.659+0000][1][gc,age       ] GC(159) – age   4:        720 bytes,    1351296 total
[2019-07-30T11:03:20.659+0000][1][gc,age       ] GC(159) – age   5:     378152 bytes,    1729448 total
[2019-07-30T11:03:20.659+0000][1][gc,age       ] GC(159) – age   6:     111352 bytes,    1840800 total
[2019-07-30T11:03:20.659+0000][1][gc,heap      ] GC(159) ParNew: 274766K->2257K(306688K)
[2019-07-30T11:03:20.659+0000][1][gc,heap      ] GC(159) CMS: 798452K->798453K(3853568K)
[2019-07-30T11:03:20.659+0000][1][gc,metaspace ] GC(159) Metaspace: 85950K->85950K(1128448K)

关键是无论怎么增大Xms XmX和deploy.resources.limits.memory都不管用,新生代的大小都是只有275195K这么大,下面是我们的ES启动配置

image.png

后来网上搜了之后才发现,原来CMS 默认的新生代并不是总堆大小的1/3,必须显式设置XX:NewRatio才可以。可以参考https://www.jianshu.com/p/832fc4d4cb53
于是手动设置XX:NewRatio=1,设置了之后发现yonggc频率变成大概6s一次,CPU占用也大概下降至180%左右,其实6s一次还是挺频繁,后续还是需要考虑增加ES的node,以及增加内存来分散压力

ES的高性能写模式

其实这块儿主要参考了https://blog.csdn.net/lengxiangwu/article/details/90445014,大家可以直接看这篇博文
或者参考官网:https://www.elastic.co/guide/en/elasticsearch/reference/6.8/tune-for-indexing-speed.html
核心就是修改index的设置, 个人实现发现主要起作用的是index.refresh_interval这个参数

“index.merge.scheduler.max_thread_count” : “1”,
“index.refresh_interval” : “30s”,
“index.translog.durability” : “async”,
“index.translog.sync_interval” : “120s”

由于skywalking是通过template的方式创建index,一个一个修改template的配置比较麻烦,我就直接修改了skywalking的代码,添加了上面的配置,然后批量删除旧的与日期相关的index(之所以没有全部删除是因为全部删除的话需要重启agent), 重新打包、部署skywalking-server

org.apache.skywalking.oap.server.storage.plugin.elasticsearch.base.StorageEsInstaller

private JsonObject createSetting() {
JsonObject setting = new JsonObject();
setting.addProperty(“index.number_of_shards”, indexShardsNumber);
setting.addProperty(“index.number_of_replicas”, indexReplicasNumber);
setting.addProperty(“analysis.analyzer.oap_analyzer.type”, “stop”);

//custom config for better es update performance
setting.addProperty(“index.refresh_interval”, “30s”);
setting.addProperty(“index.translog.durability”, “async”);
setting.addProperty(“index.translog.sync_interval”, “120s”);
setting.addProperty(“index.merge.scheduler.max_thread_count”, “1”);
return setting;
}

重启skywalking-server,查看es的index配置,发现配置已经生效

image.png

再次观察ES的CPU占用情况,已经降到了100%左右,至此 ES的CPU优化暂告一段落吧, 由于skywalking对ES的操作实在是太多了,想完全把ES的CPU降下来是不太现实的,只能考虑增加ES机器,减小采样频率了

 

本文地址: https://www.xiongge.club/1416.html

转载请注明:熊哥club » 解决Skywalking对应的ES的CPU很高的问题


关注微信公众号『熊哥club』

免费提供IT技术指导交流
  关注博主不迷路~

喜欢 (2)
[您的支持是我最大的动力]
分享 (0)
发表我的评论
取消评论
表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
(1)个小伙伴在吐槽
  1. 膜拜大神
    爱因斯坦耿2019-08-21 15:47 回复
×
订阅图标按钮