分析Flask+Gunicorn部署深度学习模型出现的一些问题
最近遇到一个比较坑的问题,经过几天的代码调试后才发现错误的原因,在此记录一下。
部署简单的深度学习模型一般推荐使用谷歌的tf_serving,但是针对某些复杂的项目而言,则需要将各个模块拆分成单独的服务进行部署,在使用上变得很不方便。Nginx+gunicorn+flask框架可以支持高并发,在已上线的歌单识别的项目中性能很稳定,图片审核服务(各场景的AI模型有10个以上)则采用了该套部署框架。
根据图片审核服务线上实时的监控数据分析,客户端请求服务的失败率很低(1%左右),性能应该是很稳定的。前期接到一个业务需求,通过我们提供的机审服务审核一批图片,但线上的服务失败率突然变得很高。排查问题的过程很曲折,在此汇总一下。
首先分析是不是gunicorn出现了问题。查看debug日志,报如下的错误。
2.gunicorn中工作模式worker_class之前都是使用异步的方式gevent(线上配置,gunicorn对于基于libev的并发库gevent的支持非常好),改为同步的sync的方式,问题依然存在。以下是gunicorn的参数配置:
在watch -n 1 nvidia-smi的命令下,可以看到gunicorn服务器的worker会不断地挂掉又自动重启,问题又回到了参数timeout上,上述的配置证明该参数并不能解决问题。
接着分析会不会是拉取云存储的图片造成的?由于审核的图片是直接从云存储拉取的图片,如果拉取时报错502同样会是gunicorn的worker挂掉并重启的情况。测试了10万条云存储的链接,出现502错误的情况非常少(不到0.01%)。但通过观察显卡的显存变化,基本上可以判定原因不在此。
后来想到了一种方式,绕过flask+gunicorn这套直接对外提供服务的框架(排除flask和gunicorn的框架问题),采用轮询的方式来处理这些图片。采用多进程在多张显卡上初始化多个模型(即推理代码改为多进程模式),并建立2个队列(取数队列与结果队列)进行轮询。意想不到的情况发生了,程序报错segmention fault,这个错误应该就是worker不断中断启动的根本原因,最大可能就是内存不足。
查看了这批数据的尺寸基本都是4k以上的超高清图片,基本上就明白了。限制了图片的输入的小,显存稳定,失败率降低,问题完美解决。
至此,分析完毕。