我司的项目使用到了influxdb时序数据库。项目使用influxdb-java对influxdb进行操作,然后有一天数据读写出现异常了
org.influxdb.InfluxDBIOException: java.net.SocketTimeoutException: timeout
at org.influxdb.impl.InfluxDBImpl.execute(InfluxDBImpl.java:514) ~[market_data_fetcherd.jar:na]
at org.influxdb.impl.InfluxDBImpl.write(InfluxDBImpl.java:312) ~[market_data_fetcherd.jar:na]
at ewhine.tools.InfluxDBUtil.execWrite(InfluxDBUtil.java:77) ~[market_data_fetcherd.jar:na]
at ewhine.dataprocessor.DataUploader.realtimeUpload(DataUploader.java:171) [market_data_fetcherd.jar:na]
at ewhine.actor.RealtimeDataUploaderActor.onReceive(RealtimeDataUploaderActor.java:68) [market_data_fetcherd.jar:na]
at akka.actor.UntypedActor$$anonfun$receive$1.applyOrElse(UntypedActor.scala:165) [market_data_fetcherd.jar:na]
at akka.actor.Actor$class.aroundReceive(Actor.scala:502) [market_data_fetcherd.jar:na]
at akka.actor.UntypedActor.aroundReceive(UntypedActor.scala:95) [market_data_fetcherd.jar:na]
at akka.actor.ActorCell.receiveMessage(ActorCell.scala:526) [market_data_fetcherd.jar:na]
我司的服务器使用的是阿里云,此时ssh上去进行操作,发现系统卡住了。我司的网站也部署再此阿里云服务器上,此时访问网站是可以访问的。当时登录阿里云控制台重启了系统,事后查看日志也没有发现什么。
最近对kotlin深感兴趣,决定将项目中的部分代码转为kotlin试试,由于ant配置kotlin不太方便,于是换了gradle来进行项目管理,正是踩到了gradle的一个坑,才重现了之前influxdb挂掉的现象。
gradle编译项目会启动一个gradle-deamon后台常驻进程。我在阿里云上频繁的进行gralde编译操作,最后竟然导致系统卡了.......然后复现了influxdb读写异常的错误。
-
此时查看influxdb状态 service influxdb status
-
最终发现是因为系统内存太小,而启动的gradle-deamo占用的内存不小
系统内存。发现系统只有1G内存,并且没有交换空间!
qwweb@webserver:~$ free -mh
total used free shared buff/cache available
Mem: 992M 342M 106M 2.8M 543M 498M
后来多次启动gradle并实时查看内存情况,发现编译代码的时候内存不断减少,最终减少到0!此时也没有交换空间可用,所以导致了OOM,系统选择将influxdb杀死以释放内存!
- 关于系统OOM时选择目标进程进行kill的方法 oom-killer机制介绍
- 查看influxdb的oom_score,可见其值相当大
qwweb@webserver:~$ ps aux | grep influxdb
influxdb 21950 0.4 16.5 576864 167940 ? Ssl 16:28 1:07 /usr/bin/influxd -config /etc/influxdb/influxdb.conf
qwweb 24186 0.0 0.0 14196 948 pts/1 S+ 20:41 0:00 grep influxdb
qwweb@webserver:~$ cat /proc/21950/oom_
oom_adj oom_score oom_score_adj
qwweb@webserver:~$ cat /proc/21950/oom_score
55
- 查看oom_socre的排序脚本
#!/bin/bash
for proc in $(find /proc -maxdepth 1 -regex '/proc/[0-9]+'); do
printf "%2d %5d %s\n" \
"$(cat $proc/oom_score)" \
"$(basename $proc)" \
"$(cat $proc/cmdline | tr '\0' ' ' | head -c 50)"
done 2>/dev/null | sort -nr | head -n 10
qwweb@webserver:~$ sh oom_score.sh
55 23918 /usr/lib/jvm/java-8-oracle/bin/java -server -Xms64
42 736 /usr/sbin/mysqld
38 21950 /usr/bin/influxd -config /etc/influxdb/influxdb.co
36 21897 /lib/systemd/systemd-journald
2 24158 sshd: qwweb [priv]
2 24052 sshd: qwweb [priv]
2 731 /usr/bin/redis-server 127.0.0.1:6379
1 24179 -bash
1 24178 sshd: qwweb@pts/1
1 24135 bash
- 要解决或者降低OOM发生的概率,有两种方法,一是增加系统内存,二是设置交换空间
- 设置交换空间
# 生成交换文件2G
dd if=/dev/zero of=/mnt/swap bs=100M count=20
# 格式化为交换文件系统
mkswap /mnt/swap
#
chmod 600 /mnt/swap
# 挂载
swapon /mnt/swap
# 使系统重启时也生效,vim /etc/fstab
/mnt/swap swap swap defaults 0 0
- free -mh
qwweb@webserver:~$ free -mh
total used free shared buff/cache available
Mem: 992M 368M 69M 2.8M 553M 470M
Swap: 2.0G 102M 1.9G
- gradle-deamon长期占用内存也需要解决,即编辑项目下gradle.properties
$ cat gradle.properties
# 不要以后台deamon方式执行
org.gradle.daemon=false
# 并行编译
org.gradle.parallel=true
- 控制交换空间使用频率
echo 40 > /proc/sys/vm/swappiness
- 经过这次实践,发现交换空间真的很好用,可以极大的降低极端情况下系统杀死某些重要进程以释放内存的概率。