Thanos源码专题【左扬精讲】——Thanos API 组件(release-0.26)源码阅读和分析(详解 pkg\api\blocks\v1.go)
Thanos API 组件(release-0.26)源码阅读和分析(详解 pkg\api\blocks\v1.go)
https://github.com/thanos-io/thanos/blob/v0.26.0/pkg/api/blocks/v1.go
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 | // Copyright (c) The Thanos Authors. // Licensed under the Apache License 2.0. package v1 import ( "net/http" "time" "github.com/go-kit/log" // 日志库 "github.com/oklog/ulid" // ulid库 "github.com/opentracing/opentracing-go" // opentracing库,用于分布式追踪 "github.com/pkg/errors" // 错误处理库 "github.com/prometheus/client_golang/prometheus" // prometheus库,用于监控和度量指标收集 "github.com/prometheus/client_golang/prometheus/promauto" // promauto库,用于自动注册度量指标 "github.com/prometheus/common/route" // route库,用于路由管理 "github.com/thanos-io/thanos/pkg/api" // api库,用于处理API请求和响应 "github.com/thanos-io/thanos/pkg/block" // block库,用于处理块数据 "github.com/thanos-io/thanos/pkg/block/metadata" // metadata库,用于处理块元数据 extpromhttp "github.com/thanos-io/thanos/pkg/extprom/http" // extpromhttp库,用于扩展Prometheus HTTP客户端功能 "github.com/thanos-io/thanos/pkg/logging" // logging库,用于处理日志记录 "github.com/thanos-io/thanos/pkg/objstore" // objstore库,用于处理对象存储 ) // BlocksAPI is a very simple API used by Thanos Block Viewer. // BlocksAPI 是一个用于Thanos Block Viewer的非常简单的API。 type BlocksAPI struct { baseAPI *api.BaseAPI // 嵌入了api.BaseAPI,用于处理一些基础API操作 logger log.Logger // 日志记录器,用于记录日志信息 globalBlocksInfo *BlocksInfo // 全局块信息 loadedBlocksInfo *BlocksInfo // 加载的块信息 disableCORS bool // 是否禁用CORS bkt objstore.Bucket // 对象存储桶,用于存储和检索块数据 } // BlocksInfo 是块信息结构体,包含了标签、块元数据和刷新时间等信息。 type BlocksInfo struct { Label string `json: "label" ` // 标签,用于标识块信息 Blocks []metadata.Meta `json: "blocks" ` // 块元数据,包含了块的详细信息 RefreshedAt time.Time `json: "refreshedAt" ` // 刷新时间,表示块信息最后一次刷新的时间 Err error `json: "err" ` // 错误信息,如果获取块信息时发生错误,则包含具体的错误 } // ActionType int32 枚举类型,表示不同的操作类型。 type ActionType int32 const ( Deletion ActionType = iota // 删除操作 NoCompaction // 不压缩操作 Unknown // 未知操作 ) // parse 函数根据传入的字符串 s 返回对应的 ActionType 类型 // // 参数: // // s string: 待解析的字符串 // // 返回值: // // ActionType: 返回对应的 ActionType 类型 func parse(s string) ActionType { // 根据传入的字符串s进行分支判断 switch s { case "DELETION" : // 当s为"DELETION"时,返回Deletion类型 return Deletion case "NO_COMPACTION" : // 当s为"NO_COMPACTION"时,返回NoCompaction类型 return NoCompaction default : // 当s既不是"DELETION"也不是"NO_COMPACTION"时,返回Unknown类型 return Unknown } } // NewBlocksAPI creates a simple API to be used by Thanos Block Viewer. // NewBlocksAPI 创建一个新的 BlocksAPI 实例 // // 参数: // logger: 用于记录日志的 log.Logger 实例 // disableCORS: 是否禁用 CORS // label: BlocksAPI 实例的标签 // flagsMap: 传递给 API 的标志映射 // bkt: 用于存储对象的 objstore.Bucket 实例 // // 返回值: // *BlocksAPI: 返回一个新的 BlocksAPI 实例 func NewBlocksAPI(logger log.Logger, disableCORS bool, label string, flagsMap map [string]string, bkt objstore.Bucket) *BlocksAPI { // 创建一个新的BlocksAPI实例 return &BlocksAPI{ // 创建baseAPI实例,传入logger, disableCORS, flagsMap参数 baseAPI: api.NewBaseAPI(logger, disableCORS, flagsMap), // 传入logger参数 logger: logger, // 创建globalBlocksInfo实例,并设置Blocks为空数组和Label为传入的label参数 globalBlocksInfo: &BlocksInfo{ Blocks: []metadata.Meta{}, Label: label, }, // 创建loadedBlocksInfo实例,并设置Blocks为空数组和Label为传入的label参数 loadedBlocksInfo: &BlocksInfo{ Blocks: []metadata.Meta{}, Label: label, }, // 传入disableCORS参数 disableCORS: disableCORS, // 传入bkt参数 bkt: bkt, } } // Register 注册BlocksAPI路由到路由器 // // 参数: // // r *route.Router: 路由器对象 // tracer opentracing.Tracer: OpenTracing追踪器对象 // logger log.Logger: 日志记录器对象 // ins extpromhttp.InstrumentationMiddleware: 监控中间件对象 // logMiddleware *logging.HTTPServerMiddleware: HTTP服务器中间件对象 func (bapi *BlocksAPI) Register(r *route.Router, tracer opentracing.Tracer, logger log.Logger, ins extpromhttp.InstrumentationMiddleware, logMiddleware *logging.HTTPServerMiddleware) { // 调用基类API的注册方法 bapi.baseAPI.Register(r, tracer, logger, ins, logMiddleware) // 获取API的Instrumentation实例 instr := api.GetInstr(tracer, logger, ins, logMiddleware, bapi.disableCORS) // 注册GET请求处理函数 // 路径为"/blocks",处理函数为bapi.blocks r.Get( "/blocks" , instr( "blocks" , bapi.blocks)) // 注册POST请求处理函数 // 路径为"/blocks/mark",处理函数为bapi.markBlock r.Post( "/blocks/mark" , instr( "blocks_mark" , bapi.markBlock)) } // markBlock 函数用于标记一个块(Block)执行特定的操作。 // // 参数: // r: *http.Request 类型,包含请求信息的HTTP请求对象。 // // 返回值: // interface{}: 无返回值,故为nil。 // []error: 错误列表,这里不返回错误,故为nil。 // *api.ApiError: API错误对象,当发生错误时返回。 func (bapi *BlocksAPI) markBlock(r *http.Request) ( interface {}, []error, *api.ApiError) { // 获取请求参数 idParam := r.FormValue( "id" ) // 获取请求参数中的"id",表示要操作的块的ID actionParam := r.FormValue( "action" ) // 获取请求参数中的"action",表示要执行的操作类型 detailParam := r.FormValue( "detail" ) // 获取请求参数中的"detail",表示操作的详细信息,例如原因或备注 // 检查ID是否为空 if idParam == "" { return nil, nil, &api.ApiError{Typ: api.ErrorBadData, Err: errors.New( "ID cannot be empty" )} } // 检查Action是否为空 if actionParam == "" { return nil, nil, &api.ApiError{Typ: api.ErrorBadData, Err: errors.New( "Action cannot be empty" )} } // 解析ULID id, err := ulid.Parse(idParam) if err != nil { return nil, nil, &api.ApiError{Typ: api.ErrorBadData, Err: errors.Errorf( "ULID %q is not valid: %v" , idParam, err)} } // 解析Action类型 actionType := parse(actionParam) switch actionType { case Deletion: // 执行删除操作 err := block.MarkForDeletion(r.Context(), bapi.logger, bapi.bkt, id, detailParam, promauto.With(nil).NewCounter(prometheus.CounterOpts{})) if err != nil { return nil, nil, &api.ApiError{Typ: api.ErrorBadData, Err: err} } case NoCompaction: // 执行不压缩操作 err := block.MarkForNoCompact(r.Context(), bapi.logger, bapi.bkt, id, metadata.ManualNoCompactReason, detailParam, promauto.With(nil).NewCounter(prometheus.CounterOpts{})) if err != nil { return nil, nil, &api.ApiError{Typ: api.ErrorBadData, Err: err} } default : // 返回不支持的操作错误 return nil, nil, &api.ApiError{Typ: api.ErrorBadData, Err: errors.Errorf( "not supported marker %v" , actionParam)} } return nil, nil, nil } // blocks 函数用于处理BlocksAPI的blocks请求。 // // 参数: // // r *http.Request: HTTP请求对象 // // 返回值: // // interface{}: 返回的响应数据 // []error: 返回的错误列表 // *api.ApiError: API错误对象 func (bapi *BlocksAPI) blocks(r *http.Request) ( interface {}, []error, *api.ApiError) { // 获取URL查询参数中的"view"参数 viewParam := r.URL.Query().Get( "view" ) // 如果"view"参数值为"loaded" if viewParam == "loaded" { // 返回已加载的区块信息 return bapi.loadedBlocksInfo, nil, nil } // 返回全局区块信息 return bapi.globalBlocksInfo, nil, nil } // set 方法用于更新 BlocksInfo 结构体中的数据 // // 参数: // - blocks:[]metadata.Meta 类型的切片,包含要更新的区块数据 // - err:error 类型,包含错误信息,如果更新成功则为 nil func (b *BlocksInfo) set(blocks []metadata.Meta, err error) { // 判断是否存在错误 if err != nil { // 如果存在错误,则保持上次视图不变 // Last view is maintained. b.RefreshedAt = time.Now() b.Err = err return } // 更新视图时间 b.RefreshedAt = time.Now() // 更新区块数据 b.Blocks = blocks // 设置错误信息 b.Err = err } // SetGlobal updates the global blocks' metadata in the API. // SetGlobal 设置全局块信息 // // 参数: // // blocks - []metadata.Meta:块信息的切片 // err - error:错误信息 // // 说明: // // 将blocks和err参数传递给bapi.globalBlocksInfo的set方法,用于设置全局块信息 func (bapi *BlocksAPI) SetGlobal(blocks []metadata.Meta, err error) { // 设置全局块信息 // 将blocks和err参数传递给bapi.globalBlocksInfo的set方法 bapi.globalBlocksInfo.set(blocks, err) } // SetLoaded 设置 BlocksAPI 实例的已加载区块信息 // // 参数: // - blocks []metadata.Meta:已加载的区块元数据列表 // - err error:加载区块过程中出现的错误 func (bapi *BlocksAPI) SetLoaded(blocks []metadata.Meta, err error) { // 调用 loadedBlocksInfo 的 set 方法,将 blocks 和 err 传入 bapi.loadedBlocksInfo.set(blocks, err) } |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析