2. Backstage 核心架构:App、Plugin、Backend、Frontend 的分层与通信机制

理解 Backstage 的架构分层是设计插件隔离策略的前提。Backstage 采用 前端-后端分离 的微内核架构,核心实体包括 App(应用壳)、Plugin(插件)、Frontend(前端模块) 和 Backend(后端服务)。这四个层次通过明确的契约和通信机制协同工作,为容量规划中的故障域隔离提供了天然的结构基础。

2.1 四层架构总览

下图展示了 Backstage 的核心分层结构及各层之间的通信路径。每一层都承担独立的职责,并通过标准接口进行交互。

Backstage 四层架构与通信机制 Backstage 核心架构分层与通信 App Shell(应用壳) 负责插件发现、路由注册、主题管理、全局布局 Frontend Plugins(前端插件层) Plugin A UI + 路由 Plugin B UI + 路由 Plugin C UI + 路由 Plugin D UI + 路由 Backend Plugins(后端插件层) Backend A API + 逻辑 Backend B API + 逻辑 Backend C API + 逻辑 Backend D API + 逻辑 基础设施层(数据库、缓存、外部服务) 前端-后端通信(REST/gRPC) 层间依赖/注册
架构要点:App Shell 不包含业务逻辑,仅作为插件容器。每个 Plugin 在前后端都有对应的模块,形成“一对插件对”。这种设计使得单个插件的故障可以被限制在其自身的前后端范围内,不会扩散到整个系统。

2.2 各层职责详解

层次 核心职责 关键技术 故障域范围
App Shell 插件注册、路由分发、全局 UI 框架、主题系统 React Router、Context API、Dynamic Import 全局(崩溃影响所有插件)
Frontend Plugin UI 渲染、用户交互、前端路由、状态管理 React、Material UI、Zustand/Redux 插件级(崩溃仅影响该插件页面)
Backend Plugin 业务逻辑处理、数据持久化、外部系统集成 Express/Koa、gRPC、Prisma/TypeORM 服务级(崩溃影响该插件后端功能)
基础设施层 数据库、缓存、消息队列、外部 API PostgreSQL、Redis、Kafka 数据级(故障影响所有依赖该资源的插件)

2.3 前后端通信机制

Backstage 的前端插件与后端插件之间通过 标准化的 API 代理 进行通信,而不是直接调用。这种机制是实现插件隔离的关键。

  • API 代理(Proxy):App Shell 内置一个反向代理,将前端发往 /api/{pluginId}/* 的请求转发到对应的后端插件服务。
  • 服务发现:后端插件启动时向 App Shell 注册自己的服务地址和路由前缀,前端无需感知后端的具体部署位置。
  • 通信协议:默认使用 RESTful HTTP/JSON;对于高性能场景,Backstage 也支持通过 gRPC 进行后端插件间的通信。
// 前端插件调用后端 API 的典型模式
// 使用 @backstage/core-plugin-api 提供的 createApiRef 和 fetchApi

import { createApiRef, useApi } from '@backstage/core-plugin-api';

// 1. 定义 API 引用(契约)
export const myPluginApiRef = createApiRef<MyPluginApi>({
  id: 'plugin.my-plugin.service',
});

// 2. 实现 API 客户端(自动通过代理转发)
class MyPluginClient implements MyPluginApi {
  constructor(private readonly fetchApi: { fetch: typeof fetch }) {}

  async getData(id: string): Promise<MyData> {
    // 请求自动被代理到后端插件的 /api/my-plugin/data/{id}
    const response = await this.fetchApi.fetch(`/api/my-plugin/data/${id}`);
    return response.json();
  }
}

// 3. 在 React 组件中使用
const MyComponent = () => {
  const client = useApi(myPluginApiRef);
  // client.getData(...) 触发跨层通信
};
隔离性分析:由于所有前端请求都经过 App Shell 的代理层,后端插件的地址变更、服务重启、甚至崩溃都不会直接影响前端插件的加载。前端插件只会收到 HTTP 错误响应(如 503),而不会导致整个页面崩溃。这为容量规划中的“故障域隔离”提供了第一道防线。

2.4 插件间的依赖与隔离

在 Backstage 中,插件之间允许存在依赖关系,但必须通过 显式接口 进行。这种设计避免了隐式耦合,使得每个插件的故障域可以被清晰界定。

插件间依赖与隔离边界 插件依赖与故障域隔离边界 故障域 A 故障域 B 故障域 C Plugin A (Frontend) Plugin A (Backend) Plugin B (Frontend) Plugin B (Backend) Plugin C (Frontend) Plugin C (Backend) 依赖接口 依赖接口 故障域边界(虚线框) 显式依赖(跨域通信)
容量规划警示:虽然插件间通过显式接口通信,但在容量规划中,如果 Plugin A 对 Plugin B 的依赖是同步且高频率的,那么 Plugin B 的容量瓶颈会直接传导至 Plugin A。在划分故障域时,应将这种强依赖的插件对视为一个“容量组”,避免将它们部署在完全独立的资源池中导致延迟放大。

2.5 分层架构对故障域隔离的启示

  1. 进程级隔离:每个后端插件可以独立部署为单独的进程或容器,实现操作系统级的故障域隔离。
  2. 通信级隔离:通过 API 代理和超时/熔断机制,防止后端故障无限期阻塞前端线程。
  3. 数据级隔离:每个后端插件应拥有独立的数据库 Schema 或数据库实例,避免数据层面的级联故障。
  4. 部署级隔离:在 Kubernetes 环境中,可以将不同插件部署到不同的 Node 或 Availability Zone,实现物理故障域隔离。