背景
由于上次k8s事故导致mongodb数据损坏,所以本次重构时将mongodb以二进制方式部署到物理服务器上。使用systemctl管理进程。mongodb副本集搭建完成过后,使用mongorestore导入数据时,mongodb进程不定时非正常退出,mongorestore要么卡着不动,要么直接退出。
版本介绍
mongodb: 5.0.27
OS :ubuntu20.04
部署简述
1、解压mongodb的tar包,并编写启动配置文件,配置文件参考如下:
systemLog:
destination: file
logAppend: true
path: /Raid_disk/mongodb/mongodb_log/mongod.log
storage:
dbPath: /Raid_disk/mongodb/mongodb-data
journal:
enabled: true
processManagement:
fork: true
pidFilePath: /Raid_disk/mongodb/mongod.pid
net:
port: 27017
bindIp: 0.0.0.0
replication:
replSetName: rs0
#security:
#clusterAuthMode: keyFile
#keyFile: /Raid_disk/mongodb/key/mongo.key
#authorization: enabled
2、按照启动配置文件创建目录等
3、编写service文件,参考如下:
[Unit]
Description=Mongodb Service
After=network.target remote-fs.target nss-lookup.target
[Service]
Type=forking
ExecStart=/Raid_disk/mongodb/mongodb-5.0.14/bin/mongod -f /Raid_disk/mongodb/mongodb.conf
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/Raid_disk/mongodb/mongodb-5.0.14/bin/mongod -f /Raid_disk/mongodb/mongodb.conf --shutdown
PrivateTmp=true
[Install]
WantedBy=multi-user.target
4、使用systemctl启动mongodb服务并初始化集群
systemctl daemon-reload
systemctl start mongod
登录节点初始化副本集。
导入数据,出现故障
操作:
使用mongorestore导入数据
mongorestore --host rs0/x.x.x.x27017,x.x.x.x:27017,x.x.x.x:27017 -u root -p '.....' -d db_name file_path --drop
现象
还原的过程中突然卡着,或者还原的命令直接退出。
排查
1、查看mongodb集群状态
发现更本就无法登录,或者登录进去有一个节点状态不正常。
使用systemctl status mongod查看每个服务器上的Mongod启动状态。发现有一个或者两个或者全部都非正常退出。
2、查看mongodb日志
发现有大量的Too many open file....
打印出来,如下:
{"t":{"$date":"2023-01-14T14:45:01.435+08:00"},"s":"F", "c":"CONTROL", "id":6384300, "ctx":"AuthorizationManager-1","msg":"Writing fatal message","attr":{"message":"DBException::toString(): TooManyFilesOpen: error in creating eventfd: Too many open files\nActual exception type: mongo::error_details::ExceptionForImpl<(mongo::ErrorCodes::Error)264, mongo::AssertionException>\n\n"}}
{"t":{"$date":"2023-01-14T14:45:01.435+08:00"},"s":"I", "c":"NETWORK", "id":51800, "ctx":"conn468","msg":"client metadata","attr":{"remote":"10.10.1.5:45732","client":"conn468","doc":{"driver":{"name":"mongo-java-driver","version":"4.1.2"},"os":{"type":"Linux","name":"Linux","architecture":"amd64","version":"5.4.0-121-generic"},"platform":"Java/IcedTea/1.8.0_212-b04"}}}
{"t":{"$date":"2023-01-14T14:45:01.435+08:00"},"s":"W", "c":"NETWORK", "id":23023, "ctx":"listener","msg":"Error accepting new connection","attr":{"error":{"code":264,"codeName":"TooManyFilesOpen","errmsg":"error in creating eventfd: Too many open files"}}}
从日志可以看出很明显是内核参数中文件打开限制。此处还是开心的(^_ ^)
使用ulimit -n查看服务器上限制是1024。这不是把饭味道最里边了吗?
ulimit -n 204800
ulimit -n检查一下,嗯嗯,确实是我配置的,这么多总该够了吧。
启动mongodb进程,登录检查集群状态,恩恩,不错,没有问题。
那就干正事吧,开始还原数据……
经过漫长的等待,终于,他喵的,集群又坍了,日志还是报这个错,mongodb进程依然是非正常退出。
3、修改内核文件
从第二步中结果看出,使用ulimit -n 204800配置没有生效,那肯定是配置地方没对,所以没生效。
于是,我就在修改配置的漫漫苦难旅途中上下求索,爆炸重组,崩溃大哭。所有人都是说的修改了文件限制需要重启服务器,对于我,这尼玛是线上的环境,我又不是胆子长毛了,我敢随便重启服务器?
然后经过多次查看发现虽然配置了limits.conf但是,这个是对于普通启动进程生效,但是对于systemctl管理的进程却是不生效的。那么针对systemctl管理的进程,应该咋弄?请看下面:
1、查看进程现在启动的进程限制:
cat /proc/${PID}/limits
cat /proc/1754103/limits
Limit Soft Limit Hard Limit Units
Max cpu time unlimited unlimited seconds
Max file size unlimited unlimited bytes
Max data size unlimited unlimited bytes
Max stack size 8388608 unlimited bytes
Max core file size 0 unlimited bytes
Max resident set unlimited unlimited bytes
Max processes 2058055 2058055 processes
Max open files 204800 204800 files
Max locked memory 65536 65536 bytes
Max address space unlimited unlimited bytes
Max file locks unlimited unlimited locks
Max pending signals 2058055 2058055 signals
Max msgqueue size 819200 819200 bytes
Max nice priority 0 0
Max realtime priority 0 0
Max realtime timeout unlimited unlimited us
默认是max open files 1024,在这里我们可以直接修改进程的限制,prlimit --pid 1754103 --nofile=204800:204800
这是临时的,进程关闭就失效。
对于单个service永久生效,可以在service文件中添加,如本次的Mongod.service,修改后:
[Unit]
Description=Mongodb Service
After=network.target remote-fs.target nss-lookup.target
[Service]
Type=forking
ExecStart=/Raid_disk/mongodb/mongodb-5.0.14/bin/mongod -f /Raid_disk/mongodb/mongodb.conf
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/Raid_disk/mongodb/mongodb-5.0.14/bin/mongod -f /Raid_disk/mongodb/mongodb.conf --shutdown
PrivateTmp=true
#配置文件限制
LimitCORE=infinity
LimitNOFILE=204800
LimitNPROC=204800
[Install]
WantedBy=multi-user.target
也可以对所有systemctl 管理的进程管理配置:
vim /etc/systemd/system.conf
[Manager]
DefaultLimitCORE=infinity
DefaultLimitNOFILE=204800
DefaultLimitNPROC=65535
vim /etc/systemd/user.conf
[Manager]
DefaultLimitCORE=infinity
DefaultLimitNOFILE=204800
DefaultLimitNPROC=65535
#生产环境一般处于禁用状态
DefaultLimitCORE=infinity
#核心转储文件大小不限制,它是进程运行时突然崩溃的那一刻的内存快照。操作系统在程序发生异常而异常在进程内部又没有被捕获的情况下,会把进程此刻内存、寄存器状态、运行堆栈等信息转储保存在一个文件里,可使用 gdb 工具来分析。core dump 生产环境一般处于禁用状态,对于内存消耗性的进程,core dump 时会占用很多系统资源,磁盘空间也可能被写满。
DefaultLimitNOFILE=1048576
#服务进程可以打开文件的最大数目为1048576
DefaultLimitNPROC=65535
#进程可以打开的最大线程数目为65535
运维的小伙伴们,好运!