java.io.IOException: Too many open files
前言:
项目最近报 java.io.IOException: Too many open files 问题,大概意思是:意味着你的应用程序尝试打开的文件描述符数量超过了系统允许的最大数量,在linux中每个进程打开的文件描述是有一定限制的。导致项目运行不起来,找了好几天,记录一下。
一、问题排查
1,查看所有进程信息
c
-- 查看所有进程消息
jps -l
-- 找到java进程的PID
ps aux | grep 应用名称
2,下面用 lsof 命令使用讲解,排查的逻辑
lsof: list open files 【列出来打开的命令】
c
-- 计算<进程>打开的文件数
lsof -p <进程号> | wc -l
进程 82253 打开的文件数是 2289
系统默认是 1024
命令如下
c
-- 查看系统默认进程打开的文件个数
ulimit -n
二、 解决方案:
1,可以临时增加进行打开文件的个数
-- 将进程打开个数临时修改为 65535
ulimit -n 65535
2,查看占用端口的文件是哪个
lsof -p xxxxx
最后发现有个关于 kafka打开的文件过多
3,将所有关于kafka关闭 进程维持在200左右问题解决
问题分析:
1,之前对接kafka 做消费者时候,是有个while(true) 循环,不断拉取数据
2,现在是有个定时器,每5分钟拉取一波数据代码如下,问题出现在 每5分钟拉取一波数据,但是consumer 始终没有关闭。要关闭consumer ,进程打开数据量是有限的。【之前对接kafka都是不断轮训拉取数据使用while(true) 循环,也管自己没有考虑到,索引进行打开的文件数始终在增加】
定时器:
c
@Scheduled(cron = "0 0/5 * * * ?")
public void physicalAlarmConsumerTask(){
kafkaReportClient.physicalAlarmTopicConsumer();
}
消费者:
c
public void physicalAlarmTopicConsumer(){
Date currentDate = new Date();
// 1.配置Kafka
Properties properties = new Properties();
properties.put("bootstrap.servers","xxx");
properties.put("group.id","xxx");
properties.put("enable.auto.commit","false");
properties.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
properties.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
KafkaConsumer<String, String> consumer = new KafkaConsumer<>(properties);
consumer.subscribe(Collections.singleton("xxxaacctopic"));
// 2.消费消息
ConsumerRecords<String, String> records = consumer.poll(Duration.ofMillis(5000));
// 3.数据解析
for (ConsumerRecord<String, String> record : records) {
JSONObject jsonObject = JSON.parseObject(record.value());
// TODO:业务逻辑
...
}
// 4.提交offset
consumer.commitAsync(new OffsetCommitCallback() {
@Override
public void onComplete(Map<TopicPartition, OffsetAndMetadata> offsets, Exception e) {
if (e != null){
log.error("xxx commit offset is error,offsets:{},e:{}", offsets, e);
} else {
log.info("xxxx offset commit success");
}
}
});
}
小节
1,如果在有类似 Too many open files ,看下是哪个端口下的服务
2,lsof -P -i :xxx 【指定端口占用情况】
3,lsof -p xxx 【占用端口文件是哪个,具体分析】
4,lsof -p xxxx | wc -l
注:xxx为进程号。
喜欢我的文章记得点个在看,或者点赞,持续更新中ing...