注册中心
案例一(jvm内存猛增)
问题描述
eureka主从节点之间同步频繁出现超时现象,客户端连接eureka节点出现超时现象.
解决思路
- 群里出现告警,告警信息为eureka-master节点HealthCheck超时
- 登录eureka-master节点查看日志发现内部出现大量peerNode数据同步超时的error
- eureka-master节点的配置为100C128G
- jvm分区比例未优化
- 回回收器默认(parallel)
- 观察jvm情况MinorGC执行非常频繁
- 使用jstat -gcutil观察发现MinorGC每次进入Old的对象非常少
- MinorGC优化,修改-XX:NewRatio为2(默认为4),修改后效果依然不明显
- 更换GC为G1,效果依然不明显MinorGC依然执行非常频繁,118GEden区7秒钟满
- 怀疑有大量业务方错误想eureka注册
- 直接查看pod监控,网卡并无异常(3mb/s)
- tcpdump抓包发现频繁注册(之前已在日志中发现),推测也并无异常
- 定位具体产生的对象是什么尝试对堆内存dump(之所以不dump是因为会造成eureka服务长时间STW)
- 观测dump文件发现存在较大对象
- 使用jstack和arthas:thread查看cpu占用高的调用栈
- 根据栈信息逐行分析代码定位到异常问题
解决过程
查看日志发现无法找到该实例
2021-05-09 06:59:52.042 [http-nio-8761-exec-17] WARN c.netflix.eureka.registry.AbstractInstanceRegistry - DS: Registry: lease doesn't exist, registering resource: PS-COMMON-TEXT-REG - ps-common-text-reg-v21-6787668d4c-gsbgz:PS-COMMON-TEXT-REG:5012
找到该实例
继续查找日志发现重新注册
2021-05-09 07:07:26.965 [http-nio-8761-exec-131] INFO c.netflix.eureka.registry.AbstractInstanceRegistry - Registered instance PS-COMMON-TEXT-REG/ps-common-text-reg-v21-6787668d4c-gsbgz:PS-COMMON-TEXT-REG:5012 with status UP (replication=false)
tcpdump抓包正常
查看jvm信息
查看GC执行情况
查看dump文件
num #instances #bytes class name
----------------------------------------------
1: 132193235 9314511896 [C
2: 164906141 6596245640 java.util.ArrayList
3: 166927161 5341669152 java.util.concurrent.ConcurrentLinkedQueue$Node
4: 105870077 5081763696 java.util.concurrent.ConcurrentHashMap$Node
5: 78156812 5002035968 java.util.LinkedHashMap$Entry
6: 156092464 4995455464 [Ljava.lang.String;
7: 78072784 4372075904 com.netflix.appinfo.LeaseInfo
8: 6701361 3218090296 [Ljava.util.concurrent.ConcurrentHashMap$Node;
9: 5531702 2690989264 [Ljava.util.HashMap$Node;
10: 67130523 2148176736 java.lang.String
11: 7645406 1826270272 [Ljava.lang.Object;
12: 4402625 457873000 java.util.concurrent.ConcurrentHashMap
13: 209387 445898704 [I
14: 7156661 400773016 java.util.LinkedHashMap$LinkedKeyIterator
15: 3557977 313101976 java.util.LinkedHashMap
16: 3556435 284514800 java.util.concurrent.ConcurrentHashMap$EntryIterator
17: 7091754 283670160 com.netflix.discovery.shared.Applications$VipIndexSupport
18: 10638167 255316008 java.util.concurrent.atomic.AtomicReference
19: 7105900 227388800 java.util.concurrent.ConcurrentLinkedQueue
20: 4543434 218084832 java.util.concurrent.ConcurrentHashMap$ReservationNode
21: 3546001 198576056 com.netflix.discovery.shared.Application
查看高cpu栈信息
定位代码
修改方案
根据源码可以知道实际产生大量内存对象的原因是因为InstanceRegistry会组装获取所有的Instance导致遍历所有的实力信息,会产生大量的临时对象,这些临时对象在每一次续约的时候都会调用,SpringCloud之所以会增加这个额外的功能是为了在续约的时候发布一个事件,并且在发送的过程中携带本次续约的具体信息.
但是我们实际上没有用到这个事件而且这个对内存以及cpu的占用过大但实际并没有任何收益,所以我们可以直接将这段代码注释掉就可以了.
更多的优化
在使用netstat查看pod上网络状态的情况是我发现有大量的连接(我们eureka管理了大约8000个服务)按照标准的美30秒进行一次续约来计算每天大约2300w次调用每秒533次这种情况下一Tomcat作为作为容器其实问题也不大但是可以考虑将容器直接换位Netty
再就是目前有些业务方在使用的时候是只对master节点进行操作导致master节点的压力远远大于其他节点,目前我们的集群模式是一主两从,在后期使用可以考虑在集群前加一个lb进行负载保证集群压力均衡.