提交 e3b4b27e 编写于 作者: S ShiningZhang

update doc

上级 49483971
......@@ -2,31 +2,53 @@
Paddle Serving 服务端目前提供了支持 Http 直接访问的功能,本文档显示了详细信息。
- [基本原理](#1)
- [1.1 HTTP 方式](#2.1)
- [1.2 Http + protobuf 方式](#2.2)
- [示例](#2)
- [2.1 获取模型](#2.1)
- [2.2 开启服务端](#2.2)
- [客户端访问](#3)
- [3.1 HttpClient 方式发送 Http 请求](#3.1)
- [3.2 curl方式发送Http请求](#3.2)
- [3.3 Http压缩](#3.3)
<a name="1"></a>
## 基本原理
Server 端支持通过 Http 的方式被访问,各种语言都有实现 Http 请求的一些库,下边介绍使用 Java/Python/Go 等语言通过 Http 的方式直接访问服务端进行预测的方法。
<a name="1.1"></a>
**一. Http 方式:**
基本流程和原理:客户端需要将数据按照 Proto 约定的格式(请参阅[`core/general-server/proto/general_model_service.proto`](../../core/general-server/proto/general_model_service.proto))封装在 Http 请求的请求体中。
Server 会尝试去 JSON 字符串中再去反序列化出 Proto 格式的数据,从而进行后续的处理。
<a name="1.2"></a>
**二. Http + protobuf 方式:**
各种语言都提供了对 ProtoBuf 的支持,如果您对此比较熟悉,您也可以先将数据使用 ProtoBuf 序列化,再将序列化后的数据放入 Http 请求数据体中,然后指定 Content-Type: application/proto,从而使用 http + protobuf 二进制串访问服务。
实测随着数据量的增大,使用 JSON 方式的 Http 的数据量和反序列化的耗时会大幅度增加,推荐当您的数据量较大时,使用 Http + protobuf 方式,目前已经在 Java 和 Python 的 Client 端提供了支持。
<a name="2"></a>
## 示例
我们将以 examples/C++/fit_a_line 为例,讲解如何通过 Http 访问 Server 端。
<a name="2.1"></a>
**一. 获取模型:**
```shell
sh get_data.sh
```
<a name="2.2"></a>
**二. 开启服务端:**
```shell
......@@ -35,15 +57,28 @@ python3.6 -m paddle_serving_server.serve --model uci_housing_model --thread 10 -
服务端无须做任何改造,即可支持 BRPC 和 HTTP 两种方式。
<a name="3"></a>
## 客户端访问
<a name="3.1"></a>
**一. HttpClient 方式发送 Http 请求(Python/Java):**
为了方便用户快速的使用 Http 方式请求 Server 端预测服务,我们已经将常用的 Http 请求的数据体封装、压缩、请求加密等功能封装为一个 HttpClient 类提供给用户,方便用户使用。
使用 HttpClient 最简单只需要四步:1、创建一个 HttpClient 对象。2、加载 Client 端的 prototxt 配置文件(本例中为 examples/C++/fit_a_line 目录下的 uci_housing_client/serving_client_conf.prototxt)。3、调用 connect 函数。4、调用 Predict 函数,通过 Http 方式请求预测服务。
使用 HttpClient 最简单只需要四步:
- 1、创建一个 HttpClient 对象。
- 2、加载 Client 端的 prototxt 配置文件(本例中为 examples/C++/fit_a_line 目录下的 uci_housing_client/serving_client_conf.prototxt)。
- 3、调用 connect 函数。
- 4、调用 Predict 函数,通过 Http 方式请求预测服务。
此外,您可以根据自己的需要配置 Server 端 IP、Port、服务名称,设置 Request 数据体压缩,设置 Response 支持压缩传输,模型加密预测(需要配置 Server 端使用模型加密)、设置响应超时时间等功能。
此外,您可以根据自己的需要配置:
- Server 端 IP、Port、服务名称
- 设置 Request 数据体压缩
- 设置 Response 支持压缩传输
- 模型加密预测(需要配置 Server 端使用模型加密)
- 设置响应超时时间等功能。
1. Python 的 HttpClient 使用示例如下:
......@@ -97,6 +132,7 @@ Java 的 HttpClient 更多使用示例详见[`java/examples/src/main/java/Paddle
如果不能满足您的需求,您也可以在此基础上添加一些功能。
<a name="3.2"></a>
**二. curl方式发送Http请求:**
......@@ -108,7 +144,7 @@ curl -XPOST http://0.0.0.0:9393/GeneralModelService/inference -d ' {"tensor":[{"
`GeneralModelService`字段和`inference`字段分别为 Service 服务名和 rpc 方法名。
-d 后面的是请求的数据体,json 中一定要包含述 proto 中的 required 字段,否则转化会失败,对应请求会被拒绝。
-d 后面的是请求的数据体,json 中一定要包含述 proto 中的 required 字段,否则转化会失败,对应请求会被拒绝。
需要注意的是,数据中的 shape 字段为模型实际需要的 shape 信息,包含 batch 维度在内。
......@@ -151,6 +187,8 @@ repeated int32 numbers = 1;
表示返回结果中需要的数据名称,请参考模型文件 serving_client_conf.prototxt 中的`fetch_var`字段下的`alias_name`
<a name="3.2"></a>
**三. Http压缩:**
支持 gzip 压缩,但 gzip 并不是一个压缩解压速度非常快的方法,当数据量较小时候,使用 gzip 压缩反而会得不偿失,推荐至少数据大于 512 字节时才考虑使用 gzip 压缩,实测结果是当数据量小于 50K 时,压缩的收益都不大。
......@@ -173,13 +211,11 @@ curl --data-binary @data.txt.gz -H'Content-Encoding: gzip' -XPOST http://127.0.0
当 Http 请求头中设置了 Accept-encoding: gzip 时,Server 端会尝试用 gzip 压缩 Response 的数据,“尝试“指的是压缩有可能不发生,条件有:
- 请求中没有设置 Accept-encoding: gzip。
- body 尺寸小于 -http_body_compress_threshold 指定的字节数,默认是 512。gzip 并不是一个很快的压缩算法,当 body 较小时,压缩增加的延时可能比网络传输省下的还多。当包较小时不做压缩可能是个更好的选项。
这时 server 总是会返回不压缩的结果。
如果使用 curl,通常推荐使用 --compressed 参数来设置 Response 压缩,--compressed 参数会自动地在 http 请求中设置 Accept-encoding: gzip,并在收到压缩后的 Response 后自动解压,对于用户而言,整个压缩/解压过程就像透明的一样
如果使用 curl,通常推荐使用 --compressed 参数来设置 Response 压缩,--compressed 参数会自动地在 http 请求中设置 Accept-encoding: gzip,并在收到压缩后的 Response 后自动解压。
```shell
curl --data-binary @data.txt.gz -H'Content-Encoding: gzip' --compressed -XPOST http://127.0.0.1:9393/GeneralModelService/inference
......
......@@ -2,16 +2,29 @@
Paddle Serving 采用[brpc框架](https://github.com/apache/incubator-brpc)进行 Client/Server 端的通信。brpc 是百度开源的一款PRC网络框架,具有高并发、低延时等特点,已经支持了包括百度在内上百万在线预估实例、上千个在线预估服务,稳定可靠。与 gRPC 网络框架相比,具有更低的延时,更高的并发性能,且底层支持<mark>**brpc/grpc/http+json/http+proto**</mark>等多种协议。本文主要介绍如何使用 BRPC 进行通信。
- [示例](#1)
- [1.1 获取模型](#1.1)
- [1.2 开启服务端](#1.2)
- [客户端请求](#2)
- [2.1 C++ 方法](#2.1)
- [2.2 Python 方法](#2.2)
<a name="1"></a>
## 示例
我们将以 examples/C++/fit_a_line 为例,讲解如何通过 RPC 访问 Server 端。
<a name="1.1"></a>
**一. 获取模型:**
```shell
sh get_data.sh
```
<a name="1.2"></a>
**二. 开启服务端:**
```shell
......@@ -19,11 +32,19 @@ python3.6 -m paddle_serving_server.serve --model uci_housing_model --thread 10 -
```
服务端无须做任何改造,即可支持 RPC 方式。
<a name="2"></a>
## 客户端请求
<a name="2.1"></a>
**一. C++ 方法:**
基础使用方法主要分为四步:1、创建一个 Client 对象。2、加载 Client 端的 prototxt 配置文件(本例中为 examples/C++/fit_a_line 目录下的 uci_housing_client/serving_client_conf.prototxt)。3、准备请求数据。4、调用 predict 函数,通过 brpc 方式请求预测服务。
基础使用方法主要分为四步:
- 1、创建一个 Client 对象。
- 2、加载 Client 端的 prototxt 配置文件(本例中为 examples/C++/fit_a_line 目录下的 uci_housing_client/serving_client_conf.prototxt)。
- 3、准备请求数据。
- 4、调用 predict 函数,通过 brpc 方式请求预测服务。
示例如下:
```
......@@ -69,6 +90,8 @@ python3.6 -m paddle_serving_server.serve --model uci_housing_model --thread 10 -
| `test_type` | str | `"brpc"` | Mode of request "brpc" |
| `sample_type` | str | `"fit_a_line"` | Type of sample include "fit_a_line,bert" |
<a name="2.2"></a>
**二. Python 方法:**
为了方便用户快速的使用 RPC 方式请求 Server 端预测服务,我们已经将常用的 RPC 请求的数据体封装、压缩、请求加密等功能封装为一个 Client 类提供给用户,方便用户使用。
......
# 如何开发一个新的General Op?
- [定义一个Op](#1)
- [在Op之间使用 `GeneralBlob`](#2)
- [2.1 实现 `int Inference()`](#2.1)
- [定义 Python API](#3)
在本文档中,我们主要集中于如何为 Paddle Serving 开发新的服务器端运算符。在开始编写新运算符之前,让我们看一些示例代码以获得为服务器编写新运算符的基本思想。我们假设您已经知道 Paddle Serving 服务器端的基本计算逻辑。 下面的代码您可以在 Serving代码库下的 `core/general-server/op` 目录查阅。
......@@ -31,11 +36,14 @@ class GeneralInferOp
} // namespace paddle_serving
} // namespace baidu
```
<a name="1"></a>
## 定义一个Op
上面的头文件声明了一个名为 `GeneralInferOp` 的 Paddle Serving 运算符。 在运行时,将调用函数 `int inference()`。 通常,我们将服务器端运算符定义为baidu::paddle_serving::predictor::OpWithChannel 的子类,并使用 `GeneralBlob` 数据结构。
<a name="2"></a>
## 在Op之间使用 `GeneralBlob`
`GeneralBlob` 是一种可以在服务器端运算符之间使用的数据结构。 `tensor_vector``GeneralBlob` 中最重要的数据结构。 服务器端的操作员可以将多个 `paddle::PaddleTensor` 作为输入,并可以将多个 `paddle::PaddleTensor `作为输出。 特别是,`tensor_vector` 可以在没有内存拷贝的操作下输入到 Paddle 推理引擎中。
......@@ -63,6 +71,8 @@ struct GeneralBlob {
};
```
<a name="2.1"></a>
**一. 实现 `int Inference()`**
``` c++
......@@ -106,8 +116,7 @@ DEFINE_OP(GeneralInferOp);
`input_blob``output_blob` 都有很多的 `paddle::PaddleTensor`, 且 Paddle 预测库会被 `InferManager::instance().infer(engine_name().c_str(), in, out, batch_size)` 调用。此函数中的其他大多数代码都与性能分析有关,将来我们也可能会删除多余的代码。
基本上,以上代码可以实现一个新的运算符。如果您想访问字典资源,可以参考 `core/predictor/framework/resource.cpp` 来添加全局可见资源。资源的初始化在启动服务器的运行时执行。
<a name="3"></a>
## 定义 Python API
......
# 如何使用 C++ 定义模型组合
如果您的模型处理过程包含 2+ 的模型推理环节(例如 OCR 一般需要 det+rec 两个环节),此时有两种做法可以满足您的需求。
如果您的模型处理过程包含一个以上的模型推理环节(例如 OCR 一般需要 det+rec 两个环节),此时有两种做法可以满足您的需求。
1. 启动两个 Serving 服务(例如 Serving-det, Serving-rec),在您的 Client 中,读入数据——>det 前处理——>调用 Serving-det 预测——>det 后处理——>rec 前处理——>调用 Serving-rec 预测——>rec 后处理——>输出结果。
- 优点:无须改动 Paddle Serving 代码
......@@ -9,7 +9,7 @@
- 优点:只需要一次请求服务,效率高。
- 缺点:需要改动代码,且需要重新编译。
本文主要介绍第二种效率高的方法,该方法的基本步骤如下:
本文主要介绍自定义服务处理流程的方法,该方法的基本步骤如下:
1. 自定义 OP(即定义单个模型的前处理-模型预测-模型后处理)
2. 编译
3. 服务启动与调用
......@@ -202,7 +202,7 @@ void* data_1 = tensor_1.data.data();
```
## 编译
## 修改后编译
此时,需要您重新编译生成 serving,并通过 `export SERVING_BIN` 设置环境变量来指定使用您编译生成的 serving 二进制文件,并通过 `pip3 install` 的方式安装相关 python 包,细节请参考[如何编译Serving](2-3_Compile_CN.md)
## 服务启动与调用
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册