系统吃swap问题排查

目录

背景

问题

分析并解决

1.控制线程数

2.更换IO组件

3.Linux进程信息文件分析

总结加餐

参考文档

背景

隔壁业务组系统是简单的主从结构,写索引的服务(主)叫primary, 读索引并提供搜索功能的服务(从)叫replica。业务线同步数据并不是平滑的,在同步数据时primary瞬间负载上升,磁盘写IO增加,这是合理的。

primary 写完索引,会马上触发索引的同步操作,因此,瞬间的磁盘读IO增加以及网络流量的增加都是合理的。

问题

在节假日高峰期前期,团队增加了50%的replica服务器,这造成了primary的同步压力进一步增加,观测系统监控,发现了“吃swap”的现象,这就不合理了,需要分析优化。

这里简单解释下“吃swap”:

在计算机系统中,"吃swap"指的是系统开始使用交换空间(swap space)来补充物理内存(RAM)的不足。交换空间是一块预留在磁盘上的区域,用于存储那些当前不常用的内存数据。当物理内存不足时,操作系统会将一些数据从内存中移到交换空间,以腾出内存给其他需要的进程。

具体来说,“吃swap”通常表示以下几种情况:

  1. 内存不足:系统的物理内存已经被用完,导致操作系统不得不使用交换空间来存储数据。
  2. 性能下降:因为磁盘的读写速度远低于内存的读写速度,当系统频繁访问交换空间时,性能会显著下降。用户可能会注意到系统变得响应缓慢。
  3. 高负载场景:在高负载场景下,如大量的索引写入和同步操作,内存需求突然增加,导致系统不得不使用swap。

以上描述的情况下,primary服务器在索引写入和同步操作的高负载下,内存不足,导致操作系统开始频繁使用swap,从而出现“吃swap”的现象。这是不合理的,因为频繁使用swap会显著降低系统性能,影响整体服务的响应速度和稳定性。因此,需要通过优化措施来减少对swap的依赖,提高系统的性能。

分析并解决

1.控制线程数

参考以前的经验,replica 有个索引备份功能,在晚上4点会备份本地索引文件(30G)到指定目录
这个操作就会造成瞬间IO的增加以及负载的升高,因此最初我们判断这是索引复制太快,导致的内存耗尽和负载增加。我们尝试通过控制primary服务线程池的大小,来放慢索引复制的速度。

经过压测发现,线程很小(5个)的情况,载峰值有所降低,但是吃swap的问题仍然存在。

结论:primary采用的gRPC框架,通过控制线程池大小来放慢索引复制的速度在gRPC框架中并不奏效,因为gRPC的异步调用机制允许高并发执行,独立于线程数量。有效的优化策略需要针对异步调用特性和具体负载情况进行调整,而不仅仅是控制线程数。

2.更换IO组件

Lucene提供了两种磁盘访问方式MMapDirectory和NIODirectory,因为mmap方式会大量使用堆外内存,因此我们怀疑是堆外内存失控导致的系统内存不足,经过更换Directory,发现吃swap问题仍然存在。

Apache Lucene 是一个高性能、可伸缩的信息检索库,用于全文搜索和索引。Lucene 提供了多种方式来访问磁盘存储的索引数据,主要包括 MMapDirectoryNIODirectory

结论:mmap虽然会使用堆外内存,但是linux应该是可以控制好堆外内存的回收的。

3.Linux进程信息文件分析

我们分析了linux下的 /proc/$pid/status文件,VmSwap是swap占用情况,VmHWM是历史内存占用。以及java进程当前的内存占用情况 sudo -u tomcat jhsdb jmap --heap --pid $pid

发现java进程的历史内存占用很高,而当前内存占用并不高(所以排除了内存泄漏),各个进程都有占用swap的现象,说明是java进程在某个时刻(文件传输)耗尽了内存,导致其他进程吃swap,而那个时刻过后,java进程是可以回收内存的。所以推测是索引文件传输过程中,某些buffer设置不合理导致的。

经过代码排查 ,发现gRPG(高度异步)在读取索引文件时需要多次判断serverCallStreamObserver.isReady(),如果只判断一次isReady,就把所以数据写入响应流,就会占用大量系统缓冲区。官方推荐的是一种callback机制,示例代码如下:

final InputStream input = ...

serverCallStreamObserver.setOnReadyHandler(new Runnable() {

    int upto = 0// 传输偏移,需要反复使用

    final long size = file.length();

    public void run() { // 这里会根据缓冲区状态多次被触发执行,因此这个Runnable是有状态的

        while (upto < size && serverCallStreamObserver.isReady()) {

             response.onNext(...); //写入缓冲区

             upto += chunk;

        }

    }

});

serverCallStreamObserver.setOnCancelHandler(() -> input.close());

serverCallStreamObserver.setOnCloseHandler(() -> input.close());

  • 缓冲区管理不当:原始代码在判断 serverCallStreamObserver.isReady() 一次后,立即写入所有数据,导致系统缓冲区被大量占用,内存迅速耗尽。
  • 回调机制:通过设置 serverCallStreamObserver.setOnReadyHandler 回调函数,确保只有在缓冲区准备好时才写入数据。这样可以避免一次性写入过多数据,导致内存占用过高。
  • 状态管理:使用 upto 变量跟踪传输偏移量,每次 isReady 时仅写入一部分数据,缓解系统缓冲区的压力。
  • 资源释放:通过 setOnCancelHandlersetOnCloseHandler 确保在取消或关闭时正确关闭输入流,避免资源泄漏。

这种写法会比较反直觉,通过回调函数关闭InputStream看上去没有finally去关闭安全,好处是缓冲区压力小,最终问题解决。

总结加餐

以上描述的问题的根本原因在于 gRPC 在文件传输过程中缓冲区管理不当,导致内存占用过高。通过引入官方推荐的回调机制和合理的状态管理,成功解决了该问题。因此在日常开发中,涉及到文件写入与读取时,还是需要多关注一下流的关闭与打开与缓冲区buffer的使用是否合理。

Linux将物理内存分为内存段,叫做页面。交换是指内存页面被复制到预先设定好的硬盘空间(叫做交换空间)的过程,目的是释放这份内存页面。物理内存和交换空间的总大小是可用的虚拟内存的总量。我们知道swap space是磁盘上的一块区域,可以是一个分区,也可以是一个文件,或者以它们的组合方式出现。简单点说,当系统物理内存吃紧时,Linux系统会将内存中不常访问的数据保存到 swap 上,这样系统就有更多的物理内存为其他进程服务,而当系统需要访问swap上存储的内容时,系统会再将 swap 上的数据加载到内存中,这就是我们常说的swap outswap in了。那么配置多大的 Swap 比较合适?

  • 当物理内存小于1G且不需要休眠时,设置和内存同样大小的swap空间即可;当需要休眠时,建议配置两倍物理内存的大小,但最大值不要超过两倍内存大小。
  • 当物理内存大于1G且不需要休眠时,建议大小为sqrt(RAM),其中RAM为物理内存大小;当需要休眠时,建议大小是RAM+round(sqrt(RAM)),但最大值不要超过两倍内存大小。
  • 如果两倍物理内存大小的swap空间还不够用,建议增加内存而不是增加swap

此外,在一篇参考文献中看到如下这段话:

 如果频繁的访问 swap 的话,怎么优化 swap 都没用,跟内存比还是低几个数量级,性能还是下降的厉害,如果不频繁访问 swap 的话,优化 swap 又有啥意义呢?所以其实优化 swap 性能的实际意义不大。

参考文档

https://zhuanlan.zhihu.com/p/467976849

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/786196.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【转载】目标检测mAP的含义

转载自三叔家的猫 https://blog.csdn.net/qq_39056987 https://blog.csdn.net/qq_39056987/article/details/104348493 <div id"content_views" class"markdown_views prism-atom-one-light"><svg xmlns"http://www.w3.org/2000/svg" s…

rocketmq实现限流

目录 问题背景 技术方向 方案确认 消息队列&#xff08;√&#xff09; 分布式锁&#xff08;&#xff09; 方案实现 监控方向 业务方向 问题背景 公司邮件服务token有 分钟内超200封的熔断机制&#xff0c;当前token被熔断后&#xff0c;系统发邮件操作会被忽略&…

使用F1C200S从零制作掌机之构建debian文件系统

前情&#xff1a;使用buildrootfs构建的文件系统调试了很久NES模拟器&#xff0c;执行InfoNES模拟器的时候一直黑屏&#xff0c;无内容显示&#xff0c;调不通了&#xff0c;所以改用debian系统试试。 一、环境配置 首先下载两个工具&#xff1a;qemu-arm-static和debootstra…

如何在 Microsoft Edge 上使用开发人员工具

Microsoft Edge 提供了一套强大的开发人员工具&#xff0c;可帮助 Web 开发人员检查、调试和优化他们的网站或 Web 应用程序。 无论您是经验丰富的 Web 开发人员还是刚刚起步&#xff0c;了解如何有效地使用这些工具都可以对开发过程产生重大影响。 在本文中&#xff0c;我们…

vb.netcad二开自学笔记8:界面之任务窗格

使用net可以创建一个类似属性面板的自定义的任务窗格&#xff0c;从而实现应用程序更丰富的人机交互。 1、添加一个自定义控件 2、在前面创建的代码框架内增加一个命令函数ShowMyPalette Imports System.Windows.Media.Imaging Imports Autodesk.AutoCAD.ApplicationServices …

电机控制杂谈——位置环到底该用什么调节器?

1.为什么位置环用P调节器尽可以实现无静差调节&#xff1f; 当时在学《运动控制》这门课程时&#xff0c;用的是陈伯时老师的教材。在介绍调节器的时候&#xff0c;教材中说到&#xff0c;P&#xff08;比例&#xff09;调节器会存在稳态误差&#xff0c;所以在转速环和电流环…

html——VSCode的使用

快捷键 快速生成标签&#xff1a;标签名tab 保存文件&#xff1a;CtrlS 设置自动保存【文件】→【自动保存】 快速查看网页效果&#xff1a;右击→Open in Default Browser 快捷键&#xff1a;altb 注意&#xff1a;必须安装了open in brows…

显示渲染-OSG框架解析

1.背景介绍 1.1 OSG介绍 OSG的全称&#xff1a;OpenSceneGraph&#xff0c;它是一个开放源码&#xff0c;跨平台的图形开发包&#xff0c;它为诸如飞行器仿真&#xff0c;游戏&#xff0c;虚拟现实&#xff0c;科学计算可视化这样的高性能图形应用程序开发而设计。 它基于场…

生成图质量评价

1. RichHF-18K 论文地址 解决问题&#xff1a; 如何对生成图质量进行算法评价&#xff0c;以优化图片质量&#xff0c;提升模型生成能力 解决思路&#xff1a; 参考多模态模型&#xff0c;构建评价模型&#xff0c;从7个维度分三个分支对生成图进行测评&#xff1a; Tips&…

简单仿写MVC

代码地址&#xff08;需要自取&#xff09;&#xff1a;mvc_Imitation: 简单仿写实现MVC (gitee.com) 项目目录 先把架子搭好 Controller注解 Documented Retention(RetentionPolicy.RUNTIME) Target(ElementType.TYPE) public interface Controller { }RequestMapping Do…

java设计模式(十一)组合模式(Composite Pattern)

1、模式介绍&#xff1a; 组合模式是一种结构型设计模式&#xff0c;它允许你将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。 2、应用场景&#xff1a; 表示树形结构&#xff1a;当你需要表示对象的部分-整体…

2024年06月CCF-GESP编程能力等级认证Python编程四级真题解析

本文收录于专栏《Python等级认证CCF-GESP真题解析》&#xff0c;专栏总目录&#xff1a;点这里&#xff0c;订阅后可阅读专栏内所有文章。 一、单选题&#xff08;每题 2 分&#xff0c;共 30 分&#xff09; 第 1 题 小杨父母带他到某培训机构给他报名参加CCF组织的GESP认证…

前端视角下的Spring-Boot语法学习:打印 hello-world

今日话题 基于 Spring Boot 打印输出 hello world 作者&#xff1a;云层上的光 时间&#xff1a;2024年6月20日 14时25分14秒 主线任务 一、打印 hello world 1、点击 “新建项目”用来演示 打印输出 “hello world” 2、填写项目配置&#xff1a;&#xff08;详细版见&a…

Python基础知识——(002)

文章目录 P8——7. input函数的使用 基本的输入函数input P9——8. Python中的注释 P10——9. Python中的缩进与本章总结 本章总结 P11——10. 章节习题 P8——7. input函数的使用 基本的输入函数input 语法结构&#xff1a; x input(提示文字) 注意事项&#xff1a;无论输…

【matlab】【python】爬虫实战

目录 引言 具体步骤 1.设置请求选项 2.发送请求并获取响应 3.设置正则表达式 4.执行正则表达式匹配 matlab完整代码 python代码示例 引言 在当今这个信息爆炸的时代&#xff0c;数据已成为推动社会进步和企业发展的核心动力之一。随着互联网的普及和技术的飞速发展&am…

前端视角下的Spring-Boot语法学习:demo-crud 实现增删改查

今日话题 基于 Spring Boot 实现增删改查&#xff0c;仅仅只是提供接口不涉及数据库增删改查 作者&#xff1a;云层上的光 时间&#xff1a;2024年6月21日 15时19分14秒 主线任务 一、项目创建 1、基于 idea 创建项目 2、选择项目依赖 Spring Web 二、实现增删改查 1、新…

Pix4Dmapper:无人机测绘的革命性工具

在现代测绘和地理信息系统&#xff08;GIS&#xff09;领域&#xff0c;Pix4Dmapper无疑是一款革命性的工具。作为一名长期使用这款软件的用户&#xff0c;我深深感受到它在工作中的重要性和便利性。Pix4Dmapper不仅仅是一款软件&#xff0c;更是测绘工作者的得力助手&#xff…

Selenium 的基本操作你知道哪些?

1. 前言 今天的推文&#xff0c;我们就来说说看&#xff0c;怎么实现模拟真人去打开微信读书网站。 2.需求分析和准备 整体的需求大致可以分为以下步骤&#xff1a; 打开chrome浏览器 打开百度网页 搜索“微信读书” 点击进入“微信读书”官网 搜索关键词“长安的荔枝” 点…

2023.2版IDEA复制配置修改端口增加一个当前运行服务的操作流程

文章目录 前言操作流程截图 前言 在微服务技术学习中很多学习场景会使用到运行多个服务节点进行调试&#xff0c;想要去模拟集群部署&#xff0c;就需要去复制配置&#xff0c;本文讲解一下如何复制&#xff0c;以及修改端口号。 操作流程截图

现代化木工装备建设新颖校园木工创客室

校园木工创客室是一个集木工制作、创意设计、科技融合与教育实践于一体的多功能空间。它为学生提供了一个动手实践、创新创造的平台&#xff0c;旨在培养学生的动手能力、创新思维、解决问题的能力以及团队协作能力。 木工创客室的设备选择应综合考虑需求、预算、品牌、质量、安…