fastdfs应用于线上环境已经有一段时间,但在使用过程中出现一个问题,通过程序在上传图片时,有时图片无法正常回显,通过后台日志查看,发现图片确实已经传到服务器;把图片地址复制出来通过浏览器访问也能正常访问到。猜测是网络延迟的问题,但不确定这个延迟发生在哪个过程中。
重新过了一遍线上的结构及fastdfs的原理,终于确定了问题所在。也修改了线上的方案。结合下面两图详细说明下。
图1中是线上原来的结构,一个tracker,两个storage;其中一个storage结合nginx提供图片访问服务,一个storage作为在线热备使用,两个Storage都注册到了tracker下。
故障发生2这个过程中,客户端联系tracker,tracker返回s2(备份storage)的地址,于是图片被上传到了s2上,然后WEB程序返回给客户端一个S1的地址作为回显地址;但因为网络等其他问题,导致S2在把刚上传的图片同步到S1时产生延迟,刚上传的图片在S1上还不存在;此时客户端去访问这个地址,就会返回404的错误,于是回显失败。当上传的图片完成,再去手动访问这个图片地址的时候,这时图片又可以正常显示了。
图2是在考虑到上述问题后做的一个改进,但这里依赖nginx的一个功能proxy_next_upstream http_404。因为在图2的结构下延迟依然会导致图片的回显失败。比如,图片上传到了S2,但前端负载nginx却将访问转发到了S1这个nginx上,在延迟发生的情况下依然会发生404错误。proxy_next_upstream在这时的功能就是避免这种情况的,proxy_next_upstream会在被代理服务器返回404时将请求转发到下一个被代理服务器也是S2上,而不会把404这个错误直接返回客户端。从而避免了回显失败的问题。
当然如果图片的访问功能通过tracker本身的功能来提供的话是可以直接避免这个问题的,因为tracker中是有相应配置控制这部分功能。
还有一个解决办法就是,在客户端回显的时候增加一个等待时间,上传图片成功后,等待2S再显示传回的图片地址基本上可以避免这个问题。但这需要修改代码,目前最简单的就是把图1中的备份storage去掉,但较好的方案还是图2中的,线上的生产数据是必须要备份的。
在使用过程中也发生了一点,就是fastdfs还是比较依赖nginx这类的WEB服务器的,当然这也可能是轻量化带来的必然的情况。