Redis订阅模式在生产环境引起的内存泄漏
内存泄漏
内存泄漏指的就是在运行过程中定义的各种各样的变量无法被垃圾回收器正常标记为不可达并触发后续的回收流程,主要原因还是因为对可回收对象引用没有去除,导致垃圾回收器通过GC ROOT可达性分析时认为当前是可达的;这时随着系统的运行时间,累积的不可回收的对象就越多,直到垃圾回收器执行Full GC还是没有空余空间存放新加入的对象,这时虚拟机就会抛出out of memory错误。此种错误可以分类为内存泄漏导致的,原因是应该回收的对象无法被垃圾回收器正常回收从而导致内存不足。说起内存泄漏近十年引起比较大的是便是Android 5.0引起的内存问题,该Bug导致手机在使用一段时间后必须手动重启系统释放内存;不然,无法运行任何应用,包括系统自带APPS桌面等都会引起FC崩溃;这时查看内存占用发现可用内存为负数。安卓5.0导致的内存泄漏:http://www.lupaworld.com/portal.php?mod=view&aid=249186&continueFlag=6f56029cba978a1a4ac09c91b20c196d
接下来说一个我在实际开发中文件遇到的内存泄漏问题,该问题在测试环境不易发现,主要原因有以下几点:
1、测试环境经常更新重启,相当于GC回收了对象
2、用户量太少了,根本撑不到内存泄露出现的那一刻
但是,生产环境那就不一样了,用户多,运行时间久,如果存在长期没有被回收的对象时,久而久之就会触发内存不足的情况
言归正传,生产环境出现的内存泄露问题是由对Redis订阅使用不当导致,下面我把引起内存泄漏的代码贴上来
1 /**
2 * 因为@ServerEndpoint不支持注入,所以使用SpringUtils获取IOC实例
3 */
4 private StringRedisTemplate redisTampate = SpringUtils.getBean(StringRedisTemplate.class);
5 private RedisMessageListenerContainer redisMessageListenerContainer = SpringUtils.getBean(RedisMessageListenerContainer.class);
6 private Session session;
7
8 @OnOpen
9 public void onOpen(Session session, @PathParam("topic") String topic, @PathParam("username") String username) {
11 this.session = session;
12 sessions.add(this);
13 SubscribeListener subscribeListener = new SubscribeListener();
14 subscribeListener.setSession(session);
15 subscribeListener.setStringRedisTemplate(redisTampate);
17 try {
18 redisMessageListenerContainer.addMessageListener(subscribeListener, new ChannelTopic(topic));
19 } catch (Exception e) {
20 e.printStackTrace();
21 }
22 }
这是一个WebSocket的项目,利用即时通信的特性实现了,由后台触发前端页面的刷新
眼尖的人应该已经发现问题所在了吧?这就是一个使用Spring和Redis不当导致的内存泄露问题
接下来我们分析
首先代码的4到7行申明了三个成员变量,主要关注点还是第5行的RedisMessageListenerContainer 变量,从SpringContext中取出了Redis的消息监听容器;在接下来的onOpen方法里定义了获取了WebSocket连接成功后产生而Session会话,这里的Session会话不是WebSession而是WebSocketSession,可以定义正会话帧,每次用户连接成功之后服务器就分发一个WebSocket给当前用户,当断开连接时该会话帧就会断开对象引用,垃圾回收器就可以回收;说到这里其实问题已经非常明显了,那就这个WebSession压根就没有被垃圾回收器回收掉,每次用户连接就产生一个WebSession对象,并通过地14行代买引用给Redis的监听器,然后再由将监听器添加到Redis消息监听容器中,而Redis消息监听容器又是从SpringContext中取出的,那就意味着该对象是一个SpringIOC中的Bean实例,这一个有GC ROOT引用的对象;这样一来后续产生的每一个WebSession会话帧都会被Redis消息监听容器的实例引用,垃圾回收器在进行可达性分析时都认为该对象是可达的,判定无法回收,从而就导致了内存泄漏。
这个问题其实是对垃圾回收器和Spring原理不了解导致的,在日常开发中应该尽可能的避免这些问题
Redis订阅模式在生产环境引起的内存泄漏的更多相关文章
- 生产环境Java应用服务内存泄漏分析与解决
有个生产环境CRM业务应用服务,情况有些奇怪,监控数据显示内存异常.内存使用率99.%多.通过生产监控看板发现,CRM内存超配或内存泄漏的现象,下面分析一下这个问题过程记录. 服务器配置情况: 生产服 ...
- 【原】Storm Local模式和生产环境中Topology运行配置
Storm入门教程 1. Storm基础 Storm Storm主要特点 Storm基本概念 Storm调度器 Storm配置 Guaranteeing Message Processing(消息处理 ...
- Centos6.3 下使用 Tomcat-6.0.43 非root用户 jsvc模式部署 生产环境 端口80 vsftp
一.安装JDK环境 方法一. 官方下载链接 http://www.oracle.com/technetwork/java/javase/downloads/jdk7-downloads-1880260 ...
- redis 编译安装(生产环境推荐)
一.安装redis 1.下载redis包 wget http://download.redis.io/releases/redis-3.2.1.tar.gz 2.解压redis包到/opt下 tar ...
- Linux Debugging (九) 一次生产环境下的“内存泄露”
一个偶然的机会,发现一个进程使用了超过14G的内存.这个进程是一个RPC server,只是作为中转,绝对不应该使用这么多内存的.即使并发量太多,存在内存中的数据太多,那么在并发减少的情况下,这个内存 ...
- prometheus+grafana 监控生产环境机器的系统信息、redis、mongodb以及jmx
介绍: 为了更好的对生产环境的一些中间件和操作系统的运行情况进行可视化的展示,近期了解了下prometheus加上grafana来实现这种效果,由于prometheus是新出来的开源项目,所以,监控的 ...
- Centos6.3 下使用 Tomcat-6.0.43 非root用户 部署 生产环境 端口转发方式
一.安装JDK环境 方法一. 官方下载链接 http://www.oracle.com/technetwork/java/javase/downloads/jdk7-downloads-1880260 ...
- 生产环境上,哨兵模式集群Redis版本升级应用实战
背景: 由于生产环境上所使用的Redis版本并不一致,好久也没有更新,为了避免版本不同对Redis集群造成影响,从而升级为统一Redis版本! 1.集群架构 一主两从三哨兵: 2.升级方案 (1)升级 ...
- ASP.NET MVC 学习笔记-2.Razor语法 ASP.NET MVC 学习笔记-1.ASP.NET MVC 基础 反射的具体应用 策略模式的具体应用 责任链模式的具体应用 ServiceStack.Redis订阅发布服务的调用 C#读取XML文件的基类实现
ASP.NET MVC 学习笔记-2.Razor语法 1. 表达式 表达式必须跟在“@”符号之后, 2. 代码块 代码块必须位于“@{}”中,并且每行代码必须以“: ...
- redis实现消息队列&发布/订阅模式使用
在项目中用到了redis作为缓存,再学习了ActiveMq之后想着用redis实现简单的消息队列,下面做记录. Redis的列表类型键可以用来实现队列,并且支持阻塞式读取,可以很容易的实现一个高性 ...
随机推荐
- 悟空活动中台 - 基于 WebP 的图片高性能加载方案
本文首发于 vivo互联网技术 微信公众号 链接: https://mp.weixin.qq.com/s/rSpWorfNTajtqq_pd7H-nw作者:悟空中台研发团队 一.背景 移动端网页的加载 ...
- SPI 在 Dubbo中 的应用
通过本文的学习,可以了解 Dubbo SPI 的特性及实现原理,希望对大家的开发设计有一定的启发性. 一.概述 SPI 全称为 Service Provider Interface,是一种模块间组件相 ...
- 倾斜摄影技术构建图扑 WebGIS 智慧展馆
前言 智慧展馆通过"云大物移智链"等技术将"物"(展品.设备.环境等)进行互联,并感知"人"(工作人员.观众等)的行为.结合 GIS.BIM ...
- 核心技能之UI库选择
移动端推荐: vant.cube-ui 有赞vant: https://youzan.github.io/vant/#/zh-CN/ 滴滴cube-ui: https://didi.github.io ...
- 电脑面试两道问题(python+shell)
最近面试电脑代码面试遇到两个问题,供大家参考一下一.python脚本: 手写一个函数,实现两个数相加,并使用unittest与pytest工具测试函数正确性. 1.unnitest进行测试: impo ...
- java基础(3)--pulic class与class的区别
1.一个类前面的public是可有可无的2.如果一个类使用 public 修饰,则文件名必须与类名一致3.如果一个类前面没有使用public修饰,则文件名可以与类名不一致.当编译成功后会生成对应类名的 ...
- idea导入maven项目结构不全
本文为博主原创,转载请注明出处 将本地的项目导入idea中,其操作第一步为: File->open->选中导入maven项目的pom文件,正常情况通过该步骤项目就会导入到idea中. 通过 ...
- 强大的PDF格式转换器--迅捷PDF转换器
1.功能十分强大,具体如图所示,实现了多种文件格式的转换,PDF合并和PDF密码解除也帮了我很大的忙(注意这里的密码解除是强行解除,不需要你知道密码) 2.资源分享 https://www.aliyu ...
- B2033 A*B 问题
A*B 问题 题目描述 输入两个正整数 \(A\) 和 \(B\),求 \(A \times B\) 的值.注意乘积的范围和数据类型的选择. 输入格式 一行,包含两个正整数 \(A\) 和 \(B\) ...
- WebApi允许跨域
services.AddCors(options => { options.AddPolicy("abc", builder => { //App:CorsOrigin ...