步骤一:建议先通读TensorFlow Servering官网,对整体概念有大体的认识
步骤二:去TF github下载源码。注意,同时下载tensoflow源码,servering会依赖其中的一部分
步骤三:开始源码解析
目录介绍:
api
对外服务接口部分
batching
不知道在干啥
config
Server的配置参数
core
模型管理核心部分。包括模型发现,加载,本机资源管理
model_servers
模型服务整体框架
resouces
单机资源管理(内存)
servable
具体模型加载服务接口
sources
模型数据源发现模块
utils
线程池 事件队列 工厂注册类 智能指针 等等什么东西
主要类结构介绍:
main启动后,ServerCore单例加载,然后PredictionServiceImpl 启动api目录下对外服务的四个程序接口,查询ServerCore中的结构提供服务。
ServerCore
Options options_;
ServableStateMonitorCreator(EventBus)
ServerRequestLoggerUpdater
std::map<string, int> platform_to_router_port_;
std::shared_ptr<EventBus<ServableState>> servable_event_bus_;
std::shared_ptr<ServableStateMonitor> servable_state_monitor_;
UniquePtrWithDeps<AspiredVersionsManager> manager_;
struct StoragePathSourceAndRouter {
FileSystemStoragePathSource* source;
DynamicSourceRouter<StoragePath>* router;
};
optional<StoragePathSourceAndRouter> storage_path_source_and_router_GUARDED_BY(config_mu_);
(实现manager接口)主要作用,读配置,初始化全局/单例的(file source),最主要结构在AspiredVersionsManager中。platform_to_router_port (根据配置,支持哪几种模型格式 save bundle mode/bundle)
AspiredVersionsManager
std::unique_ptr<AspiredVersionPolicy> aspired_version_policy_;
using AspiredVersionsMap =std::map<string, std::vector<ServableData<std::unique_ptr<Loader>>>>;
AspiredVersionsMap pending_aspired_versions_requests_ GUARDED_BY(pending_aspired_versions_requests_mu_);
std::unique_ptr<PeriodicFunction> manage_state_thread_;
std::unique_ptr<BasicManager> basic_manager_;
(实现manager接口)负责servable加载管理
1. Resource是否足够(完整的接口,没发现配置实现)
2. aspired_version_policy 默认 AvailabilityPreservingPolicy
3. manage_state_thread,定期从队列pending_aspired_versions_requests_中获取Aspired-versions requests,根据aspired_version_policy策略执行加载动作
4. target_impl_ 模型目录变化后,新的version需要加载的回调函数。(放入pending_aspired_versions_requests_请求)
BasicManager
using ManagedMap = std::unordered_multimap<string, std::shared_ptr<LoaderHarness>>;
LoaderHarness::Options harness_options_;
EventBus<ServableState>* servable_event_bus_;
ManagedMap managed_map_ GUARDED_BY(mu_);
ServingMap serving_map_;
Env* const env_;(跨平台)
std::unique_ptr<ResourceTracker> resource_tracker_ GUARDED_BY(mu_);
std::unique_ptr<Executor> load_executor_,unload_executor_
(实现manager接口)
1. 保存每个loader的状态 2. 资源管理 resoure tracker 3. 跨平台 4. Executor 线程池or 单线程
ServingMap
using HandlesMap = std::unordered_multimap<ServableRequest,std::shared_ptr<const LoaderHarness>, HashRequest, EqRequest>;
FastReadDynamicPtr<HandlesMap> handles_map_;
Status GetUntypedServableHandle(const ServableRequest& request, std::unique_ptr<UntypedServableHandle>* untyped_handle);
handles_map_存储servable到session的映射(handle),GetUntypedServableHandle返回这个handle,执行查询
FileSystemStoragePathSource
FileSystemStoragePathSourceConfig config_ GUARDED_BY(mu_);
AspiredVersionsCallback aspired_versions_callback_ GUARDED_BY(mu_);
std::unique_ptr<PeriodicFunction> fs_polling_thread_ GUARDED_BY(mu_);
全局,工厂(根据配置对每个source目录一个实例),发现新目录(最新的or有更新的)后根据开始配置,调用不同的回掉函数,放入AspiredVersionsManager的pending_aspired_versions_requests_,
总结
代码框架及其恶心,不知道为啥需要这么多类,搞这么多层次(扫描目录,如何加载就让我看了一天多才懂。还有一坨工厂什么模版,模版层次多的都让我糊涂了,需要翻来覆去的看才能看懂)。虽然是大google的东西,精细的环节,为啥需要这么设计还没学习到。