内存泄漏

  内存泄漏指的就是在运行过程中定义的各种各样的变量无法被垃圾回收器正常标记为不可达并触发后续的回收流程,主要原因还是因为对可回收对象引用没有去除,导致垃圾回收器通过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订阅模式在生产环境引起的内存泄漏的更多相关文章

  1. 生产环境Java应用服务内存泄漏分析与解决

    有个生产环境CRM业务应用服务,情况有些奇怪,监控数据显示内存异常.内存使用率99.%多.通过生产监控看板发现,CRM内存超配或内存泄漏的现象,下面分析一下这个问题过程记录. 服务器配置情况: 生产服 ...

  2. 【原】Storm Local模式和生产环境中Topology运行配置

    Storm入门教程 1. Storm基础 Storm Storm主要特点 Storm基本概念 Storm调度器 Storm配置 Guaranteeing Message Processing(消息处理 ...

  3. Centos6.3 下使用 Tomcat-6.0.43 非root用户 jsvc模式部署 生产环境 端口80 vsftp

    一.安装JDK环境 方法一. 官方下载链接 http://www.oracle.com/technetwork/java/javase/downloads/jdk7-downloads-1880260 ...

  4. redis 编译安装(生产环境推荐)

    一.安装redis 1.下载redis包 wget http://download.redis.io/releases/redis-3.2.1.tar.gz 2.解压redis包到/opt下 tar ...

  5. Linux Debugging (九) 一次生产环境下的“内存泄露”

    一个偶然的机会,发现一个进程使用了超过14G的内存.这个进程是一个RPC server,只是作为中转,绝对不应该使用这么多内存的.即使并发量太多,存在内存中的数据太多,那么在并发减少的情况下,这个内存 ...

  6. prometheus+grafana 监控生产环境机器的系统信息、redis、mongodb以及jmx

    介绍: 为了更好的对生产环境的一些中间件和操作系统的运行情况进行可视化的展示,近期了解了下prometheus加上grafana来实现这种效果,由于prometheus是新出来的开源项目,所以,监控的 ...

  7. Centos6.3 下使用 Tomcat-6.0.43 非root用户 部署 生产环境 端口转发方式

    一.安装JDK环境 方法一. 官方下载链接 http://www.oracle.com/technetwork/java/javase/downloads/jdk7-downloads-1880260 ...

  8. 生产环境上,哨兵模式集群Redis版本升级应用实战

    背景: 由于生产环境上所使用的Redis版本并不一致,好久也没有更新,为了避免版本不同对Redis集群造成影响,从而升级为统一Redis版本! 1.集群架构 一主两从三哨兵: 2.升级方案 (1)升级 ...

  9. ASP.NET MVC 学习笔记-2.Razor语法 ASP.NET MVC 学习笔记-1.ASP.NET MVC 基础 反射的具体应用 策略模式的具体应用 责任链模式的具体应用 ServiceStack.Redis订阅发布服务的调用 C#读取XML文件的基类实现

    ASP.NET MVC 学习笔记-2.Razor语法   1.         表达式 表达式必须跟在“@”符号之后, 2.         代码块 代码块必须位于“@{}”中,并且每行代码必须以“: ...

  10. redis实现消息队列&发布/订阅模式使用

    在项目中用到了redis作为缓存,再学习了ActiveMq之后想着用redis实现简单的消息队列,下面做记录.   Redis的列表类型键可以用来实现队列,并且支持阻塞式读取,可以很容易的实现一个高性 ...

随机推荐

  1. WPF ElementHost 内存泄露问题

    无意中发现,WPF ElementHost 控件如果未正确释放,会存在内存泄露问题.解决方法如下: xaml代码: <Grid x:Name="grid"> <W ...

  2. 为什么加了@Transactional注解,事务没有回滚?

    在昨天的<事务管理入门>一文发布之后,有读者联系说根据文章尝试,加了@Transactional注解之后,事务并没有回滚.经过一顿沟通排查之后,找到了原因,在此记录一下,给后面如果碰到类似 ...

  3. 第六届蓝桥杯C++A组 A~F题题解

    蓝桥杯历年国赛真题汇总:Here 1.方格填数 在2行5列的格子中填入1到10的数字. 要求: 相邻的格子中的数,右边的大于左边的,下边的大于上边的. 如[图1.png]所示的2种,就是合格的填法. ...

  4. HTML+CSS小实战案例 (照片墙特效、代码展示)

    预览图: HMTL代码部分 <!DOCTYPE html> <html lang="en"> <head> <meta charset=& ...

  5. OKR之剑·实战篇04:OKR执行过程优化的那些关键事

    作者:vivo 互联网平台产品研发团队 本文是<OKR 之剑>系列之实战第 4 篇--OKR执行过程不是一成不变的,团队和个人在执行中不断优化执行的具体行动,保障OKR的高效执行. 前言 ...

  6. springboot+vue实现 下载服务端返回的文件功能

    开发中会遇到,通过浏览器下载服务器端返回的文件功能,本文使用springboot+vue实现该功能. 后端代码: 注:后端返回的文件名遇到中文就会乱码,一直也没得到很好的解决方案,最后就统一返回1.x ...

  7. vue 状态管理 四、Action用法

    系列导航 vue 状态管理 一.状态管理概念和基本结构 vue 状态管理 二.状态管理的基本使用 vue 状态管理 三.Mutations和Getters用法 vue 状态管理 四.Action用法 ...

  8. http-长连接

    1. 短链接 http1.0 -- 1个请求-响应过程会创建且1个新的连接 2. 长连接 http1.1 -- 同域下可以创建1个tcp连接,多个请求在同一个tcp上串行处理请求 http2.0 -- ...

  9. SpringBoot开启动态定时任务并手动、自动关闭

    场景需求:在执行某个方法的两小时之后进行某个操作 涉及:定时任务.哈希表 需要注意:业务逻辑层是单一实例的,所以在定时任务类内操作业务逻辑层的某个属性和在业务逻辑层内操作的都是同一个. 疑问:Thre ...

  10. [转帖]OceanBase实验4:迁移MySQL数据到OceanBase集群

    服务器环境 1)12核48G,操作系统为centos 7.9系统,单节点三副本1-1-1集群. 2)源MySQL数据库:与OceanBase同一台服务器,版本为MySQL 5.7. 1.使用 mysq ...