同事牛逼啊,写了个隐藏 bug,我排查了 3 天才解决问题!
最近线上监控 SFTP
连接频繁爆表,通过重启某个系统,连接数迅速下降,系统就能恢复正常,初步判断是应用程序连接未关闭的问题导致的。
栈长通过 IDE 全局搜索排查,SFTP 连接使用了 jsch
包,确实有一些功能点使用了 SFTP
连接而未关闭的情况,或者不在 finally
语句块中正常关闭。
整改上线后,SFTP 还是爆表……
事后运维心态都要崩了,运维主动写了个 SFTP
连接监控,当连接超过 5 分钟空闲时就主动断开。
但这只是临时的处理,真正的原因肯定还是应用程序没有正常关闭导致的,于是再认真排查下程序,终于找出了元凶。。
下面是示例代码:
Session session = null;
ChannelSftp channel = null;
try{
for(...){
...
// 创建会话
JSch jsch = new JSch();
jsch.getSession(host, username);
session = jsch.getSession(username, host, port);
session.setPassword(password);
session.connect();
// 创建sftp连接
channel = session.openChannel("sftp");
channel.connect();
...
}
} catch(...){
...
} finally{
if (null != channel && channel.isConnected()) {
channel.disconnect();
}
if (null != session && session.isConnected()) {
session.disconnect();
}
}
大家都看出问题了吗?
这程序我检查了 2 遍,排查了 3 天才解决了这个问题。
写出这代码,同事真是个人才啊!!!
乍一看,连接确实是关闭了啊,也确实是在 finally
语句块关闭,为什么还会有问题?
原因就是在该死的 for
循环中创建连接的,虽然在 finally
中进行了关闭,但是连接变量在循环中进行重建和替换,所以关闭的永远只是最后一个连接。
而且,这还是个下载 Excel
明细的功能,数据很多的时候,一个操作就能导致连接瞬间爆表。
解决方案肯定是要把创建连接的部分拿到 for
循环前面去,连接创建一次就好了,可以反复使用。
另外,知道 JDK 7+ 中的 try-with-resources 语法的朋友可能会问,可以省略 finally
语句块吧,可以直接在 try(...)
中定义,它会自动关闭。
Really?建议还是仔细阅读下 try-with-resources 这篇文章吧,没看过的可以关注公众号Java技术栈进行搜索阅读。
这个 jsch
连接包还真不行,我们来看它的源码吧,不然又是一个坑你没商量的坑。
com.jcraft.jsch.Session:
com.jcraft.jsch.Channel:
这两个类只实现了 Runnable
接口,没有实现 java.lang.AutoCloseable
接口,所以,它并不符合 try-with-resources
自动关闭的原则。
至此,线上 SFTP
连接爆表的问题终于解决了,可以安心睡个好觉了,同时,我也感觉我们的同事太牛逼了,又让我涨知识了。
- 关于Android PullTorefreshScrollview回到顶部实例
- 《笨办法学Python》 第2课手记
- 《笨办法学Python》 第1课手记
- 《笨办法学Python》 第40课手记
- 很经典的GDB调试命令,包括查看变量,查看内存
- 《笨办法学Python》 第39课手记
- 《笨办法学Python》 第38课手记
- 01背包及其变种(物品无限背包、恰好装满背包)
- 《笨办法学Python》 第35课手记
- github pages + Hexo + 域名绑定搭建个人博客增强版
- 责任链模式
- 《笨办法学Python》 第33课手记
- 《笨办法学Python》 第32课手记
- 《笨办法学Python》 第31课手记
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 深度学习Pytorch检测实战 - Notes - 第5章 单阶多层检测器:SSD
- Java+selnium 智能等待,try catch方法智能定位需添加等待的元素
- Python中的命名空间和作用域(2)
- C/C++可以用正则表达式吗?
- typescript实战总结之实现一个互联网黑白墙
- 文件上传漏洞演示(一句话木马文件 + 蚁剑)
- [Bazel]构建Golang项目
- 2020--IDEA破解失败后无法打开(mac/win)【已解决】
- CPU:别再拿我当搬砖工!
- 7类 登录/注册 安全漏洞
- 安全弹出你的移动设备,保护数据安全!
- burpsuite系列
- idea_Maven_setting文件依赖源国内镜像
- Wapiti安装及使用
- 利用burpsuite+sqlmap POST自动化注入详解