4. 开发者门户工程
开发者门户(Developer Portal)是内部开发者平台面向工程师的统一入口。它把散落在代码仓库、CI/CD、监控、工单和 Wiki 中的信息聚合到一个可检索、可操作、可自助的界面里。Backstage 是当前最主流的开源门户框架,其核心由三块能力构成:软件目录(Software Catalog)负责“有哪些服务、谁负责、依赖谁”;软件模板(Software Templates)负责“如何按标准快速创建新项目”;技术文档中心(TechDocs)负责“文档与代码同源、集中呈现”。本节围绕这三块能力,讲清数据模型、落地方式与关键实现细节。
一、软件目录:用实体模型描述整个软件生态
Backstage 目录的本质是一个实体图(Entity Graph)。每个实体由 YAML 描述文件定义,通常放在代码仓库根目录的 catalog-info.yaml 中,由目录插件定期抓取并建立关系。实体有明确的 kind 与 metadata,最常用的几种如下:
- Component:一个可部署的服务、库或网站,是目录的主体。
- System:一组协作完成业务能力的组件集合。
- API:对外或对内暴露的接口契约,可关联 OpenAPI/AsyncAPI 定义。
- Resource:数据库、消息队列、缓存等基础设施依赖。
- Group / User:团队与人员,用于归属和权限。
实体之间通过 relations 自动建立反向关系,例如 ownedBy、partOf、dependsOn、providesApi。下面是一个订单服务的目录描述示例:
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
name: order-service
description: 订单创建与状态流转服务
annotations:
backstage.io/techdocs-ref: dir:.
grafana/dashboard-selector: "order-service"
tags: [java, spring-boot, tier-1]
spec:
type: service
lifecycle: production
owner: group:default/order-team
system: order-platform
providesApis:
- order-api
dependsOn:
- resource:default/order-db
- component:default/payment-service
目录数据来源有两种模式:静态注册(在 app-config.yaml 的 catalog.locations 中列出仓库地址或 GitHub 组织)与动态发现(通过 GitHub/GitLab 发现器自动扫描带 catalog-info.yaml 的仓库)。生产环境建议以动态发现为主、静态注册补充关键系统,避免手工维护遗漏。
dependsOn 可以回答“payment-service 故障会影响哪些上游”,通过 ownedBy 可以一键找到值班团队。因此录入时宁可少而准,不要多而乱。二、软件模板:把“新建服务”变成一次表单提交
软件模板用 kind: Template 定义,本质是“参数表单 + 骨架代码 + 自动化动作”的组合。用户在门户填写表单后,Backstage 的 Scaffolder 会执行一系列 action:拉取模板骨架、替换变量、创建仓库、注册目录实体、触发 CI。一个最小可用的模板结构如下:
apiVersion: scaffolder.backstage.io/v1beta3
kind: Template
metadata:
name: java-service-template
title: Java 微服务脚手架
spec:
parameters:
- title: 基本信息
required: [name, owner]
properties:
name:
type: string
pattern: '^[a-z][a-z0-9-]{2,30}$'
owner:
type: string
ui:field: OwnerPicker
port:
type: integer
default: 8080
steps:
- id: fetch
action: fetch:template
input:
url: ./skeleton
values: { name: '{{ parameters.name }}', port: '{{ parameters.port }}' }
- id: publish
action: publish:github
input:
repoUrl: github.com?owner=my-org&repo={{ parameters.name }}
- id: register
action: catalog:register
input:
repoContentsUrl: '{{ steps.publish.output.repoContentsUrl }}'
catalogInfoPath: /catalog-info.yaml
模板设计的关键在于约束前置:用 pattern 限制命名规范,用 OwnerPicker 保证归属合法,用默认值减少必填项。这样生成的项目天然符合目录规范,无需事后补录。模板骨架中应内置 catalog-info.yaml、CI 流水线文件、Dockerfile、健康检查端点和基础可观测性配置,使新服务“出生即合规”。
三、技术文档中心:文档与代码同源
TechDocs 采用“Docs like Code”模式:文档以 Markdown 存放在代码仓库的 docs/ 目录,通过 mkdocs.yml 组织导航,Backstage 在构建时渲染为静态站点并挂载到对应组件页面。实体只需声明 backstage.io/techdocs-ref: dir:.,门户即可自动关联。文档构建可放在 CI 中预生成并推送到对象存储,避免每次浏览都触发构建。
三块能力并非孤立:模板创建组件时自动写入目录实体,目录实体又自动关联其文档。下图展示了从模板实例化到目录与文档联动的完整数据流。
四、落地要点与常见问题
门户工程最容易失败的地方不是技术选型,而是数据质量与使用习惯。以下几点在实践中反复被验证有效:
- 目录实体与代码同仓库:
catalog-info.yaml随代码评审,归属和依赖变更可被 review 捕获,避免目录与真实架构脱节。 - 模板即规范:把命名、目录结构、CI 配置、可观测性埋点固化进模板,新项目默认合规,比事后治理成本低得多。
- 文档构建放 CI:TechDocs 在流水线中生成并上传,门户只做展示,避免浏览时等待构建。
- 权限与归属对齐:
owner必须指向真实存在的 Group,否则目录会出现“无主服务”,影响值班与告警路由。 - 渐进式接入:先接入核心系统与高频服务,再逐步扩展,避免一次性导入大量低质量实体稀释目录价值。
综上,Backstage 门户工程的落地路径可以概括为:先用目录把软件生态结构化,再用模板把标准动作自动化,最后用文档中心把知识沉淀到代码旁边。三者共享同一套实体模型,形成从“创建”到“运行”再到“理解”的完整闭环,这也是内部开发者平台区别于普通工具集合的核心特征。