众所周知python在机器学习实践中的应用广泛深入,而在我们业务中的应用集中在提供线上实时风控输出服务,比如国内业务的模型在线服务架构和海外业务的后台决策引擎架构。这两种应用的结合就要求我们考虑如何高效安全便捷地来实现模型的在线部署,为上游提供服务。
在我们的考虑中,无论是代码复杂程度和业务场景,还是语言本身的特点,模型部署都有趋于向微服务架构转型的趋势和需要。一方面,需要进行代码分离来明确责任分工提高开发效率和容错性。另外一个方面,python在CPU密集型的应用中表现是无法令人满意的。为了使用协程来提高异步性从而处理更多的并发请求,最直接地就是将CPU密集转化为IO密集,因为Python天生就适合IO密集型的网络应用。
因此,我们生产中将模型计算抽取为model_lib代码库,并且通过微服务online_model进行交互。这里我们调研过两种模型部署的方式,最终选择了第一种。
一、基于flask框架进行模型部署
Flask是一个轻量级的可定制框架,具有灵活、轻便且高效的特点,并且是标准的wsgi接口框架,易于扩展和维护。
1. 为什么选用nginx+uwsgi+flask这种技术架构
1) Uwsgi搭配nginx性能快,内存占用低,高度可定制,自带详尽日志功能,支持平滑重启。
2) Flask完全兼容了wsgi标准; 微框架,扩展性强; 完全基于unicode,不需处理编码问题;自带服务可独立做单元测试及开发。
3) 我们客户端采用了tornado协程,已经实现了将cpu计算转为io操作,服务端完全是CPU密集的模型计算,不会释放进程,异步框架保持大量文件描述符状态耗费内存,因此不适用异步IO框架。
2. 业务流程框架
3. 部署方式:
部署方式采用nginx+uwsgi+flask的方式,uwsgi可直接接受socket而不是http请求提高性能,再将服务转发给flask框架,这里注意flask此类wsgi标准接口的服务框架比如djangoweb.py在生产中一般不使用自带服务,而是在上层部署uwsgi或者gunicorn作为服务器来进行服务转发,上层再用nginx来做负载均衡,这样可以提高服务稳定性和性能。
4. 代码示例:
uwsgi服务配置:[uwsgi]
# 监听端口
socket=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.py
callable=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 = true
flask服务关键代码:import importlib
import json
import cProfile
import pstats
import StringIO
import time
import traceback
from flask import Flask, request
from common import rong_logger
from common.global_variable import StaticCacheClass
import autopath # 不能去掉
app = Flask(__name__)
# 这里是模型代码库的统一入口,模型代码库中是通过抽象类实现的规范化的模型代码实例,通过此服务提供调用,也通过离线调度进行跑批任务。保证线上线下模型调用一致性
online_model_main = importlib.import_module('online_model_main')
MUST_PARAMS = ['resource_id', 'feature_dict']
SUCCESS_STATUS = 0
ERROR_STATUS = 1
# 路由函数只允许post请求
@app.route("/", methods=['POST'])
def model_main():
uniq_id = '[%s][%s]' % (request.form.get('resource_id', ''), request.url)
status, msg, params = _check_params(request)
if status != SUCCESS_STATUS:
rong_logger.error(uniq_id + 'params error, detail: %s' % msg)
status, msg, result = status, msg, None
else:
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))
except Exception as e:
rong_logger.error(uniq_id + 'error: %s, detail: %s' % (str(e), traceback.format_exc()))
status, msg, result = 5, 'online_model_error:' + str(e), None
return _get_response(status, msg, result)
模型代码库模型实例:
其中 XgboostExecutor类是基于xgb模型抽象类实现的类,通过它来实例化一个模型对象,给flask应用提供调用。具体我们不再深究,有兴趣可以再写一个专题来介绍模型代码库的部署。# -*- coding:utf-8 -*-
# !/usr/bin/python
import logging
import os
from executor.src.load_helper import read_cur_path
from executor.xgboost_model_executor import XgboostExecutor
logging.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%,但注意这是在高并发的情况下,就单条请求来看,微服务并不能显著提高性能。
二、 基于grpc进行在线模型部署
在 gRPC 里客户端应用可以像调用本地对象一样直接调用另一台不同的机器上服务端应用的方法,能够更容易地创建分布式应用和微服务。与许多 RPC 系统类似,gRPC 也是基于以下理念:定义一个服务,指定其能够被远程调用的方法(包含参数和返回类型)。在服务端实现这个接口,并运行一个 gRPC 服务器来处理客户端调用。在客户端拥有一个存根能够执行在服务端实现的一样的方法(这个方法就类似于接口)
1. 为什么选用grpc进行模型部署1)grpc使用ProtoBuf来定义服务、请求返回的数据格式,压缩和传输效率高,语法简单,表达力强。(如下为ProtoBuf的序列化和反序列话性能表现)
2)grpc可支持tensorflow serving的接口调用,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. 开发流程
三、 两种方式线上模型部署对比
1) grpc使用protbuf更加复杂,需要在客户端服务端均保留protbuf文件并做校验,而flask只需要做好统一的接口标准规范即可。
2) grpc使用http2.0更适用移动端的在线模型预测,或者基于tensorflowd的大规模线上模型部署和预测,flask更适用后端面向服务的手动模型部署和预测。
3) grpc节省数据空间,但与python交互需要做json和protbuf数据转换,flask兼容wsgi标准,适用于RESTful类服务,但数据传输占用空间较大。
关于找一找教程网
本站文章仅代表作者观点,不代表本站立场,所有文章非营利性免费分享。
本站提供了软件编程、网站开发技术、服务器运维、人工智能等等IT技术文章,希望广大程序员努力学习,让我们用科技改变世界。
[机器学习模型python在线服务部署的两种实例]http://www.zyiz.net/tech/detail-147354.html
Flask本身并不是一个异步框架,因此在处理高
并发
请求时会出现
性能
瓶颈。然而,Flask可以通过与其他异步框架和库的集成来提高
并发
性能
。所以下面会介绍gevent、gprc
两种
协程库,如何结合使用到Flask项目中,提高项目本身的
并发
性能
。文中我会写份简单的接口代码,通过ab(Apache bench)工具进行请求压测,观察两个模块对Flask项目
性能
提升的情况。gevent是一个基于协程的
Python
网络编程库,它可以使编写异步代码变得更加简单和高效。
1. 核心概念
一个HDF5文件是一种存放两类对象的容器:dataset和group. Dataset是类似于数组的数据集,而group是类似文件夹一样的容器,存放dataset和其他group。在使用h5py的时候需要牢记一句话:groups类比词典,dataset类比Numpy中的数组。 HDF5的dataset虽然与Numpy的数组在接口上很相近,但是支持更多对外透明的存储特征,如数据压缩...
在一个项目中同时使用了
python
和R语言,但如果想要在
python
中训练
模型
并保存为h5文件,那么如何在R中打开它并用它来预测数据呢?答案是R语言keras包(原来R也有keras)下面是过程示例。
背景众所周知
python
在
机器学习
实践中的应用广泛深入,而在我们业务中的应用集中在提供线上实时风控输出
服务
,比如国内业务的
模型
在线
服务
架构和海外业务的后台决策引擎架构。这
两种
应用的结合就要求我们考虑如何高效安全便捷地来实现
模型
的
在线
部署
,为上游提供
服务
。在我们的考虑中,无论是代码复杂程度和业务场景,还是语言本身的特点,
模型
部署
都有趋于向微
服务
架构转型的趋势和需要。一方面,需要进行代码分离来明确责任...
gRPC
是一个高
性能
、通用的开源RPC框架,其由 Google 主要面向移动应用开发并基于HTTP/2协议标准而设计,基于 ProtoBuf(Protocol Buffers) 序列化协议开发,且支持众多开发语言。自
gRPC
推出以来,已经广泛应用于各种
服务
之中。在测试中,我们也越来越多地遇到
gRPC
接口相关的测试内容。测试一个
gRPC
接口,我们往往需要一个测试用的客户...
gRPC
是什么?
gRPC
是什么可以用官网的一句话来概括A high-performance, open-source universal RPC framework所谓RPC(remote procedure call 远程过程调用)框架实际是提供了一套机制,使得应用程序之间可以进行通信,而且也遵从server/client
模型
。使用的时候客户端调用server端提供的接口就像是调用本地的函数一样...
pip install keras==2.2.4
然后在代码中按照https://blog.csdn.net/leleprogrammer/article/details/119699449https://blog.csdn.net/leleprogrammer/article/details/119699
👽👽👽在本文中,我将带你使用
Python
的Flask框架与Pickle模块构建了Web应用程序,在UFO目击数据集上构建了逻辑回归多分类
模型
,并将其集成在Web程序中。🏆🏆🏆