背景众所周知,python广泛应用于机器学习实践,我们业务中的应用主要集中在提供在线实时风控输出服务,例如在线国内业务模型服务架构和海外业务后台决策引擎架构。这两个应用的结合,需要我们考虑如何高效、安全、便捷地实现模型的在线部署,并为上游提供服务。在我们的考虑中,无论是代码复杂度、业务场景,还是语言本身的特性,模型部署都有向微服务架构转型的趋势和需要。一方面需要代码分离,明确职责分工,提高开发效率和容错能力。另一方面,python在CPU密集型应用中的表现并不尽如人意。为了使用协程提高异步性,处理更多的并发请求,最直接的方式就是将CPU密集型转为IO密集型,因为Python天生就适合IO密集型网络应用。所以我们在生产中,将模型计算提取为model_lib代码库,通过微服务online_model进行交互。这里我们考察了两种模型部署方式,最终选择了第一种。1、基于flask框架的模型部署Flask是一个轻量级、可定制的框架,灵活、可移植、高效,是一个标准的wsgi接口框架,易于扩展和维护。一、为什么选择nginx+uwsgi+flask的技术架构1)uwsgiwithnginx性能快,内存占用低,高度可定制,自带详细日志功能,支持平滑重启。2)Flask完全兼容wsgi标准;微框架,可扩展性强;完全基于unicode,无需处理编码问题;独立的服务可以独立进行单元测试和开发。3)我们的客户端使用了tornado协程,已经实现了cpu计算到io操作的转换。服务器完全是CPU密集型模型计算,不会释放进程。异步框架维护大量的文件描述符,消耗内存,所以不适用于异步IO框架。2.业务流程框架3.部署方式:部署方式采用nginx+uwsgi+flask的方式。Uwsgi可以直接接受socket而不是http请求来提高性能,然后将服务转发给flask框架。这里要注意wsgi的标准接口如flask和djangoweb.py等服务框架在生产中一般不会使用自己的服务。而是在上层部署uwsgi或者gunicorn作为服务转发的服务器。上层使用nginx做负载均衡,可以提高服务的稳定性和性能。(这里的inrouter层是我们自己封装的路由层,用于集群中的路由转发,nginx只在本地进行端口转发。)4.代码示例:uwsgi服务配置:[uwsgi]#Listenportsocket=127.0。0.1:8200#进程数processes=20;async=4;threads=2;enable-threads=true#运行目录chdir=/home/rong/www/online_model#wsgi文件wsgi-file=model_main.pycallable=app#是否有主进程master=true#后台运行及其打印日志daemonize=/home/rong/www/log/uwsgi.log#主进程pid文件pidfile=/home/rong/www/log/online_model/pid/uwsgi.pid#日志切割大小log-maxsize=5000000#不记录请求信息的日志。只有错误和uWSGI内部消息被记录到日志中。disable-logging=false#超时时间http-timeout=3#传输数据大小限制buffer-size=1048576#每个进程分别加载lazy-apps=trueflask服务关键代码:importimportlibimportjsonimportcProfileimportpstatsimportStringIOimporttimeimporttracebackfromflaskimportFlask,requestfromcommonimportrong_loggerfromcommon.global_variableimportStaticCacheClassimportautopath#不能去掉app=Flask(__name__)#这里是模型代码库的统一入口,是通过抽象类实现的标准化模型代码实例,通过这个服务提供调用,并通过离线调度运行批处理任务。保证线上线下模型调用一致性online_model_main=importlib.import_module('online_model_main')MUST_PARAMS=['resource_id','feature_dict']SUCCESS_STATUS=0ERROR_STATUS=1#methods=['POST'])defmodel_main():uniq_id='[%s][%s]'%(request.form.get('resource_id',''),request.url)尝试:status,msg,params=_check_params(request)如果状态!=SUCCESS_STATUS:rong_logger.error(uniq_id+'paramserror,detail:%s'%msg)status,msg,result=status,msg,Noneelse:resource_id,feature_dict=params['resource_id'],json.loads(params['feature_dict'])status,msg,result=online_model_main.main(resource_id,feature_dict,request,rong_logger)rong_logger.info(uniq_id+'[%s][%s][%s]'%(status,msg,result))exceptExceptionase:rong_logger.error(uniq_id+'error:%s,detail:%s'%(str(e),traceback.format_exc()))状态,多发性硬化症g,result=5,'online_model_error:'+str(e),Nonereturn_get_response(status,msg,result)模型代码库模型实例:其中XgboostExecutor类是基于xgb模型抽象类实现的类,通过它实例化一个模型对象,它提供对烧瓶应用程序的调用。我们不会深入研究细节。有兴趣的可以另写专题介绍模型代码库的部署。#-*-编码:utf-8-*-#!/usr/bin/pythonimportloggingimportosfromexecutor.src.load_helperimportread_cur_pathfromexecutor.xgboost_model_executorimportXgboostExecutorlogging.basicConfig(level=logging.INFO,format='%(asctime)s:%(message)s')[model_path,features_path,feature_importance_path]=map(read_cur_path,["xgb_model","feature_list","feature_importance"])model=XgboostExecutor(model_path,features_path,feature_check_white_list=["n21_score"],white_or_weight=False,feature_check_weight_limit=1,feature_importance_path=feature_importance_path,manager="qutianhang@xx.com",developer="qutianhang@xx.com",correlation="negative")5.微服务改造后20并发性能对比请求模型:微服务改造前20并发请求模型:本地测试并发性能提升20%,但注意这是在高并发的情况下,就单次请求而言,微服务不不能显着提升性能2.基于grpc的在线模型部署在gRPC中,客户端应用可以像本地对象一样直接调用另一台不同机器上服务端应用的方法,更容易创建分布式应用和微服务。与许多RPC系统一样,gRPC的思想是定义一个服务并指定其可以远程调用的方法(包括参数和返回类型)。在服务器端实现这个接口,并运行一个gRPC服务器来处理客户端调用。client端有个stub可以执行server端实现的相同方法(这个方法类似于接口)1.为什么选择grpc进行模型部署1)grpc使用ProtoBuf定义服务,返回的数据格式通过请求、压缩和传输效率高,语法简单,表达能力强。(以下是ProtoBuf的序列化和反序列化性能)2)grpc可以支持tensorflowserving接口调用。tensorflow完成模型训练和部署后,可以提供服务接口供grpc调用。实施方便高效,自带版本管理,模型热更新等,非常适合大型线上业务。是我们下一步模型部署的技术方向。3)gRPC支持多种语言,可以根据语言自动生成客户端和服务端函数库。2、部署方式(业务流程同前)部署方式采用nginx+grpc,要求nginx支持http2.0。在客户端将json特征字典转换为protobuf。(https://github.com/NextTuesday/py-pb-converters/blob/master/pbjson.py这里有一个json和protobuf相互转换的脚本。)3.服务发现和负载均衡4.客户端开发过程:服务器端:3.两种方式在线模型部署对比1)grpc使用protbuf比较复杂,protbuf文件需要在client端和server端都保存和验证,而flask只需要做一个统一接口标准规范。2)使用http2.0的grpc更适合移动端在线模型预测,或者基于tensorflowd的大规模在线模型部署和预测,flask更适合后端面向服务的人工模型部署和预测。3)grpc节省了数据空间,但是需要将json和protbuf数据进行转换才能与python进行交互。Flask兼容wsgi标准,适用于RESTful服务,但数据传输占用空间大。
