VSS-HTTP架构设计

5 阅读5分钟

VSS 中 HTTP 架构设计

本文说明 core/app/sev/vss 信令服务中 REST/JSON HTTP API 的分层结构:Gin 引擎、全局中间件、/api 路由组、泛型 Handler 与业务 Logic 契约,以及与 SIP、流媒体(MS)、设备 RPC 的协作关系。


一、在整体进程中的位置

项目说明
启动main.gogo server.NewHttpSev(svcCtx).Start(),与 SIP(TCP/UDP)SSEWebSocket 并行运行。
监听":" + Config.Http.Port(仅端口,绑定 0.0.0.0 由 Gin 默认行为决定)。
框架Gingin.New(),默认 ReleaseMode)。
API 前缀业务接口统一挂在 /api 下(见 internal/server/http.go)。

二、分层结构总览

flowchart TB
    subgraph Server["HttpSev.Start"]
        Gin["gin.New()"]
        MW1["全局: CORS + OPTIONS"]
        GAPI["Group /api"]
        MW2["HttpHeader + Timeout"]
        Reg["RegisterApiHandlers"]
    end

    subgraph Handler["internal/handler/http"]
        NH["newHandler / newHandlerWithParams"]
        Parse["httpx.Parse -> Req"]
        Ctx["Context: IP + IsInternalReq"]
        TR["toResp(HttpResponse)"]
    end

    subgraph Logic["internal/logic/http/*"]
        BL["base / video / ms / gbs / onvif / notify"]
    end

    Gin --> MW1 --> GAPI
    GAPI --> MW2 --> Reg
    Reg --> NH
    NH --> Parse --> Ctx --> BL
    BL --> TR
层级路径职责
Serverinternal/server/http.go创建 Engine、挂中间件、注册 /api、监听端口。
Handlerinternal/handler/http/handler.gorouters.go解析请求、注入 Context、调用 Logic、统一写出 JSON。
Logicinternal/logic/http/{base,video,ms,gbs,onvif,notify}具体业务;实现 Path() + New() + DO() 契约。
Interceptorinternal/interceptor/http.go/api 组内:超时(及预留 Header Hooks)。
类型与上下文internal/types/types.gointernal/svc/service_context.goHttpResponseHttpRHandleLogic / HttpEHandleLogicServiceContext

三、Server 层:中间件与路由组

3.1 全局中间件(所有路径)

router.Use 中:

  • CORSAccess-Control-Allow-Origin: *、Methods/Headers *、预检缓存 Max-Age 等。
  • JSON 倾向c.Set("content-type", "application/json")
  • OPTIONS:直接 204 No ContentAbort,便于浏览器跨域预检。

当前未默认启用 gin.Logger(),生产日志依赖项目统一 logx / 业务日志。

3.2 /api

var aipGroup = router.Group("/api")
aipGroup.Use(interceptor.HttpHeader(), interceptor.Timeout(time.Duration(Config.Timeout)*time.Millisecond))
httpHandler.RegisterApiHandlers(svcCtx, aipGroup)
  • HttpHeader():现为透传 Next(),可扩展为统一鉴权/Trace 等。
  • Timeout(Config.Timeout):对每个请求启 goroutine 执行 c.Next(),超时则 AbortWithStatusJSON(408, {"error":"request timeout"})
    • Config.Timeout 来自 VssSevConfig.Timeoutcore/tps/conf/config.go,字段与 YAML 一致,在代码中与 time.Millisecond 相乘,以实际配置文件为准,常见为毫秒量级整型)。
    • 注意:与「单接口长时间阻塞」(如设备录像轮询)需结合业务评估是否应调大超时或拆异步。

3.3 路由注册表

所有 HTTP 业务路由集中在 internal/handler/http/routers.goRegisterApiHandlers,按领域分组:

分组包路径典型能力
baselogic/http/base/status/device-videos/ws-token
videologic/http/video取流地址、停流、流信息
mslogic/http/ms流组、按名查录像、MS 配置、reload
gbslogic/http/gbsCatalog、Invite、StopStream、回放控制、订阅
onviflogic/http/onvif发现、设备信息、Profile
notifylogic/http/notify流媒体回调:推/拉流、订阅、统计、HLS、帧信息等

完整路径以各 Logic 的 Path() 为准(例如 GET /api/statusPOST /api/video/stream 等)。


四、Handler 层:泛型适配与统一响应

4.1 两种入口

定义于 internal/handler/http/handler.go

  1. newHandlerWithParams[Req, Logic]

    • 使用 httpx.Parse 将 Query / Path / JSON Body 绑定到 Req
    • 调用 logic.New(ctx, c, svcCtx).DO(req)
  2. newHandler[Logic](无请求体)

    • 直接 logic.New(...).DO(),适用于纯 GET 或参数仅从 Path/Query 由 Logic 自行读取的场景(若仍用 httpx.Parse 需在 Logic 内处理,当前部分接口为无参 DO())。

4.2 Context 注入

在调用 New 之前向 context.Context 写入:

Key含义
constants.HEADER_IPc.ClientIP(),便于下游直接获取。
constants.CTX_VSS_IS_INTERNAL_REQ是否「内部请求」:根据 Referer 的 host 是否为 127.0.0.1 / ::1 / localhostConfig.InternalIp 判定。

业务可通过 contextx.GetIsInternalReq(ctx) 读取(例如 internal/pkg/ms/api.go 中按内外网区分行为)。

4.3 统一响应 toResp

Logic 返回 types.HttpResponse

type HttpResponse struct {
    Data interface{}
    Err  *response.HttpErr
}
  • Err != nilresponse.New().RequestError(...),携带统一错误语义与 localization
  • Data != nilSuccess 写出业务数据。
  • 两者皆无 / resp == nil:成功但 body 为 nil

Handler 顶层有 recover, panic 时打栈日志,避免进程崩溃(与 Gin 默认行为叠加,以实际为准)。


五、Logic 层契约(接口驱动)

定义于 internal/types/types.go

type HttpHandleLogicBase[Logic any] interface {
    Path() string
    New(ctx context.Context, c *gin.Context, svcCtx *ServiceContext) Logic
}

type HttpRHandleLogic[Logic, Req any] interface {
    HttpHandleLogicBase[Logic]
    DO(req Req) *HttpResponse
}

type HttpEHandleLogic[Logic any] interface {
    HttpHandleLogicBase[Logic]
    DO() *HttpResponse
}

约定习惯

  • 每个接口一个 单例指针(如 StatusLogicVVideosLogic),在 routers.go 中传给 newHandler / newHandlerWithParams
  • New 注入 ctxgin.ContextServiceContext,便于读 Header、访问 RPC/Redis/配置
  • DO 只做业务,不直接操作 c.JSON,保持 可测响应格式统一

编译期检查:Logic 文件内常见:

var _ types.HttpEHandleLogic[*statusLogic] = (*statusLogic)(nil)

六、导航代码

6.1 video:播放与流信息

对接 VSS 内部能力与 MS/VSS 协作,如 StreamPlayLogic 生成播放相关能力、StreamStopLogic 停止会话等(具体见各文件 DO)。

6.2 gbs:国标信令侧 HTTP 触发

将 HTTP 转为 channel 消息SIP 发送(如 Catalog、Invite、StopStream、订阅、回放控制),与 internal/logic/gbs_proc 协程配合。

6.3 ms:流媒体运维与查询

HTTP 代理调用 MS 的 HTTP APIinternal/pkg/ms),如 all_groups、query_by_names、reload 等;部分逻辑结合 contextx.GetIsInternalReq

6.4 notify:流媒体事件回调

MS/边缘服务向 VSS POST 各类事件;公共逻辑在 notify/common.go(如 setStreamState:解析 stream_name、校验通道存在、更新状态/保活)。与 stream.New().Parse设备 RPC 强相关。

6.5 onvif:探测与元数据

设备发现、Profile 等,配置依赖 Config.Onvif

6.6 base:状态与辅助

  • /status:返回绑定地址、HTTP/SIP 端口、部分 SIP 参数(便于探活与运维)。
  • /device-videos:设备录像查询(SIP RecordInfo 聚合,见专项文档)。
  • /ws-token:签发 WebSocket 子协议用 Token。

七、与 WebSocket / SSE 的关系

通道端口说明
HTTP APIConfig.Http.Port本文主体,/api/...
WebSocketConfig.WS.Port独立 net/http,见《VSS-WebSocket架构设计》
SSEConfig.SSE.Port独立服务,运维状态推送等

HTTP 中的 /ws-token 为 WebSocket 握手提供 Token,形成 HTTP 辅助 + WS 长连接 的组合。


八、扩展新接口的步骤建议

  1. internal/types(或现有 types 文件)增加 请求/响应结构体(若需要)。
  2. internal/logic/http/<domain> 新增 xxxLogic,实现 HttpRHandleLogicHttpEHandleLogic,实现 Path()DO
  3. internal/handler/http/routers.gorouter.GET/POST(..., newHandler...) 注册。
  4. 若需全链路超时,确认 Config.Timeout 是否足够;超长任务考虑异步化或单独调大(并评估 Timeout 中间件对 goroutine 的影响)。
  5. 若依赖内部调用方 Referer,注意网关/反向代理是否改写 Referer,以免影响 GetIsInternalReq

九、设计要点小结

  1. 前缀统一:对外 JSON API 集中在 /api,与端口、文档、网关规则一致。
  2. 契约清晰Path + New + DO + HttpResponse,Handler 处理器、Logic 业务逻辑。
  3. 解析统一:有 body 的接口优先 httpx.Parse,减少手写 ShouldBind
  4. 横切能力:CORS、OPTIONS、超时、(可扩展)Header 中间件;Context 注入 IP 与内部请求标记。
  5. 领域分包gbs / video / ms / notify / onvif / base 边界清楚,notify 与 MS 生命周期绑定紧密。

十、相关源码索引

说明路径
HTTP 服务启动core/app/sev/vss/internal/server/http.go
泛型 Handler / toRespcore/app/sev/vss/internal/handler/http/handler.go
路由注册core/app/sev/vss/internal/handler/http/routers.go
超时与 Header 中间件core/app/sev/vss/internal/interceptor/http.go
HTTP 契约类型core/app/sev/vss/internal/types/types.goHttpResponseHttpRHandleLogic 等)
进程入口core/app/sev/vss/main.go
VSS 配置结构core/tps/conf/config.goVssSevConfig

可与《VSS-WebSocket架构设计》对照阅读:二者共享 ServiceContext,但监听端口与协议模型不同。