记录一次线上的文件描述符泄露问题

本文记录了一次线上服务进程文件句柄持续增长的问题分析过程。通过监控产品中查找相似性的功能,定位到文件系统相关的原因,并最终确定为kafkastream的PersistentStore未正确关闭迭代器导致。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文最开始发表于择维士社区
本文记录了一次线上文件描述符异常问题的分析过程以及方法.

起因

某天,在查看系统资源时,发现我们的核心后台backend服务进程文件句柄一直在缓慢增长如下图:
问题

如上图左下角所示,过去一周文件句柄一直在缓慢规律的增加当中.

调查

因为文件句柄一直在缓慢增长中,那么一般有如下2种情况:

  • 文件流没有关闭
  • Socket没有关闭

本来想直接上BTrace来调查(之前也调查过类似的问题记录一次TCP连接异常问题使用btrace),但是毕竟还要写脚本,有没有更简单的办法呢?

想起来我们的监控产品中有查找相似性的功能,或许能找到些蛛丝马迹:
原始数据:
在这里插入图片描述

AI找到的相似的数据1:
AI1

AI找到的相似的数据2:
在这里插入图片描述

从上面来看就比较明显了,大概率是文件系统相关造成的句柄泄露.

那么登录容器(backend服务在容器内运行), 执行(7是进程ID):

ls -l /proc/7/fd > fd.txt

然后查看fd.txt,发现有很多如下的记录:

lr-x------ 1 root root 64 Aug  8 08:13 615 -> /data/alert-evaluator/0_2/rocksdb/alertState/000636.sst
lr-x------ 1 root root 64 Aug  8 08:13 616 -> /data/alert-evaluator/0_2/rocksdb/recentNStore/000476.sst
lr-x------ 1 root root 64 Aug  8 08:13 617 -> /data/alert-evaluator/0_2/rocksdb/alertState/000624.sst
lr-x------ 1 root root 64 Aug  8 08:13 618 -> /data/alert-evaluator/0_2/rocksdb/alertState/000625.sst
lr-x------ 1 root root 64 Aug  8 08:13 619 -> /data/alert-evaluator/0_2/rocksdb/alertState/000657.sst
lrwx------ 1 root root 64 Aug  8 08:13 62 -> anon_inode:[eventpoll]
lr-x------ 1 root root 64 Aug  8 08:13 620 -> /data/alert-evaluator/0_2/rocksdb/alertState/000629.sst
lrwx------ 1 root root 64 Aug  8 08:13 621 -> socket:[2715092561]
lr-x------ 1 root root 64 Aug  8 08:13 622 -> /data/alert-evaluator/0_2/rocksdb/alertState/000628.sst
lr-x------ 1 root root 64 Aug  8 08:13 623 -> /data/alert-evaluator/0_2/rocksdb/alertState/000630.sst
lr-x------ 1 root root 64 Aug  8 08:13 624 -> /data/alert-evaluator/0_2/rocksdb/alertState/000634.sst
lr-x------ 1 root root 64 Aug  8 08:13 625 -> /data/alert-evaluator/0_2/rocksdb/alertState/000637.sst
lr-x------ 1 root root 64 Aug  8 08:13 626 -> /data/alert-evaluator/0_2/rocksdb/recentNStore/000480.sst
lr-x------ 1 root root 64 Aug  8 08:13 627 -> /data/alert-evaluator/0_2/rocksdb/alertState/000632.sst

该文件是kafka stream的persistent store的数据文件,最终定位下来是使用的KeyValueStore的Iterator是需要关闭的:

 try (KeyValueIterator<String, byte[]> iterator = recentNStore.all()) {
        ....
}

总结

在遇到不同寻常的数据时,往往会关联其他数据也出现异常,而且很有可能有相似的模式,而AI非常适合来找到这些隐藏的关联来辅助我们定位和发现问题从而节约开发定位问题的时间.

广告时间:
择维士提供的数据监控产品支持如下的AI功能:

  • 预测: 预测未来一段时间的数据. 比如磁盘占用.
  • 相关性: 发现与选定数据模式高度匹配的数据. 用来问题关联分析.
  • 异常数据: 自动发现当前系统中的可能异常的数据. 并推送通知.
### 实现Spring Boot应用自动化部署到服务器 #### 准备工作 为了成功地将Spring Boot应用程序自动化部署至服务器,需准备如下组件: - **Jenkins**:作为持续集成工具来触发构建流程并执行部署操作[^1]。 - **Apache Tomcat**:版本8.5.15被提及作为一个可选的应用容器,用来运行打包成WAR形式的Spring Boot程序实例[^2]。 #### 配置Tomcat服务端设置 对于希望以WAR包方式发布的Spring Boot项目,在目标Linux服务器上的`apache-tomcat-8.5.15`安装路径下完成必要的配置调整。具体来说是在`conf/server.xml`文件内添加或修改特定于该项目上下文环境的描述符,例如: ```xml <Context docBase="/home/user/project_workspace/my-springboot-app/project_deploy/my-springboot-app" path="/" reloadable="true"/> ``` 这里指定了Web应用程序根目录(`docBase`)以及访问URL前缀(`path`)等重要参数。 #### Jenkins流水线定义 创建一个新的Pipeline Job,并编写相应的Groovy脚本来指导整个CI/CD过程。下面是一个简单的例子展示如何从GitHub获取最新代码变更、编译测试并通过Maven插件制作最终制品(WAR),最后将其复制给远程主机上待命的服务进程进行热更新: ```groovy pipeline { agent any stages { stage('Checkout') { steps { git 'https://github.com/example/spring-boot-demo.git' } } stage('Build & Test') { steps { sh './mvnw clean package -DskipTests=true' // 假设已存在mvn wrapper } } stage('Deploy') { environment { // 设置一些环境变量供后续命令使用 DEPLOY_PATH = '/opt/tomcat/webapps/' WAR_NAME = 'myapp.war' } steps { sshagent(['your-private-key-id']) { sh """ scp target/${WAR_NAME} user@remote:/tmp/ ssh user@remote << EOF sudo systemctl stop tomcat.service mv /tmp/${WAR_NAME} ${DEPLOY_PATH} sudo chown -R tomcat:tomcat ${DEPLOY_PATH}${WAR_NAME} sudo systemctl start tomcat.service EOF """ } } } } post { always { junit '**/target/surefire-reports/*.xml' archiveArtifacts artifacts: '**/target/*.war', onlyIfSuccessful: true } } } ``` 此段脚本实现了从源码检出直至成品上传的一系列动作;值得注意的是实际生产环境中应当更加注重安全性考量,比如采用更安全的身份验证机制而非明文密码传输,同时也要确保敏感数据妥善保管不泄露。 #### 日志管理 考虑到运维需求,建议利用Log4j2框架定制化的记录策略以便更好地追踪线问题的发生与发展情况。可以在项目的资源文件夹中放置名为`log4j2.xml`的日志配置文档,从而精确控制各类消息输出行为及其存储位置。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值