AI视觉后端系统详细设计文档
个人专著《C++元编程与通用设计模式实现》由清华大学出版社出版。该书内容源于工业级项目实践,出版后市场反馈积极(已加印)。其专业价值获得了图书馆系统的广泛认可:不仅被中国国家图书馆作为流通与保存本收藏,还被近半数省级公共图书馆及清华大学、浙江大学等超过35所高校图书馆收录为馆藏。
个人软仓,gitee搜索“galaxy_0”
1. 项目概述
1.1 项目简介
AI视觉后端系统是一个高性能、可扩展的视觉数据处理与管理平台,专为实时计算机视觉应用设计。系统通过共享内存与视觉处理进程高效通信,提供完整的进程管理、模型生命周期管理、数据存储与检索、以及Web交互接口。该系统采用模块化架构设计,支持跨平台部署,可应用于工业自动化、智能监控、机器人视觉等多种场景。
1.2 核心功能
- 实时视觉数据处理:通过共享内存与视觉进程进行低延迟数据交互,支持高清图像、视频流及结构化视觉数据的实时处理
- Web服务接口:提供RESTful API和WebSocket接口,支持前端应用的实时数据展示与远程控制
- 多数据库支持:灵活支持SQLite3、JSON文件数据库和MySQL等多种数据存储方式,适应不同规模和性能需求
- 灵活日志系统:支持多后端日志记录(UDP、本地文件、管道、UNIX套接字),可配置日志级别与格式
- 进程与模型管理:提供视觉进程的启动、停止、重启控制,以及AI模型的部署、卸载与版本管理
- 网络配置管理:支持网络接口配置、IP地址管理、端口映射等网络相关功能
- 用户认证与授权:实现基于角色的访问控制(RBAC),确保系统安全性
1.3 要解决的问题与设计模式应用
1.3.1 功能需求实现遇到的问题
多数据库类型支持问题
- 问题描述:系统需要支持SQLite3、JSON文件和MySQL等多种数据库类型,以适应不同的部署环境和性能需求。直接实现多种数据库操作会导致代码重复和维护困难。
- 挑战:如何设计统一的数据库接口,使上层应用无需关心具体的数据库实现细节。
高性能进程间通信问题
- 问题描述:视觉进程与后端系统需要实时传输大量视觉数据(如高清图像、视频流),传统的进程间通信方式(如套接字)无法满足低延迟和高吞吐量的要求。
- 挑战:如何设计高效的通信机制,减少数据拷贝和通信延迟。
可扩展的日志系统问题
- 问题描述:不同的部署环境对日志记录有不同的需求,如本地文件日志、远程日志服务器、管道日志等。需要设计灵活的日志系统,支持多种日志后端的切换和扩展。
- 挑战:如何设计可插拔的日志架构,支持在运行时或编译时选择不同的日志后端。
事件驱动的系统架构问题
- 问题描述:系统需要处理大量并发事件,如Web请求、视觉数据就绪、系统状态变更等。传统的顺序处理方式无法满足系统的响应性能要求。
- 挑战:如何设计高效的事件调度机制,支持事件的异步处理和优先级管理。
共享数据的内存优化问题
- 问题描述:系统中存在大量重复的共享数据(如配置信息、模型元数据),直接存储会导致内存占用过高。
- 挑战:如何设计内存高效的数据存储机制,减少重复数据的内存占用。
跨平台和可移植性问题
- 问题描述:系统需要在不同的硬件架构(x86_64、armv7、aarch64)和操作系统上运行,直接使用平台特定的API会导致代码不可移植。
- 挑战:如何设计跨平台的抽象层,屏蔽不同平台的差异。
Web框架的可切换问题
- 问题描述:不同的项目可能对Web框架有不同的需求,如性能优先或功能优先。需要设计支持不同Web框架切换的架构。
- 挑战:如何设计统一的Web服务接口,支持在不同Web框架实现间无缝切换。
1.3.2 设计模式解决方案
抽象工厂模式(Abstract Factory)
- 应用模块:数据库模块(db)
- 解决问题:多数据库类型支持问题
- 实现方式:通过
dbFactory抽象工厂类创建不同类型的数据库对象,所有数据库实现都继承自统一的dbItfc接口,使上层应用无需关心具体的数据库实现细节。
享元模式(Flyweight)
- 应用模块:数据管理模块(flyData)
- 解决问题:共享数据的内存优化问题
- 实现方式:通过
flyData类实现享元模式,共享相同的配置信息和元数据对象,减少重复数据的内存占用,提高内存使用效率。
策略模式(Strategy)
- 应用模块:日志模块(log)
- 解决问题:可扩展的日志系统问题
- 实现方式:通过策略模式定义不同的日志后端策略(本地文件、UDP、管道等),使用
LOG模板类作为策略上下文,支持在运行时或编译时选择不同的日志策略。
命令模式(Command)
- 应用模块:应用核心模块(app)
- 解决问题:事件驱动的系统架构问题
- 实现方式:通过命令模式实现事件驱动架构,将系统事件封装为命令对象,使用事件调度器(dispatcher)进行事件分发和处理,支持异步事件处理和优先级管理。
单例模式(Singleton)
- 应用模块:全局资源管理(如dbFactory、flyData、LOG等)
- 解决问题:全局资源的统一管理问题
- 实现方式:通过单例模式确保全局资源(如数据库工厂、日志实例、享元数据等)在系统中只有一个实例,提供全局访问点,避免资源冲突和重复创建。
模板元编程(Template Metaprogramming)
- 应用模块:rapidjsonHelper、日志模块等
- 解决问题:编译时类型安全和性能优化问题
- 实现方式:通过C++模板元编程实现编译时类型检查和代码生成,如rapidjsonHelper中的类型特化,提高系统性能和类型安全性。
适配器模式(Adapter)
- 应用模块:Web服务模块(web)
- 解决问题:Web框架的可切换问题
- 实现方式:通过适配器模式定义统一的Web服务接口,为不同的Web框架(libhv、oatpp)实现适配器,支持在不同Web框架间无缝切换。
1.4 技术栈
| 技术类别 | 技术选型 | 版本要求 | 用途说明 |
|---|---|---|---|
| 编程语言 | C++ | C++14标准 | 核心系统开发,保证性能与资源效率 |
| 构建工具 | CMake | 3.16+ | 跨平台构建系统,支持多架构编译 |
| Web框架 | libhv/oatpp | 最新稳定版 | 提供HTTP服务与WebSocket支持,可切换实现 |
| 数据库 | SQLite3 | 3.30+ | 轻量级本地数据存储 |
| JSON | 自定义实现 | 结构化数据的文件存储 | |
| MySQL | 5.7+ | 大规模数据存储与关系型数据处理 | |
| 进程间通信 | 共享内存 | 自定义实现 | 高效视觉数据传输 |
| eventfd | Linux系统调用 | 事件通知机制 | |
| 设计模式 | 单例模式 | - | 全局资源管理 |
| 抽象工厂模式 | - | 多数据库类型支持 | |
| 命令模式 | - | 事件驱动架构 | |
| 享元模式 | - | 内存优化的数据管理 | |
| 策略模式 | - | 可配置的日志后端 |
2. 系统架构设计
2.1 整体架构
2.2 架构特点
高度模块化设计:系统采用清晰的分层架构,模块间通过定义良好的接口通信,提高代码复用性和可维护性。每个功能模块独立封装,便于单独测试和升级。
设计模式驱动开发:广泛应用成熟的设计模式,如单例模式用于全局资源管理、抽象工厂模式用于数据库类型切换、命令模式用于事件驱动、享元模式用于内存优化,使系统结构清晰、扩展性强。
多态与泛型支持:通过C++模板元编程和虚函数机制实现编译时和运行时多态,支持不同实现的无缝切换(如Web框架选择)和类型安全的代码设计。
灵活的配置管理:支持通过配置文件、命令行参数等多种方式进行系统配置,便于部署和维护。配置系统设计支持动态加载和热更新。
跨平台兼容性:通过CMake构建系统和条件编译技术,支持x86_64、armv7、aarch64等多种硬件架构,可在Linux、Windows等不同操作系统上运行。
高性能设计:采用共享内存进行进程间通信,事件驱动的架构,以及高效的内存管理策略,确保系统在处理实时视觉数据时保持低延迟和高吞吐量。
3. 核心模块设计
3.1 应用核心模块(app)
3.1.1 模块概述
应用核心模块是整个系统的中枢神经,负责系统初始化、事件分发、资源管理和生命周期控制。该模块采用命令模式作为事件驱动的基础,能够高效处理来自Web接口、共享内存和系统内部的各类事件,实现进程管理和系统应用的中间调度。
3.1.2 核心设计
- 事件系统:使用强类型枚举
emEvent定义系统支持的所有事件类型,确保编译时类型安全 - 命令模式实现:基于
wheels::dm::mainLoop模板实现事件循环,通过dispatcher_t进行事件分发 - 状态管理:维护系统运行状态,包括进程状态、模型状态、网络状态等
- 资源协调:协调各模块间的资源使用,确保系统资源的高效利用和正确释放
3.1.3 关键接口与代码示例
// 事件类型定义(部分)enumclassemEvent{EVT_START_CV=1,// 启动CV进程EVT_STOP_CV=2,// 停止CV进程EVT_RERSTART_CV=3,// 重启CV进程EVT_DEPLOY_MODEL=4,// 部署模型EVT_UNDEPLOY_MODEL=5,// 卸载模型EVT_MODEL_STATUS_CHANGED=6,// 模型状态变更EVT_CV_READY=7,// CV就绪EVT_CV_STOP=8,// CV停止EVT_NETWORK_ERROR=9,// 网络异常EVT_DATABASE_ERROR=10,// 数据库异常EVT_SHM_ERROR=11,// 共享内存异常EVT_WEB_ERROR=12,// Web异常EVT_LOG_ERROR=13,// 日志异常EVT_RESTART=14,// 重启EVT_STOP=15// 停止};// 应用主循环与事件分发器类型typedefwheels::dm::mainLoop<emEvent>app_t;typedefapp_t::dispatcher_t dispatcher_t;// 事件处理示例voidhandleCvReadyEvent(app_t&app){// 处理CV就绪事件的业务逻辑app.getDispatcher().dispatch(emEvent::EVT_CV_READY);}3.1.4 事件处理流程
3.2 Web服务模块(web)
3.2.1 模块概述
Web服务模块提供系统与外部应用的交互接口,支持两种主流Web框架实现:基于libhv的轻量级实现和基于oatpp的全功能实现。该模块负责处理HTTP请求、WebSocket连接、路由管理和请求响应处理,为前端应用提供完整的API支持。
3.2.2 核心设计
- 可切换框架实现:通过编译选项
WEB_BACKEND_HV在libhv和oatpp之间切换,适应不同的性能和功能需求 - RESTful API设计:遵循REST架构风格,提供统一的资源访问接口
- WebSocket支持:实现实时双向通信,用于推送视觉数据和系统状态更新
- 请求路由与处理:使用路由表管理API端点,支持中间件机制实现认证、日志等横切关注点
- 参数验证与错误处理:提供请求参数验证和统一的错误处理机制
3.2.3 关键接口与代码示例
Web模块采用oatpp框架实现,通过单例模式创建Web应用实例,路由配置使用oatpp的ENDPOINT宏定义。
// Web应用创建与启动#include"web.hpp"intmain(){// Web服务配置在router.hpp中通过ENDPOINT宏定义// 创建Web应用实例(单例模式)autoweb_app=webApp::create_shared("0.0.0.0",8080);// 启动Web服务boolret=web_app->start();if(ret){autolog=getLog();log->info("Web服务已启动,监听地址: 0.0.0.0:8080");}else{autolog=getLog();log->error("Web服务启动失败");}return0;}路由配置示例
路由通过routerController类中的ENDPOINT宏定义,以下是部分关键路由示例:
// router.hpp中的路由定义示例#includeOATPP_CODEGEN_BEGIN(ApiController)classrouterController:publicoatpp::web::server::api::ApiController{private:nsCVBackend::infer m_infer__;///< 推理模块类singleUser m_user__;///< 用户管理类nsCVBackend::token m_token__;///< 令牌管理类nsCVBackend::deploy m_deploy__;///< 视觉模型部署类// ...public:// 启动视觉后端ENDPOINT("GET","/api/v1/startVision",startVision,QUERY(String,token)){std::string str=static_cast<std::string>(token);returnstart_vision__(str);}// 停止视觉后端ENDPOINT("GET","/api/v1/stopVision",stopVision,QUERY(String,token)){std::string str=static_cast<std::string>(token);returnstop_vision__(str);}// 登录认证ENDPOINT("POST","/api/v1/login",login,BODY_STRING(String,body)){std::string str=static_cast<std::string>(body);returnlogin__(str);}// 获取认证tokenENDPOINT("GET","/api/v1/getToken",getToken){returnget_token__();}// 部署视觉后端ENDPOINT("PUT","/api/v1/deploy",deployVision,HEADER(String,contentType,"Content-Type"),HEADER(oatpp::Int64,contentLength,"Content-Length"),QUERY(String,token),REQUEST(std::shared_ptr<IncomingRequest>,request)){std::string str=static_cast<std::string>(token);size_t len=static_cast<size_t>(contentLength);std::string content_type=static_cast<std::string>(contentType);returndeploy_vision__(str,content_type,len,request);}// ...更多路由定义};#includeOATPP_CODEGEN_END(ApiController)