当前位置: 首页 > article >正文

怎么避免服务内存溢出?

在高并发、高吞吐的场景下,很多简单的事情,会变得非常复杂,而很多程序并没有在设计时针对高并发高吞吐量的情况做好内存管理。

自动内存管理机制的实现原理

做内存管理,主要考虑申请内存和内存回收两部分。

申请内存的步骤:

  1. 计算要创建的对象需要占用多少内存
  2. 在内存中找一块连续并且是空闲的内存空间,标记为已占用

内存回收需要主要做2件事情。

  1. 找出所有可以回收的对象,将其标记为空闲
  2. 整理内存碎片

现代GC算法大部分采用“标记-清除”算法或者他的变种算法,这种算法分为标记和清除两个阶段:

  • 标记阶段:从GC Root开始,可以简单把GC Root理解为程序入口的那个对象,标记所有可达的对象,因为程序中所有在用的对象一定会被这个GC Root直接引用或者间接引用。
  • 清除阶段:遍历所有对象,找出所有没有标记的对象,这些没有标记的对象都是可以被回收的,清除这些对象,释放相应的内存。

“标记-清除”算法的一个最大问题,是在标记和清除过程中,必须先把进程暂停,否则计算的结果就是不准确的。这也是为什么发生垃圾回收的时候,我们的程序会卡死的原因。

需要注意,垃圾回收完成后,我们还需要进行内存碎片整理,将不连续的空闲内存移到到一起,以便空出足够的连续内存空间供后需用。

虽然自动内存管理机制有效地解决了内存泄露问题,带来的代价是执行垃圾回收时会暂停进程,如果暂停的时间过长,程序看起来就像“卡死了”一样。

服务为什么会在高并发时忽然“卡死”?

在高并发、高吞吐量场景下,我们的程序会非常忙,短时间内会创建大量的对象,这些对象会迅速占满内存,由于没有内存可用,垃圾回收被迫开始启动,并且,这次被迫执行的垃圾回收面临的是占满整个内存的海量对象,它执行的时间也会增加,相应的,这个回收过程会导致进程长时间暂停。

进程长时间暂停,又会导致大量的请求积压等待结果,垃圾回收刚刚结束,更多的请求立刻涌来,迅速占满内存,再次被迫执行垃圾回收,进入一个恶性循环,如果垃圾回收的速度跟不上创建对象的速度,还可能会产生内存溢出的现象。

高并发下的内存管理技巧

对于开发者来说,垃圾回收是不可控的,而且是无法避免的,但是,我们可以通过一些方法来降低垃圾回收的频率,减少进程暂停的时长。

我们需要考虑在处理大量请求的同时,尽量少的产生一次性对象,特别是占用内存比较大的对象。我们可以按照这个思路来优化对象的业务代码。

对于需要频繁使用、占用内存较大的一次性对象,我们可以考虑自行回收并重用这些对象,例如我们可以为这些对象创建一个对象池,收到请求后,在对象池里面申请一个对象,使用完后再放回到对象池中,这样就可以反复地重复使用这些对象,非常有效地避免频繁触发垃圾回收。


http://www.kler.cn/a/776.html

相关文章:

  • C程序设计:数据在数组中的交换
  • 【Ubuntu 20.4安装截图软件 flameshot 】
  • 机器视觉检测相机基础知识 | 颜色 | 光源 | 镜头 | 分辨率 / 精度 / 公差
  • MySql详细教程-从入门到进阶(超实用)
  • oracle linux8.10+ oracle 23ai安装
  • DDoS防护中的流量清洗与智能调度
  • 贯穿设计模式第一话--单一职责原则
  • 【云原生|Docker】01-docker简介
  • 数据结构--二叉树
  • toString()、equals()是什么,为啥需要重写,多种方法来重写
  • Java开发 - 布隆过滤器初体验
  • 朋友去华为面试,轻松拿到26K的Offer,羡慕了......
  • OpenCV入门(十四)快速学会OpenCV 13 边缘检测
  • SparkSQL-数据的加载和保存
  • Android开发 View属性
  • 【Spring】spring框架简介
  • Vite4 + Vue3 + vue-router4 动态路由
  • 【Linux】进程概念二
  • 实现 GPS 拒绝飞机导航的时间序列模型(Matlab代码实现)
  • 【Java注释】如何自定义注解以及JDK中的元注解
  • 你真的知道如何系统高效地学习数据结构与算法吗?
  • 五种IO模型
  • k8s快速入门
  • 响应式编程详解,带你熟悉Reactor响应式编程
  • 操作系统之进程的初步认识(1)
  • Vulnhub靶场----10、LazySysadmin