插槽设计及使用
约 1619 字大约 5 分钟
2025-03-03
在联犀早期,很多扩展需求都是靠“插槽”思路解决的。
这种方式能在主流程之外接入额外逻辑,比如:
- 订阅鉴权
- 数据过滤
- 下发前校验
- 系统初始化回调
但随着系统规模变大,我们很快发现,“插槽”这个概念本身太轻了,难以支撑一个长期演进的扩展体系。
于是当前联犀已经把这部分能力升级为更正式的 Hook 架构。
这篇文章仍沿用旧标题,但内容讨论的是它的最新版设计。
旧插槽机制为什么不够用了
插槽最早解决的是“主流程里留一个洞,让别的服务接进去”。
这个思路没问题,但真正落地后会遇到几个典型问题:
1. 协议不统一
不同插槽可能各自定义请求格式、Headers、Body 模板和响应约定,时间一长就会变成“每个插槽都是一个特例”。
2. 失败策略不清楚
一个扩展调用失败,到底应该阻塞主流程还是只记日志继续?
如果没有明确策略,业务就只能靠临时判断。
3. 重试机制太粗糙
早期做法常常是固定重试几次,但没有区分:
- 业务失败
- 网络超时
- 5xx 异常
- 鉴权失败
结果就是要么重试不该重试的请求,要么遗漏真正需要兜底的情况。
4. 管理面太弱
如果扩展点只是几条散落的配置,很难回答这些问题:
- 当前有哪些扩展服务?
- 每个服务负责哪些能力点?
- 哪个服务在生效?
- 某个能力点是否被多个服务同时监听?
从插槽升级到 Hook
联犀当前的做法,是把“插槽”升级成标准化 Hook 架构。
它的核心不是简单改个名字,而是把扩展能力拆成两层:
HookServer
HookServer 表示一个真正可被调用的扩展服务。
它关心的是:
- 服务地址
- 鉴权方式
- 超时设置
- 最大重试次数
- 失败策略
HookCapability
HookCapability 表示这个服务声明自己要处理哪些扩展点。
它用 code + subCode 标识,例如:
userSubscribe.*dataFilter.projectScopedeviceSend.propertyControlSend
这样做的价值在于:
- 服务注册与能力声明解耦
- 一个服务可以负责多个扩展点
- 一个扩展点也可以由多个服务共同处理
为什么这种拆法更稳
把服务和能力分开后,扩展体系就从“调用某个 URL”变成了“根据业务能力匹配一组扩展服务”。
主流程并不关心某个服务的具体实现细节,只需要:
- 根据
code + subCode找到匹配的 Hook 服务 - 按统一协议发起请求
- 根据失败策略决定是否阻塞业务
这让扩展点成为架构的一部分,而不是项目后期留下的几个临时口子。
当前联犀里的标准协议
为了避免每个扩展点自己定义交互方式,联犀现在统一采用标准 POST 协议。
请求里会包含几类关键信息:
- 方法名,如
areaInfo.create - 业务数据
data - 当前用户上下文
userCtx - 请求 ID、时间戳、签名等元数据
如果启用了 HMAC,服务端会根据时间戳和请求体计算签名。
这样做的目的不是“安全功能越多越好”,而是让平台调用外部扩展服务时至少具备基本的身份校验和防重放能力。
失败策略为什么必须成为一等公民
扩展体系最大的坑,往往不是“调不通”,而是“调不通时平台该怎么办”。
联犀当前把失败策略显式做成配置:
fail:扩展失败时阻塞业务ignore:扩展失败时只记录日志,主流程继续
这看起来只是一个小开关,但它实际上决定了 Hook 在架构中的角色。
例如:
- 订阅鉴权失败,通常应该阻塞
- 某些通知类回调失败,可能只需要记录
如果这类语义不在架构层明确下来,业务代码最终就会塞满 if err != nil 的临时判断。
当前有哪些 Hook 点
当前联犀里已经存在多类 Hook 点,比较典型的有:
userSubscribe
用于 WebSocket 订阅鉴权。
平台只负责接收订阅请求和分发 Hook,不直接内置每个业务模块的权限细节。
dataFilter
用于 datasvr 查询时追加动态过滤条件。
这使得项目、区域、设备等复杂查询范围可以下沉到扩展层统一处理。
deviceSend
用于设备控制消息下发前做补充逻辑,比如校验、转译或拦截。
system
用于系统初始化等全局事件。
这些 Hook 点的共同特点是:
它们都不是“某一个业务的临时需求”,而是平台长期存在、需要对外开放的关键切面。
这种 Hook 机制适合解决什么问题
它最适合处理以下场景:
- 主流程不希望硬编码所有扩展逻辑
- 第三方或定制业务需要在关键节点插入行为
- 同一扩展能力需要跨服务复用
- 业务侧想保留独立实现和独立发布能力
它不适合解决的问题也很明确:
- 不是用来替代核心业务逻辑
- 不是把所有 if/else 都外包给扩展服务
- 不是为了“可配置而可配置”
真正应该放进 Hook 的,通常都是边界明确、扩展性强、又不适合写死在主流程里的能力。
总结
联犀从“插槽”走到今天的 Hook 架构,本质上是在完成一次架构升级:
- 从零散扩展点,升级成标准化扩展协议。
- 从单纯调用某个地址,升级成“服务注册 + 能力声明”的双层模型。
- 从临时错误处理,升级成带失败策略和重试语义的正式机制。
所以如果今天再问“插槽怎么设计”,联犀给出的最新版答案其实是:
不要只设计一个洞,而要设计一套可管理、可观察、可重试、可声明能力边界的 Hook 架构。
更新日志
2026/5/18 10:48
查看所有更新日志
43ef3-docs(blog): 新增后端与架构系列技术博客 18 篇,更新原有 7 篇于d4fa0-doc: 更换皮肤到最新版于8794f-feat: 完善项目`于
