功能定位

在互联网时代,将算法、模型的处理能力,封装成一系列计算机易识别的数据接口开放出去,供第三方开发者使用,这种行为就叫做Open
API,提供开放API的平台本身就被称为开放平台。

需求梳理

如:从0到1搭建媒体处理体系的架构图所示,开放平台包括以下功能:

功能 优先级 功能说明 备注
协议转换 T0 将千变万化的用户协议,转成内部的标准文件处理协议
参数校验 T2 确保入参满足要求
鉴权 T0 确保接入请求都合法,没有所谓的:水平越权 or 垂直越权
计费 T1 统计:调用次数、输入视频时长、使用cpu、gpu的时长等
同步转异步 T0 详见:同步转异步

协议转换

业务需求千变万化,很难通过定义一套标准,让所有人都按照固定的方式接入。因此,需要有一个系统去承接:将千变万化的用户个性化报文,转成内部的标准文件处理报文。

网关形态

站在用户视角来看:所见即所得,是比较好的用户体验方式。用技术术语来说,就是用户同步等待结果的显示。但是,对于大图片计算,长视频计算,往往也是非常费时的操作,极容易超时,因此,这就产生了2种产品形态:
形态1:同步等待结果模式。这个就不用展示了,太常见了。
形态2:任务列表模式。相关产品形态如下图所示:

备注:
1、任务列表模式中,前端处有一个后台线程,定时轮训后端的一个接口,获取处理结果。
2、虽然:云处理的网关,按照调用方式,分为:同步网关和异步网关。但这并不是说一定要搞2个代码库,大部分情况下,只有一个代码库,多个接口,不同的部署模式。

鉴权

本文不谈:为啥需要对接口进行鉴权?(毕竟,网上一搜有一坨的答案)。本文探讨下:媒体处理下的鉴权应该解决以下几个问题?

如何确保接口参数不被修改?

常用的解决方案是:将所有入参,按照一定的规律,计算一个HMAC摘要值。公式如下:
算法a(api_secret,参数1,参数2,参数3…) = sign_value,

客户端将sign_value放入到请求参数列表中去。

服务端使用同样的算法,再计算一遍,得出sign_value2,然后,对比客户端上传上来的sign_value1,是否一致,即可知道:是否有人篡改请求参数。

开放平台最好能提供sdk,方便计算sign_value。

如何确保接口访问者的合法性?

请求链接中带有:api_key,服务端根据api_key,获取到api_secret,再根据同样算法a算出: sign_value,跟客户端的上传过来的sign_value进行对比。
其中:api_secret得保密,得确保只有客户端 + 服务端知道。

如何确保请求的唯一性?

需要一uuid标记当前请求,假设客户端再次带上uuid时,服务端采用类似redis的技术方案,去判断uuid是否曾经访问过。若访问过,则拒绝请求。
1、通过http请求参数中,带上uuid
2、也可以通过带有ts的:query_string,一整串当做:uuid来处理

注意:要先检验请求的合法性,后再确保请求的唯一性

如何确保请求的有效期?

参数中,带上ts(当前时间戳),服务端收到请求后,通过计算时间差,若超过一定的阈值,则直接拒绝。

如何避免水平越权?

api_key与开通的接口(path),需做一个映射关系,避免越权行为的存在。

如何避免key过期失效?

api_key + api_secret,服务端得有效期 or 调用次数的设计,并且每隔一段时间,维护用户与api_key、api_secret之间的关系。

计费

功能 优先级 功能说明 备注
按调用次数计费 T0 例如:1000次/30元
包月 T0 月均: 30元

备注:
1、当然了,上面2种只是最简单的计费方式。另外,会有单独的文章,专门描述如何计费。ß

同步转异步

在分配计算资源触发计算之前,只有:文件url、文件大小等少量信息,不足于决策:分配合理核数的cpu or gpu。
因此,比较好的方式是:由机器自身根据当前自身负载情况去决策:应该计算多少量的视频个数,以确保整个集群资源负载更加均衡些,具体流程如下图所示:

备注:
1、在物理机时代,更是如此,若无:同步转异步功能,非常容易导致:部分机器非常忙,部分机器非常闲。
2、在容器化时代,通过cgroup的方式,在本业务场景下,虽说能够缓解一部分机器负载不均的问题,但是,不能解决根本问题,极容易造成成本的浪费。
3、底层计算域,最好统一通讯范式:异步回调。
4、底层cpu or gpu可以根据自己的实际负载来拖取相关任务发起计算。
5、当业务量大时,需采用:2阶段以上的资源分配机制,其中,第一阶段:可以由网关根据请求入参,去初步:分配使用哪个配置的:cpu池子 or
gpu池子去处理,然后,第二阶段:再由底层机器,根据当前负载决策并发处理:几个计算任务。
建议:单独搞一个:资源主动调度服务来处理, 相关章节,将会在:资源调度详细阐述,这里面只是粗浅地介绍下。

解决方案

经过抽象,想要搭建一套开放平台,包括以下模块,如下图所示:

鉴权设计

redis中keys设计

库表设计

接口设计

类别 通讯模式 http请求方式 使用场景 耗时 备注
处理类 同步 Get 针对单个文件做简单处理 耗时一般在300ms以内
处理类 异步 POST 针对多个文件做复杂处理 耗时比较久
状态查询 同步 Get 结果查询、进度查询 耗时一般在10ms以内
控制类 同步 DELETE、POST 取消 耗时一般在10ms以内

处理类之同步请求

处理步骤:获取存储在小文件存储系统中的文件,触发cpu or gpu计算后,得到的文件的二进制信息。

GET请求:

1、图片处理:/api/v1/sync/image/{fn_code}?api_key=&ts=&sign=&url=

2、视频处理:/api/v1/sync/video/{fn_code}?api_key=&ts=&sign=&url=

响应报文:

1、二进制,处理后的图片 or 视频的二进制信息,一般情况下,可以直接在浏览器上展示

2、meta的json信息

处理类之异步请求

POST请求:

1、图片处理:/api/v1/async/image/{fn_code}?api_key=&ts=&sign=

2、视频处理:/api/v1/async/video/{fn_code}?api_key=&ts=&sign=

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{
"notifyUrl": "",
"media_urls": [
{
"url": "",
"args": {
"width": 1080,
"heidht": 720,
"duration": 60
}
}
],
"cmds": [
{
"cmd": "",
"args": {
}
}
],
"extra": {
}
}

3、文生图:/api/v1/async/text/{fn_code}?api_key=&ts=&sign=

4、文生视频:/api/v1/async/text/{fn_code}?api_key=&ts=&sign=

1
2
3
4
5
6
7
{
"notifyUrl": "",
"text": "",
"extra": {
}
}

异步接口响应报文

1
2
3
4
5
6
{
"error_code": "",
"error_msg": "",
"msg_id": "",
"success": true
}

异步接口回调报文

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
{
"msg_id": "",
"code": "",
"message": "",
"success": true,
"media_urls": [
{
"url": "",
"type": "url",
"extra": {
"file_size": 1111,
"mime": "mp4"
}
},
{
"url": "",
"type": "mask",
"extra": {
"file_size": 1111,
"mime": "jpg"
}
},
{
"url": "",
"type": "face",
"extra": {
"file_size": 1111,
"mime": "mp4"
}
}
],
"extra": {
"alg_version": ""
}
}

状态查询

GET请求:

1、结果查询:/api/v1/result?api_key=&ts=&sign=&msg_id=

注意:此类情况下,无需做唯一性检测

响应报文

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
{
"code": "",
"message": "",
"success": true,
"media_urls": [
{
"url": "",
"type": "url",
"extra": {
"file_size": 1111,
"mime": "mp4"
}
},
{
"url": "",
"type": "mask",
"extra": {
"file_size": 1111,
"mime": "jpg"
}
},
{
"url": "",
"type": "face",
"extra": {
"file_size": 1111,
"mime": "mp4"
}
}
],
"extra": {
"alg_version": "",
"alg_cost": 111
}
}

2、状态查询:/api/v1/status?api_key=&ts=&sign=&msg_id=

响应报文

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{
"code": "",
"message": "",
"success": true,
"handle_code": 1,
"handle_msg": "",
"handle_cost": 1000,
"step_list": [
{
"step_name": "download",
"step_cost": 10
},
{
"step_name": "image_info",
"step_cost": 2
},
{
"step_name": "upload",
"step_cost": 2
}
]
}

控制类

1、取消

DELETE请求:/api/v1/cancel?api_key=&ts=&sign=&msg_id=

响应报文

1
2
3
4
5
6
7
8
9
10
{
"code": "",
"message": "",
"success": true,
"extra": {
"alg_version": "",
"alg_cost": 111
}
}