ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Argo CD 服务端分页设计解析:为 Applications List 与 Watch API 引入 offset、limit 与 minName/maxName 游标

Argo CD 服务端分页设计解析:为 Applications List 与 Watch API 引入 offset、limit 与 minName/maxName 游标 Argo CD 服务端分页设计解析为 Applications List 与 Watch API 引入 offset、limit 与 minName/maxName 游标【免费下载链接】argo-cdDeclarative Continuous Deployment for Kubernetes项目地址: https://gitcode.com/GitHub_Trending/ar/argo-cd导读本文基于 Argo CD 仓库中的官方设计提案 docs/proposals/server-side-pagination.md完整剖析 Argo CD 为缓解大规模应用场景下 API Server 与 UI 性能瓶颈而提出的服务端分页Server Side Pagination方案。文章将带你理解为什么 Argo CD 需要把分页与过滤从客户端下沉到服务端、如何通过offset/limit与minName/maxName游标设计分页协议、服务端统计Application Stats如何补救分页对 UI 状态栏的破坏以及 CLI 与 UI 如何配合分页做向后兼容。读完本文你将掌握该方案的核心数据结构、字段语义、兼容策略与落地约束并能对照仓库源码验证每一处设计细节。一、背景与动机为什么需要服务端分页Argo CD 的 API Server 当前在响应 Applications List 请求时会把全部应用一次性放入单个响应返回。当集群中应用数量较少时这并无问题但一旦应用数量显著增长会带来两类直接影响UI 响应迟钝官方文档明确描述当应用数量增加到 2000 以上时即使在性能强劲的机器上Argo CD UI 也会变得无响应unresponsive。UI 需要一次性接收、渲染并统计全部应用数据。API Server 内存压力API Server 的内存占用会随应用数量线性增长。不过提案指出这一点并非关键问题可以通过提高 API Server 部署的内存上限来缓解。因此该提案的核心动机是以服务端分页减少 API Server 单次返回的数据量从而提升 UI 响应性同时兼顾 CLI 场景下降低对 API Server 的负载。从当前仓库源码看服务端List实现的现状与提案描述完全吻合server/application/application.go 中的List方法会从 lister 拉取全部应用随后在内存中依次完成名称过滤、项目过滤、repo 过滤、命名空间启用检查与 RBAC 鉴权最后按名称排序后整体返回——全程没有分页概念。这也解释了为什么提案要把offset/limit、minName/maxName以及一系列过滤字段引入ApplicationQuery。Goals目标为 Applications List 与 Watch API 支持服务端分页在 Argo CD UI 中利用分页提升响应性在 Argo CD CLI 中利用分页提升性能并降低 API Server 负载。Non-Goals非目标提案明确排除了一个已知问题API Server 在把超大规模 RBAC 策略应用到大量应用时本身会消耗大量 CPU。即使引入了分页API Server 在返回最后一页响应时依然必须对全部应用做 RBAC 策略计算因此该问题不在本提案解决范围内。二、协议设计ApplicationQuery 的新增字段提案建议为分页引入两组新字段全部落在ApplicationQuery消息中——该消息正是 Applications List 与 Watch 两个 API 共用的请求载荷。仓库中的原始定义位于 server/application/application.proto目前仅包含name、refresh、projects、resourceVersion、selector、repo、appNamespace与遗留的project等字段尚未包含分页字段即提案仍处于设计阶段尚未合入当前代码。2.1 游标分页字段minName / maxName提案指出Argo CD UI 与 CLI 都依赖 Watch API 获取应用的实时更新而 Watch API 本身是流式的、事件驱动的无法依赖 API Server 返回的稳定顺序。因此为了在 Watch API 上实现有效的服务端分页不能依赖返回顺序而应以应用名application name作为分页游标。为此List 与 Watch 两个 API 都将扩展两个可选字段minName指定从哪个应用名开始名字最小等于minName的应用会被包含在响应中maxName指定到哪个应用名结束名字最大等于maxName的应用会被包含在响应中。message ApplicationQuery { // ... existing fields // New proto fields for server side pagination // the application name to start from (app with min name is included in response) optional string minName 9; // the application name to end at (app with max name is included in response) optional string maxName 10; // offset optional int64 offset 18; // limit optional int64 limit 19; }字段编号的选取刻意留出了扩展空间minName/maxName紧接现有字段之后使用 9、10而offset/limit使用 18、19中间留给过滤字段见下文。2.2 偏移分页字段offset / limit对于普通的 List API提案同时建议增加经典的offset与limit字段offsetint64起始偏移量limitint64单页大小上限。offset/limit 适合 List API 这种一次性返回有序快照的场景而 minName/maxName 游标则专门解决 Watch API 无法依赖顺序的问题。2.3 服务端过滤字段要支撑服务端分页过滤逻辑也必须随之搬到服务端——否则分页后的每一页都无法独立满足用户过滤条件。因此ApplicationQuery还需扩展以下字段message ApplicationQuery { // ... existing fields // New proto fields for server side filtering // the repos filter repeated string repos 11; // the clusters filter repeated string clusters 12; // the namespaces filter repeated string namespaces 13; // the auth sync filter optional bool autoSyncEnabled 14; // the sync status filter repeated string syncStatuses 15; // the health status filter repeated string healthStatuses 16; // search optional string search 17; }各字段语义如下字段类型语义reposrepeated string按源仓库过滤clustersrepeated string按目标集群过滤namespacesrepeated string按命名空间过滤autoSyncEnabledoptional bool按是否启用自动同步过滤syncStatusesrepeated string按同步状态过滤healthStatusesrepeated string按健康状态过滤searchoptional string关键字搜索配套地Argo CD UI 应改为在 List / Watch 请求中填充这些字段而不是像现在这样在客户端做过滤。当前 UI 正是采用客户端过滤模式例如 ui/src/app/applications/components/applications-list/applications-status-bar.tsx 与 applications-summary.tsx 中健康状态、同步状态等统计数字均由applications.filter(...)在浏览器端逐项计算得出这正是提案要求改造的客户端计算点。三、Applications Stats分页后的统计补偿机制服务端分页会破坏 UI 中一个既有依赖Argo CD UI 会展示按同步状态、健康状态等维度划分的应用统计breakdown而这些数字目前由客户端基于 API Server 返回的全量应用列表计算对应上面提到的applications.filter(...)客户端统计。一旦分页生效单页响应只包含部分应用客户端统计将不再准确。为此提案引入 List API 响应中的新字段stats由服务端一次性返回全体应用的统计信息其 Go 结构如下type ApplicationLabelStats struct { Key string json:key protobuf:bytes,1,opt,namekey Values []string json:values protobuf:bytes,2,opt,namevalues } // ApplicationListStats holds additional information about the list of applications type ApplicationListStats struct { Total int64 json:total protobuf:bytes,1,opt,nametotal TotalBySyncStatus map[SyncStatusCode]int64 json:totalBySyncStatus,omitempty protobuf:bytes,2,opt,nametotalBySyncStatus TotalByHealthStatus map[health.HealthStatusCode]int64 json:totalByHealthStatus,omitempty protobuf:bytes,3,opt,nametotalByHealthStatus AutoSyncEnabledCount int64 json:autoSyncEnabledCount protobuf:bytes,4,opt,nameautoSyncEnabledCount Destinations []ApplicationDestination json:destinations protobuf:bytes,5,opt,namedestinations Namespaces []string json:namespaces protobuf:bytes,6,opt,namenamespaces Labels []ApplicationLabelStats json:labels,omitempty protobuf:bytes,7,opt,namelabels }字段说明字段说明Total应用总数TotalBySyncStatus按同步状态Synced / OutOfSync 等类型为SyncStatusCode聚合的计数TotalByHealthStatus按健康状态health.HealthStatusCode聚合的计数AutoSyncEnabledCount启用了自动同步的应用数量Destinations应用目标集群/命名空间集合ApplicationDestination列表Namespaces涉及的应用命名空间列表Labels按标签键聚合的标签值统计ApplicationLabelStats关键约束有两点stats必须基于 API Server 返回的全部应用填充即使客户端只加载了其中一页Argo CD UI 应改为直接使用服务端返回的 stats取代客户端计算。这样分页之后UI 顶部的状态条、汇总面板依然能展示全局准确的应用分布而无需拉取全量列表。四、Argo CD CLI 的分页支持与向后兼容4.1 命令级支持提案要求更新 Argo CD CLI 以支持服务端分页argocd app list命令新增--offset与--limit标志允许用户显式指定分页当用户未指定--offset与--limit时CLI 默认以每批 500 个应用batches of 500的方式分页拉取全部应用在保持列出全部语义的同时降低单次请求对 API Server 的峰值压力。CLI 相关实现位于 cmd/argocd/commands/app.go当前argocd app list尚无分页相关标志提案尚未实现但该文件是未来--offset/--limit标志与 List 请求组装逻辑的落点。4.2 向后兼容策略优雅降级通常Argo CD 在 CLI 引入新特性时会同步抬升最低支持的 API 版本。但本提案刻意规避了这一点提出了一套优雅降级策略如果 API Server 返回的应用数量多于CLI 请求中指定的limitCLI 应判定服务端不支持分页——此时响应实际是全量应用列表CLI 照常处理即可。这个判断逻辑非常巧妙支持分页的服务端在limit生效时返回的应用数必然 ≤limit反之一旦返回数超过limit说明服务端忽略了分页参数并返回了完整列表。借此用户可以在不降级 CLI的情况下单独降级 API Server二者依旧兼容工作。五、风险、取舍与替代方案5.1 风险与缓解API 版本兼容风险实现分页可能需要抬升 CLI 的最低支持 API 版本但上述返回数超过 limit 即判定不支持分页的兼容设计可以避免强制升级详见CLI Backward Compatibility一节。升级/降级策略提案声明不引入任何破坏性变更API Server 应能优雅处理不带分页字段的请求——即老客户端、新服务端、新客户端、老服务端四种组合均应可用。5.2 Drawbacks已知不足提案作者诚实列出了该方案的三个主要缺点缺乏性能剖析数据目前缺少端到端的性能剖析数据无法确认分页到底能带来多少性能提升无法利用 Kubernetes 原生分页Argo CD UI 提供了按应用名排序等功能而 Kubernetes API 并不支持这种排序因此无论 Argo 侧是否分页Argo 都必须从 Kubernetes 拉取全量列表实现复杂度高此前已有两次实现尝试分别对应 argoproj/argo-cd 的 PR #22444 与 #25097均因高复杂度和意外边界情况而失败这从侧面印证了 Watch API 分页与过滤组合场景的难度。5.3 Alternatives备选方案提案还讨论了不引入分页的替代路径提升前端性能升级到 React 19可立即获得性能收益并解锁新的性能剖析工具来定位瓶颈改进 RBAC 求值——列出应用的一个慢点是逐应用执行 RBAC 求值可以通过缓存编译后的 glob 模式等方式加速。精简列表载荷部分发送给 UI 的数据并无必要可以相对容易地裁剪掉从而减少单次响应体积。这些替代方案与分页并不互斥实际上可以组合推进。六、从源码看当前实现基线虽然分页字段尚未合入当前仓库但现有代码完整呈现了待改造前的基线形态可作为实现该提案的参照服务端 List 全量返回server/application/application.go 的List方法从 informer lister 取出全部应用依次做名称/项目/repo 过滤、命名空间启用检查、逐应用 RBAC 鉴权s.enf.Enforce(...)最后sort.Slice按名称排序后整体返回——分页字段将来可在此排序后、返回前的环节插入minName/maxName与offset/limit切片逻辑Watch 流式实现server/application/application.go 的Watch方法通过sendIfPermitted闭包逐事件做 RBAC 鉴权与过滤后推送到流式通道并借助resourceVersion实现增量事件minName/maxName游标正是要为这类流式场景提供稳定的分页锚点客户端统计现状applications-status-bar.tsx 与 applications-summary.tsx 展示的 UI 状态条/汇总面板目前都在浏览器端filter计算是未来切换到服务端stats字段的直接改造对象测试基线server/application/application_test.go 的TestListApps验证了 List 返回按名称字典序排序abc、bcd、defTestCoupleAppsListApps则在 100 个项目 × 100 个应用 10000 个应用的大规模场景下验证 RBAC 过滤行为——这些测试既是当前全量返回行为的证据也是未来分页行为测试的起点。七、总结服务端分页提案为 Argo CD 的大规模应用场景描绘了一条清晰的演进路线以offset/limit覆盖 List API 的偏移分页以minName/maxName应用名游标覆盖 Watch API 的流式分页把repos、clusters、syncStatuses、healthStatuses、search等过滤能力整体下沉到服务端配合新增的stats统计字段保住 UI 全局状态展示CLI 侧则以500 一批 超限即降级的策略同时兼顾负载控制与前后端版本兼容。该方案同样清醒地承认了自身局限——无法借用 Kubernetes 原生分页、实现复杂度高且已有两次失败尝试——并给出了 React 19、RBAC 求值优化、载荷精简等并行替代路径。对于关注 Argo CD 性能演进的开发者而言这份提案与仓库中的 List/Watch 实现代码互为印证是理解分页为什么要做、怎么做、做到什么程度的完整素材。【免费下载链接】argo-cdDeclarative Continuous Deployment for Kubernetes项目地址: https://gitcode.com/GitHub_Trending/ar/argo-cd创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表