3. 服务目录平台基础:数据模型、实体与组件概念、Catalog API 简介

服务目录(Service Catalog)是 Backstage 平台工程的核心数据平面。它通过统一的数据模型描述所有软件资源(微服务、API、网站、数据库、流水线等),并提供标准化的 API 进行查询、注册与更新。理解服务目录的数据模型、实体(Entity)与组件(Component)概念,是后续实现容量水位巡检自动化的前提。

3.1 服务目录数据模型:三层结构

Backstage 服务目录的数据模型采用 Kind → Entity → Spec 三层结构,每一层解决不同粒度的描述问题:

层级 说明 示例
Kind(种类) 定义实体的顶级分类,决定实体的语义角色 Component、API、Resource、System、Domain
Entity(实体) 一个具体的资源实例,包含元数据、规格和状态 Entity{apiVersion, kind, metadata, spec, status}
Spec(规格) 实体内部的详细配置字段,随 Kind 不同而变化 Component.spec.type、Component.spec.lifecycle
关键理解: 在容量水位巡检场景中,我们主要操作 Component 和 Resource 两种 Kind。Component 代表可独立部署的服务单元,Resource 代表该服务依赖的底层基础设施(如数据库、缓存、Kubernetes 集群)。

3.2 实体(Entity)核心结构

每个实体都是一个 JSON 对象,遵循以下标准结构。以下是一个典型的 Component 实体示例:

{
  "apiVersion": "backstage.io/v1alpha1",
  "kind": "Component",
  "metadata": {
    "name": "order-service",
    "namespace": "default",
    "title": "订单服务",
    "description": "处理用户订单的核心微服务",
    "labels": {
      "tier": "backend",
      "team": "platform-team"
    },
    "annotations": {
      "backstage.io/techdocs-ref": "dir:.",
      "grafana/dashboard-selector": "order-service-dashboard"
    },
    "tags": ["java", "spring-boot", "order"]
  },
  "spec": {
    "type": "service",
    "lifecycle": "production",
    "owner": "team:platform-team",
    "system": "order-system",
    "dependsOn": ["Component:payment-service", "Resource:order-db"],
    "providesApis": ["API:order-api"]
  }
}

实体字段说明:

  • metadata.name:唯一标识符,在同一 Kind 和 Namespace 下必须唯一。
  • metadata.annotations:键值对,用于存储与外部工具集成的配置(如 Grafana 看板链接、PagerDuty 服务 ID)。
  • spec.type:子类型,如 service、website、library、cli。
  • spec.lifecycle:生命周期阶段,常用值 production、experimental、deprecated。
  • spec.dependsOn:声明该组件依赖的其他实体,用于构建依赖关系图。

3.3 组件(Component)概念详解

Component 是服务目录中最常用的 Kind,代表一个可独立运行、可版本化、可部署的软件单元。在容量水位巡检中,Component 是巡检的基本目标对象。

Component 的常见类型与巡检场景对应关系:

spec.type 典型示例 容量巡检关注点
service 订单服务、用户服务 CPU 使用率、内存占用、请求 QPS、P99 延迟
website 管理后台、门户网站 页面加载时间、并发连接数、CDN 带宽
library 公共 SDK、工具库 通常不直接巡检,但依赖它的 service 会受影响
cli 部署工具、数据迁移工具 执行频率、任务队列积压
巡检最佳实践: 在 Catalog 中为每个 Component 添加 annotations,例如 monitoring/alert-threshold-cpu: "80",这样巡检插件可以直接从实体注解中读取阈值配置,无需硬编码。

3.4 实体关系图:Component、Resource、API 与 System

服务目录中的实体通过 dependsOn、providesApis、partOf 等关系形成拓扑。以下 SVG 展示了容量巡检场景下的典型实体关系:

服务目录实体关系图 - 容量巡检场景 System: order-system Component: order-service type: service | lifecycle: production Resource: order-db type: postgresql API: order-api type: openapi 容量巡检目标:CPU / 内存 / QPS 容量巡检目标:请求延迟 / 错误率 partOf dependsOn providesApis

3.5 Catalog API 简介

Backstage 提供一组 RESTful Catalog API,用于对服务目录中的实体进行增删改查。在容量水位巡检插件中,最常用的 API 是查询接口:

API 端点 方法 用途 巡检场景
/api/catalog/entities GET 查询实体列表,支持过滤、排序、分页 获取所有 kind=Component 且 spec.type=service 的实体
/api/catalog/entities/by-name/{kind}/{namespace}/{name} GET 按唯一标识查询单个实体 获取指定服务的详细元数据和注解
/api/catalog/entities/by-query POST 高级查询,支持复杂过滤表达式 查询 metadata.annotations.monitoring/alert-threshold-cpu 存在的实体
/api/catalog/locations GET 查询已注册的 Catalog 位置(如 YAML 文件路径) 确认巡检目标是否来自受信任的注册源
注意: Catalog API 默认返回所有实体,包括 kind=System、kind=Domain 等非巡检目标。在巡检插件中,务必使用 filter 参数缩小范围,例如 ?filter=kind=Component,spec.type=service,避免不必要的数据传输和解析开销。

3.6 使用 Catalog API 获取巡检目标

以下是一个使用 Catalog API 获取所有生产环境服务组件的示例请求与响应:

GET /api/catalog/entities?filter=kind=Component,spec.type=service,spec.lifecycle=production

响应示例:
[
  {
    "apiVersion": "backstage.io/v1alpha1",
    "kind": "Component",
    "metadata": {
      "name": "order-service",
      "namespace": "default",
      "annotations": {
        "monitoring/alert-threshold-cpu": "80",
        "monitoring/alert-threshold-memory": "85"
      }
    },
    "spec": {
      "type": "service",
      "lifecycle": "production",
      "owner": "team:platform-team",
      "dependsOn": ["Resource:order-db"]
    }
  },
  {
    "apiVersion": "backstage.io/v1alpha1",
    "kind": "Component",
    "metadata": {
      "name": "payment-service",
      "namespace": "default",
      "annotations": {
        "monitoring/alert-threshold-cpu": "75"
      }
    },
    "spec": {
      "type": "service",
      "lifecycle": "production",
      "owner": "team:payment-team"
    }
  }
]

巡检插件拿到实体列表后,可以:

  1. 从 metadata.name 获取服务标识。
  2. 从 metadata.annotations 读取自定义阈值配置。
  3. 从 spec.dependsOn 获取依赖的资源列表,用于关联基础设施容量数据。
  4. 遍历每个实体,调用监控系统 API 获取实时水位数据,与阈值对比生成告警。

3.7 实体注册方式:静态 YAML 与动态处理器

服务目录中的实体可以通过两种方式注册:

方式 描述 适用场景 巡检影响
静态 YAML 注册 在 catalog-info.yaml 中手动定义实体,通过 Location 导入 小型团队、原型验证、基础设施组件 实体稳定,适合长期巡检
动态处理器(Processor) 通过自定义 Processor 从外部系统(如 Kubernetes、PagerDuty)自动生成实体 大规模微服务、自动发现、持续集成 实体动态变化,巡检需处理新增/删除
巡检建议: 对于动态注册的实体,建议在巡检插件中增加 lastUpdated 时间戳检查,避免对已删除或已废弃的实体执行无效巡检。

以下 SVG 展示了从 YAML 注册到 Catalog API 查询的完整数据流:

服务目录数据流 - 从注册到查询 catalog-info.yaml 静态 YAML 定义实体 Catalog Processor 解析 & 校验 & 存储 Catalog API /api/catalog/entities 巡检插件 查询实体 → 获取水位 → 对比阈值 注册阶段 处理阶段 查询与巡检阶段

3.8 本章小结

  • 服务目录数据模型采用 Kind → Entity → Spec 三层结构,Component 是容量巡检的核心目标。
  • 实体通过 metadata.annotations 携带巡检阈值配置,通过 spec.dependsOn 表达依赖关系。
  • Catalog API 提供 /api/catalog/entities 等端点,支持按 Kind、类型、生命周期等条件过滤查询。
  • 实体注册支持静态 YAML 和动态处理器两种方式,巡检插件需要适配实体的动态变化。