故障现象 描述:
1、应用方面:Java客户端,上传身份证图片和视频失败,有几次,报错时间大概是从 2018 09-27 22:27:34.815。
客户端错误信息:
2、服务器方面:查看日志,发现上传的 那个storage节点 报错了,报错信息为 :
|
查看data目录,发现有8万多个临时文件,恰好等于报错的日志条数。
全程只有两个文件:
最开始是 21:25:56 是 CgEK9Vus2luAWvGOAATtxisTGPM212.mp4 这个文件,
后面21:32:07 又增加了CgEK9lus29aAUwe5AAciwZj2VXY814.jpg
另外两个storage日志如下:
|
临时解决方案:
一共有3个storage,关闭报错的那个storage,应用上传文件恢复正常。
故障排查分析:
关键点如下
1、为何无法 rename ?
答案:经过检查发现,是因为 /data/10 这个目录不存在。
启动FastDFS服务器时,正常情况下, /data/目录会有 包括00、10、11、12等在内的255 个目录。
其他254个目录都有,为何 /data/10/ 这个目录没有? 刚好文件同步到这个目录,肯定会报错。
2、查看 storage_service.c 源代码(这个文件有8000多行而且没有注释),找到506行:
|
在同步文件时,会执行这个rename的操作,看上去同步失败,发起方会再次发起同步请求,直到同步成功为止。
3、这个文件同步失败的问题,影响到文件的上传了,导致文件上传只要是到这个storage的请求都会失败。
按道理说,同步文件失败,和新上传的文件没有联系的。会不会是因为服务器忙着同步文件,而无法响应其他请求?(根据客户端的报错来看,是getStoreStorage fail,errno code: 28,确实是连不上这个storage了。但是根据报错的频率来看,基本上是1秒钟一次,速度很快,而且服务器整体CPU、内存、磁盘空间都是正常的)
原因分析和初步结论:
此次事故,系 有两个文件 同步失败,失败后无限循环重试,引起某个 storage 无法再收到上传请求。
1、同步失败引起的原因是 因为 /data/10/ 这个目录不存在。为什么这个目录不存在,有两种可能性:
-
最开始有这个目录,但是由于某种故障或者bug,程序将这个目录删除了。
-
有人动过fastdfs服务器,不小心把这个目录删除了。(据悉,之前有用过unison去同步过文件,会不会是同步文件时把这个目录清除了?)
2、fastdfs自身程序不完善,体现在两个方面:
-
同步文件失败时,不应该无限循环且无间隔的去重试。
-
某两个文件同步失败,不应该整个storage都无法继续接受新的上传请求。
初步解决方案和应对策略:
分析:正常情况下,/data/下面的目录,不会无缘无故消失,生产系统已经运行几个月了,之前都很稳定。
但是如果真的再出现这种情况,无论是意外删除,还是程序bug导致,都需要避免。
这个问题的特征很清楚,只要有 同步失败,都很可能会引起此次的问题。监控fastdfs的日志,一旦有文件多次同步失败,就告警。恢复方式比较简单,手工同步一下,再重启一般就OK了。
关于fastdfs的bug,只能尝试联系作者,等等看能否修复,但是这个作者最近几年很不活跃,这个项目几乎没人维护。
找对c语言很熟悉的人,研究一下fastdfs源码,自己改一下,但是难度也比较大,fastdfs的源码还是比较复杂,而且没有代码注释,要看懂还是得花很大功夫。
题外话
其实,我并不推荐使用FastDFS,因为它并不满足我对中间件的选型要求,
我推荐使用:SeaweedFS【https://github.com/chrislusf/seaweedfs】
两者简单对比:比如Contributors(贡献者)数量,FastDFS为4,而SeaweedFS为61,发布版本数量,前者为6,后者为54,最重要的,FastDFS有250多个open的issues没人解决,近5年多,就没人再维护了,想想多可怕……再有,以我多年代码推敲和评审的眼光来看,FastDFS的源码很糟糕,谁愿意去参与维护?