TensorFlow Serving是什么?如何用它部署模型?
TensorFlow Serving 是什么?
TensorFlow Serving 是 Google 开源的高性能模型服务系统,用 C++ 编写,专门为生产环境设计。它的核心能力是把训练好的 TensorFlow 模型以 REST API 或 gRPC 接口对外提供推理服务,同时支持模型版本管理、热更新和多模型并行托管。
跟 Flask 封一个模型接口相比,TFS 的优势在于:gRPC 协议带来的低延迟(通常比 REST 快 3-10 倍)、内置的版本策略(支持同时服务多个版本做 A/B 测试)、以及自动模型加载/卸载机制。简单说,Flask 能做的 TFS 都能做,而且更适合高并发场景。
TFS 的架构核心是 Servable 抽象——模型、词表、查找表都可以是 Servable。Manager 负责管理 Servable 的生命周期,Source 监控文件系统发现新版本,Loader 负责加载和估算资源。这种解耦设计让 TFS 可以在不中断服务的情况下完成模型切换。
怎么用 TensorFlow Serving 部署模型?
部署流程分三步:导出模型 → 启动服务 → 调用推理接口。
第一步:导出 SavedModel 格式
TFS 只认 SavedModel 格式,不支持 Checkpoint。导出时需要指定签名(SignatureDef),告诉 TFS 输入输出分别叫什么、是什么类型。
pythonimport tensorflow as tf # 假设 model 是你训练好的 Keras 模型 model.save("/models/my_model/1") # 数字 1 是版本号 # 也可以用 tf.saved_model.save 手动控制签名 tf.saved_model.save(model, "/models/my_model/1", signatures={ 'serving_default': model.__call__.get_concrete_function( tf.TensorSpec(shape=[None, 3], dtype=tf.float32) ) } )
导出后用 saved_model_cli 检查签名是否正确:
bashsaved_model_cli show --dir /models/my_model/1 --all
输出会列出签名的输入输出名称、dtype 和 shape。这一步很关键——调用时字段名必须和签名一致,否则报错。
导出后的目录结构:
shell/models/my_model/ └── 1/ # 版本号(必须是整数) ├── saved_model.pb # 模型结构和元数据 └── variables/ # 模型权重
关键点:版本号必须是整数,TFS 按数字大小判断最新版本。热更新时只需在同级目录新建 2/ 文件夹放入新模型,TFS 会自动检测并加载。
第二步:启动 TFS 服务
最简单的方式是 Docker:
bashdocker run -d --name tfs \ -p 8501:8501 \ -p 8500:8500 \ -v /models/my_model:/models/my_model \ -e MODEL_NAME=my_model \ tensorflow/serving
端口说明:
- 8501:REST API(
/v1/models/{model}:predict) - 8500:gRPC
也可以用二进制直接启动,适合需要精细控制的场景:
bashtensorflow_model_server \ --model_config_file=models.conf \ --rest_api_port=8501 \ --grpc_port=8500 \ --enable_batching=true \ --batching_parameters_file=batcningenning_config.txt
多模型配置文件 models.conf:
shellmodel_config_list { config { name: "model_a" base_path: "/models/model_a" model_platform: "tensorflow" model_version_policy { specific { versions: 1 versions: 2 } } } config { name: "model_b" base_path: "/models/model_b" model_platform: "tensorflow" } }
第三步:调用推理接口
REST API 调用(更简单,适合调试):
bashcurl -X POST http://localhost:8501/v1/models/my_model:predict \ -H "Content-Type: application/json" \ -d '{"instances": [[1.0, 2.0, 3.0]]}'
注意 instances 字段对应的是 SignatureDef 中定义的输入名。如果签名中输入名不是默认的,需要用 inputs 字段显式指定:
json{ "inputs": { "input_tensor": [[1.0, 2.0, 3.0]] } }
gRPC 调用(性能更好,适合生产):
pythonimport grpc import numpy as np import tensorflow as tf from tensorflow_serving.apis import predict_pb2, prediction_service_pb2_grpc channel = grpc.insecure_channel('localhost:8500') stub = prediction_service_pb2_grpc.PredictionServiceStub(channel) request = predict_pb2.PredictRequest() request.model_spec.name = 'my_model' request.model_spec.signature_name = 'serving_default' request.inputs['input_tensor'].CopyFrom( tf.make_tensor_proto(np.array([[1.0, 2.0, 3.0]]), dtype=tf.float32) ) response = stub.Predict(request, 10.0) # 10秒超时 result = tf.make_ndarray(response.outputs['output_tensor'])
gRPC 比 REST 快的核心原因是使用 Protocol Buffers 序列化,省去了 JSON 解析开销,且支持长连接多路复用。
模型版本管理怎么配?
TFS 支持三种版本策略:
- 可用性优先(默认):新版本加载完成后才切换,旧版本继续服务直到新版本就绪,零停机
- 资源优先:先卸载旧版本再加载新版本,节省内存但会有短暂不可用
- 指定版本:固定使用某个版本号,适合回滚场景
通过 model_version_policy 配置:
shellmodel_version_policy { specific { versions: 1 versions: 2 } }
A/B 测试场景下,可以同时加载多个版本,调用时通过 URL 参数 ?version=2 或 gRPC 的 model_spec.version 指定调用哪个版本。
热更新操作:在模型目录下新建版本号文件夹放入新模型即可。TFS 的 Source 模块会定期轮询文件系统(默认 2 秒),发现新版本后自动触发加载。也可以通过 gRPC 调用 ReloadConfig API 手动触发。
TFS 和其他部署方案怎么选?
| 方案 | 适用场景 | 协议 | 多框架支持 | 生产成熟度 |
|---|---|---|---|---|
| TensorFlow Serving | TF 模型、高并发 | gRPC + REST | 仅 TensorFlow | 高 |
| TorchServe | PyTorch 模型 | REST + gRPC | 仅 PyTorch | 中(已归档) |
| NVIDIA Triton | 多框架混合 | HTTP + gRPC | TF/PyTorch/ONNX/TensorRT | 高 |
| FastAPI/Flask | 快速验证、自定义逻辑 | REST | 任意框架 | 低 |
选型建议:纯 TF 生态用 TFS 就够了;多框架混合部署考虑 Triton;快速原型验证用 FastAPI 更灵活。注意 TorchServe 已于 2025 年 8 月归档,如果之前在用建议迁移到 Triton。
生产环境要注意什么?
性能优化:
- 开启 batching:TFS 内置请求批处理,设置
--enable_batching和--batching_parameters_file可以把多个请求合并成一个大 batch 再推理,显著提升吞吐。典型配置下吞吐可提升 3-5 倍,但 P99 延迟会增加 - 用 TensorRT 优化:
--model_platform: "tensorflow_tensorrt"可以把模型转为 TensorRT 格式,推理速度提升 2-8 倍,适合 GPU 部署 - 调整
inter_op_parallelism和intra_op_parallelism线程数,通常设为 CPU 核心数
监控:
- Prometheus 指标:TFS 默认暴露
http://localhost:8501/monitoring/prometheus端点,包含请求延迟、QPS、模型加载状态、批处理统计等指标 - 健康检查:
GET /v1/models/my_model返回模型状态,可配合 Kubernetes liveness/readiness probe
高可用:
- 多副本部署 + 负载均衡,避免单点故障
- Kubernetes 集成:官方提供 TF Serving 的 Helm Chart,支持 HPA 自动扩缩容
- 模型存储建议用 NFS 或对象存储挂载,配合 CI/CD 管道自动推送新版本
常见坑:
- 模型签名不匹配是最常见的报错原因,部署前务必用
saved_model_cli验证 - Docker 镜像分 CPU 和 GPU 版本,GPU 版本需要安装 NVIDIA Container Toolkit
- 大模型首次加载耗时较长,建议预热(启动后发几条测试请求触发懒加载)
追问:TFS 能服务非 TensorFlow 模型吗?
不能直接服务。TFS 只支持 SavedModel 格式,也就是说只认 TensorFlow 模型。如果需要服务 PyTorch 或 ONNX 模型,要么先转换格式(ONNX → TF),要么换用 NVIDIA Triton 这种多框架服务系统。不过在实际生产中,模型格式转换往往引入精度损失,不建议这么做。更实际的做法是按框架选择对应的服务系统,或者直接上 Triton 统一托管。