服务器,通过多worker进程来处理请求。启动命令可以这样写:gunicorn -w 4 -b 0.0.0.0:nment.yml文件记录所有依赖包。部署时直接conda env create -f environment.yml就能复现完全相同的运行环境。

对于需要高性能的场景,可以考虑使用PyInstaller把整个项目打包成独立可执行文件。先写个main.py作为入口文件,然后执行pyinstaller -F main.py,就会生成不依赖Python环境的单个可执行文件。不过要注意,打包时可能会遗漏一些动态链接库,需要手动在spec文件里添加。我在Windows下部署时就遇到过缺少MKL库的问题,后来在spec文件的binaries列表里加上相关dll才解决。

模型版本管理很容易被忽略。线上服务跑着v1版模型, meanwhile 本地已经训练出v2版了。直接覆盖部署风险太大,我现在的做法是在API路径里带上版本号,比如/api/v1/predict和/api/v2/predict同时存在,通过Nginx做灰度分流。模型文件命名也遵循规范,包含日期和版本标识,像model_20231025_v2.pkl这样,出了问题能快速回滚。

跨语言调用时,ONNX格式能省不少事。先用skl2onnx把scikit-learn模型转成onnx格式,其他语言只要加载onnx模型文件就能直接推理。最近做的Java Web项目就是这样,Python训练好的模型转换成onnx后,Java端用onnxruntime推理,速度比原来通过HTTP API调用快了三倍多。

监控环节千万不能省。刚开始部署时只关注接口能不能调通,后来发现内存泄漏导致服务运行几天就崩溃。现在会在代码里添加prometheus客户端,记录请求次数、响应时间和异常数量,再配上Grafana看板,模型服务的运行状态一目了然。

性能优化方面,我发现大部分时间都花在特征预处理上。后来把预处理步骤整合进pipeline,和模型一起序列化,调用时直接pipe.predict()就行,避免每次请求都要重复处理特征。对于数值型特征,提前做好标准化能提升推理速度;类别型特征则建议在训练阶段就处理好缺失值。

说到底,模型部署不只是技术活,更是工程能力的体现。从实验代码到生产服务,需要考虑环境隔离、版本控制、性能监控、故障恢复等各个方面。把这些套路都摸清后,现在部署个新模型基本上半天就能搞定,再也不用熬夜改bug了。各位要是有更好的部署方案,欢迎在评论区交流。

更多推荐