聚合请求
约 1454 字大约 5 分钟
2025-05-08
前面两节已经介绍了, 如何实现对 一个单一接口发起请求
, 聚合请求的核心就是, 如何实现对 多个接口发起请求
, 再单一请求基础之上在进行封装, 实现 一次执行, 调用多个接口, 并数据数据的能力
.
请求分析
聚合请求的概念很简单, 就是 一次函数调用, 自动按照指定规则调用调用一系列接口的能力
, 而这个逻辑, 本质上就是网关的核心能力
, 此处具备的能力, 就是 网关核心能力的上限
, 下面分析一下, 聚合请求需要具备哪些能力.
请求分组
一段逻辑, 串行执行逻辑清晰, 也号管理, 聚合请求也不例外, 多个请求规则传入, 注意处理一定是逻辑更清晰、更容易处理的, 但是, 绝对的串行, 会 导致最终全部接口请求完成耗时是一个累加关系
, 而接口耗时累加后, 很可能导致网关层面接口耗时极长, 进而超时. 而分组请求, 可以充分利用Go的并行能力, 将无依赖, 或者依赖已就绪的接口, 并行请求, 以来未就绪的接口排队等待
, 这样, 一组请求的的耗时, 与本组内请求数量无关, 仅与本组内请求耗时最长的接口有关, 一组接口请求完成的耗时, 等于耗时最长的接口耗时
. 那么请求分组如何实现呢?
请求分组实现也简单, 由使用方根据上线文场景, 确认接口间依赖关系, 然后对接口进行分组, 使用一个二维数组表达分组关系
, 排在前面的分组先执行, 每一组内的接口并行执行.
重点信息
请求到某一分组时, 默认分组内所有接口依赖的数据在前面的分组结果中都能获取到, 如果获取不到, 请求会出现异常.
配置分析
上面已经说明了为什么要对请求进行分组以及如何表达分组的概念, 下面分析下, 请求分组中, 每一个请求配置应该如何描述.
首先, 描述分组内的每一个请求, 是为了 构建出单一请求的配置
, 单一请求如何实现, 参照上一节内容: 核心请求能力实现 , 而构建单一接口的配置, 核心便是: 构建出接口的请求参数
, 那么, 对于聚合请求每一项配置的核心便是 参数构建规则
数据结构
// RequestConfigGroupItem 每一个接口的配置
type RequestConfigGroupItem struct {
Alias string `json:"alias"` // 请求别名
ParamRuleList []*RequestConfigGroupItemParamRule `json:"param_rule_list"` // 参数规则列表
RequestCfg *define.Request `json:"request_cfg"` // 请求配置
FailBehavior *RequestConfigGroupItemFailBehavior `json:"fail_behavior"` // 失败的行为, 不配置, 默认失败break
FinalFailureAllow bool `json:"final_failure_allow"` // 已经确定当前请求是最终失败了,当前请求是否允许执行
CacheInstance abstract.ICache `json:"-"` // 数据缓存实例
RateLimiter abstract.RateLimiter `json:"-"` // 流控实例
ResponseParser abstract.IResponse `json:"-"` // 响应数据解析
RequestBodyWrite abstract.IRequestBodyWrite `json:"-"` // 请求Body数据写入的实现
Condition any `json:"condition"` // TODO: 请求条件, 特定条件下不执行当前请求
}
// RequestConfigGroupItemParamRule 参数配置规则
type RequestConfigGroupItemParamRule struct {
Location consts.RequestDataLocation `json:"location"` // 参数位置
Path string `json:"path"` // 参数设置的路径
Type consts.DataType `json:"type"` // 参数类型
SourceAlias string `json:"source_alias"` // 数据源请求别名 __COMMON__ 代表从公共参数读取数据
SourceResultLocation string `json:"source_result_location"` // 数据源请求结果位置
SourceResultPath string `json:"source_result_path"` // 数据源数据, 从结果中获取的路径
DefaultValue string `json:"default_value"` // 默认值
}
// RequestConfigGroupItemFailBehavior 失败时的行为
type RequestConfigGroupItemFailBehavior struct {
Action string `json:"action"` // 请求失败的行为: continue: 继续执行下一个请求, error: 停止执行后续请求, 并且整体请求失败
}
结果分析
聚合请求的另一个问题便是 请求结果的输出
, 不同于一对一的接口请求, 聚合请求之后, 需要的返回数据 一般是从多个接口聚合而来
, 这样, 便于请求配置类似, 请求配置需要参数构建规则, 同样: 返回数据需要对应的构建规则
数据结构
// RequestConfigResultRule 返回值规则配置
type RequestConfigResultRule struct {
RequestAlias string `json:"request_alias"` // 请求别名
RequestResultLocation consts.ResponseDataLocation `json:"request_result_location"` // 请求结果位置
RequestResultPath string `json:"request_result_path"` // 请求结果路径
Location consts.ResponseDataLocation `json:"location"` // 返回值位置
DataPath string `json:"data_path"` // 返回值的路径
DataType consts.DataType `json:"data_type"` // 返回值类型
}
总结
综上, 我们分析道聚合请求的核心配置逻辑与规则, 其完整配置应该如下:
type RequestConfig struct {
Ctx context.Context `json:"-"` // 上下文
CommonParam map[string]map[string]any `json:"common_param"` // 公共参数
Group [][]*RequestConfigGroupItem `json:"group"` // 请求分组
ResultRule []*RequestConfigResultRule `json:"result_rule"` // 结果提取规则, 多个接口的结果构造成一个返回结果
}
CommonParam说明
聚合请求中, 除了依赖相关接口的请求之外, 还会以来外部输入的一些请求参数, 这些参数军通过 CommonParan 传入, 需要时读取即可.
RequestConfigGroupItem.FailBehavior 失败行为
接口请求存在失败的可能, 此配置用于控制请求失败的行为, 一些相对不重要的请求, 失败时可忽略, 继续执行, 但是重要的请求一旦失败就要终止执行
RequestConfigGroupItem.Condition 执行条件
这是一个保留属性, 用于控制, 当前接口满足特定条件才进行执行
具体实现
参见: 聚合请求的设计与实现