集群间同步导致的内存溢出(二)

现在网络发展这么迅速,传统的程序架构已经不适合这个高速发展的时代了,现在基本上都是分布式,微服务,它们之间的端点都是用集群来搭建的,有的消息队列,像kafka,注册中心,像zookeeper都是集群化,更别说缓存(redis),MySQL了,更得集群化啊,其实前面那篇文章用Nginx也与集群化相识,比如Tomcat当服务器,那它就是集群化的Tomcat

1、案例介绍:有一个基于B/S的MIS系统(管理信息系统),硬件为两台2个CPU,8GB内存的HP小型机,服务器是WebLogic9.2,每台机器启动了3个WebLogic实例,构成了一个6个节点的亲和式集群,由于是亲和式集群,所以没有进行Session同步,但是有一些数据需要部分数据在各个节点进行共享,所以后面用JBossCache构建了一个全局缓存(记住这里不是redis集群),服务正常使用一段时间后不定期出现多次的内存溢出情况,内存溢出异常不出现的时候,服务内存回收状况一直正常,每次内存回收后都能恢复到一个稳定的可用空间,怀疑是程序某些不常用的代码路径中存在内存泄漏, 但是程序并未更新升级过,也没有什么特别的操作,让服务带着 -XX:+HeapDumpOnOutOfMemoryError (生成堆的heapdump文件),发现里面存在大量的org.jgroups.protocols.pbcast.NAKACK对象 ,

2、JBossCache初步介绍
JBossCache是基于自家的JGroups进行集群间的数据通信,JGroups 使用协议栈的方式来实现收发数据包的各种所需特性自由组合,数据包接收和发送时要经过每层协议栈的up()down()方法,其中NAKACK栈用于保障各个包的有效顺序及重发

3、JBossCache造成的问题的分析
由于信息失败有重发的可能性,在确认所有注册在CMS(Group Membership Service)的节点都收到了正确的信息之前发送的信息必须保存在内存中,

4、MIS的服务端有一些重要的细节造成的问题
而此MIS的服务端中有一个负责安全校验的全局Filter,每当接收到请求时,均会更新最后一次操作时间,并将这个时间同步到所有的节点,使得一个用户在一段时间内不能在多台机器上登录,在服务使用过程中,往往一个页面会产生数次乃至数十次的请求,因此这个过滤器导致集群各个节点之间的网络交互特别频繁(因为需要同步到各个节点),当网络情况不满足情况时,重发数据就会堆积,最后造成内存溢出

5、最后的结果
看到上面差不多有点头绪了吧,其实出现案例中的问题既有MIS系统本身的缺陷的,也有JBossCache 的缺陷共同导致的,
最重要的缺陷是这一类被集群共享的数据要使用类似JBossCache这种集群缓存来同步的话,可以允许读操作频繁,因为数据在本地有一个副本但是不能写频繁,这样会带来很大的网络开销

redis集群和它的区别要说一样也有点一样,当redissession数据共享时,其实session了就有redis的一部分副本,和sessionID相关联的,但是也不完全一样,如果不提共享的话,redis更像一个缓存的平台,所有的都存在里面,谁要哪个数据给谁哪的数据,谁写就往redis里写,现在spring-data-redis 2.0以上不再用Jedis了,改用lettuce了,用netty做底层

发布了213 篇原创文章 · 获赞 22 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/weixin_43113679/article/details/100747277