基于RESTful接口访问MindSpore Serving服务

查看源文件

概述

MindSpore Serving支持gPRCRESTful两种请求方式。本章节介绍RESTful类型请求。

RESTful是一种基于HTTP协议的网络应用程序的设计风格和开发方式,通过URI实现对资源的管理及访问,具有扩展性强、结构清晰的特点。基于其轻量级以及通过HTTP直接传输数据的特性,RESTful已经成为最常见的Web服务访问方式。用户通过RESTful方式,能够简单直接的与服务进行交互。

部署Serving参考快速入门 章节。

我们可以通过mindspore_serving.server.start_restful_server接口启动RESTful服务。

请求方式

当前仅支持POST类型的RESTful请求,请求格式如下:

POST http://${HOST}:${PORT}/model/${MODLE_NAME}[/version/${VERSION}]:${METHOD_NAME}

其中:

  • ${HOST}:指定访问的IP地址;

  • ${PORT}:指定访问的端口号;

  • ${MODLE_NAME}:请求的模型名称;

  • ${VERSION}:表示版本号。版本号是可选的,若未指定具体版本号,则默认使用模型的最新版本。

  • ${METHOD_NAME}:表示请求模型的具体方法名称。

如果使用curl工具,RESTful请求方式如下:

curl -X POST -d '${REQ_JSON_MESSAGE}' http://${HOST}:${PORT}/model/${MODLE_NAME}[/version/${VERSION}]:${METHOD_NAME}

例子:请求LeNet模型的predict方法进行数字图片的推理,请求如下:

curl -X POST -d '{"instances":{"image":{"b64":"babe64-encoded-string"}}}' http://127.0.0.1:1500/model/lenet/version/1:predict

其中:babe64-encoded-string表示数字图片经过base64编码之后的字符串。由于字符串比较长,不显式列出。

请求输入格式

RESTful支持Json请求格式,key固定为instancesvalue表示多个实例。

每个实例通过key-value格式的Json对象来表示。其中:

  • key:表示输入名称,需要与请求模型提供的方法的输入参数名称一致,若不一致,则请求失败。

  • value:表示具体的值。当前支持的value类型:

    • 标量:strbytesintfloatbool

      bytes:通过base64编码方式支持。

    • 张量:intfloatbool组成的一级或多级数组。

      张量通过数组格式表示数据和维度信息。

Json中支持的int类型:是int32表示的范围,float类型:是float32表示的范围。

请求格式:

{
    "instances":[
        {
            "input_name1":<value>|<list>|<object>,
            "input_name2":<value>|<list>|<object>,
            ...
        },
        {
            "input_name1":<value>|<list>|<object>,
            "input_name2":<value>|<list>|<object>,
            ...
        }
        ...
    ]
}

例子:

{
    "instances":[
        {
            "tag":"one",
            "box":[[1,1],[2,3],[3,4]],
            "image":{"b64":"iVBOR...ggg==="}
        },
        {
            "tag":"two",
            "box":[[2,2],[5,5],[6,6]],
            "image":{"b64":"iVBOR...QmCC", "type":"bytes"}
        }
    ]
}

其中:iVBOR...ggg===是图片数字0经过base64编码之后的省略字符串。iVBOR...QmCC是图片数字1经过base64编码之后的省略字符串。不同图片编码出来的字符串可能不同,上述是示意说明。

base64数据编码

bytes类型需要通过base64编码进行表示。base64除了可以表示bytes类型,也可以表示其他标量和张量数据,此时将标量和张量的二进制数据通过base64进行编码,并额外通过type指定数据类型,通过shape指定维度信息:

  • type:可选,如果不指定,默认为bytes

    支持int8int16int32int64uint8uint16uint32uint64float16(或fp16)、float32(或fp32)、float64(或fp64)、boolstrbytes

  • shape:可选,如果不指定,默认为[1]

例子:

如果要用base64编码表示:int16的数据类型,shape为3*2,值是[[1,1],[2,3],[3,4]]的张量,则表示如下:

{
    "instances":[
        {
            "box":{"b64":"AQACAAIAAwADAAQA", "type":"int16", "shape":[3,2]}
        }
    ]
}

其中AQACAAIAAwADAAQA:是[[1,1],[2,3],[3,4]]的二进制数据格式经过base64编码后的字符串。

请求支持的类型总结如下:

支持的类型

例子

备注

int

1,[1,2,3,4]

默认int32表示范围

float

1.0,[[1.2, 2.3], [3.0, 4.5]]

默认float32表示范围

bool

true,false,[[true],[false]]

bool类型

string

“hello”或者
{“b64”:”aGVsbG8=”, “type”:”str”}

直接表示或者指定type方式表示

bytes

{“b64”:”AQACAAIAAwADAAQA”} 或者
{“b64”:”AQACAAIAAwADAAQA”, “type”:”bytes”}

如果不填type,默认为bytes

int8,int16,int32,int64,
uint8,uint16,uint32,uint64,
float16,float32,float64,bool

{“b64”:”AQACAAIAAwADAAQA”, “type”:”int16”, “shape”:[3,2]}

利用base64编码,表示指定type的数据

请求应答格式

应答格式与请求格式保持一致。返回Json格式信息。应答格式如下:

{
    "instances":[
        {
            "output_name1":<value>|<list>|<object>,
            "output_name2":<value>|<list>|<object>,
            ...
        },
        {
            "output_name1":<value>|<list>|<object>,
            "output_name2":<value>|<list>|<object>,
            ...
        }
        ...
    ]
}
  1. 多实例请求后,如果多实例全部成功处理,则响应格式如下:

    例子:LeNet请求识别数字0和数字1

    {
        "instances":[
            {
                "result":0
            },
            {
                "result":1
            }
        ]
    }
    
  2. 如果部分实例出错,则响应格式如下:

    例子:lenet请求识别数字0和一个错误数字图片。

    {
        "instances":[
            {
                "result":0
            },
            {
                "error_msg":"Preprocess Failed"
            }
        ]
    }
    
  3. 如果请求全部失败,则响应格式如下:

    例子:lenet请求识别两张错误数字图片为例。

    {
        "instances":[
            {
                "error_msg":"Preprocess Failed"
            },
            {
                "error_msg":"Time out"
            }
        ]
    }
    
  4. 出现系统性或者其他解析等错误,则返回格式:

    例子:lenet传入非法Json字符串。

    {
        "error_msg":"Parse request failed"
    }
    

应答数据表示如下:

Serving输出类型

RESTful json中数据类型

说明

举例

int8, int16, int32, int64, uint8, uint16, uint32, uint64

json integer

整型格式的数据表示为json整型

1,[1,2,3,4]

float16, float32, float64

json float

浮点格式的数据表示为json浮点数

1.0,[[1.2, 2.3], [3.0, 4.5]]

bool

json bool

bool类型数据表示为json bool

true,false,[[true],[false]]

string

json str

字符串格式输出表示为json str

“news_car”

bytes

base64 object

二进制格式输出转为base64对象

{“b64”:”AQACAAIAAwADAAQA”}

访问开启SSL/TLS的RESTful服务

MindSpore Serving支持开启SSL/TLSRESTful服务,下面以单向认证为例展示如何启动并访问开启SSL/TLSRestful服务。

verify_client设置为False表示单向认证,开启SSL/TLS需要把mindspore_serving.server.SSLConfig对象传入start_restful_serverssl_config参数。其他内容可以参考访问开启SSL/TLS的Serving服务

import os
import sys
from mindspore_serving import server


def start():
    servable_dir = os.path.dirname(os.path.realpath(sys.argv[0]))

    servable_config = server.ServableStartConfig(servable_directory=servable_dir, servable_name="add",
                                                 device_ids=(0, 1))
    server.start_servables(servable_configs=servable_config)

    ssl_config = server.SSLConfig(certificate="server.crt", private_key="server.key", custom_ca=None, verify_client=False)

    server.start_restful_server(address="127.0.0.1:5500", ssl_config=ssl_config)


if __name__ == "__main__":
    start()

我们可以使用curl工具或pythonrequests库访问Serving的开启SSL/TLSRESTful服务。如果使用curl工具访问,可以尝试使用下面的请求方式:

curl -X POST -d '${REQ_JSON_MESSAGE}' --cacert '${PATH_TO_CA_CERT_FILE}' https://${HOST}:${PORT}/model/${MODLE_NAME}/version/${VERSION}]:${METHOD_NAME}

例子:请求add模型的add_common方法,具体如下:

curl -X POST -d '{"instances":[{"x1":[[1.0, 2.0], [3.0, 4.0]], "x2":[[1.0, 2.0], [3.0, 4.0]]}]}' --cacert ca.crt https://localhost:5500/model/add/version/1:add_common

我们这里需要将协议设置为https,设置选项--cacert的值为CA证书文件ca.crt的路径。

另外由于示例中使用了自签名的证书,也可以设置选项--insecure表示忽略对服务器证书的验证,具体如下:

curl -X POST -d '{"instances":[{"x1":[[1.0, 2.0], [3.0, 4.0]], "x2":[[1.0, 2.0], [3.0, 4.0]]}]}' --insecure https://localhost:5500/model/add/version/1:add_common