Skip to main content

注意:如果现有后端尚未使用新的后端 > 系统,请参阅 迁移

本节介绍了如何设置和定制自己的Backstage,其中涉及Backstage实例如何融入大系统的一些方面,但要更深入地了解Backstage在后端系统中的作用,请参见架构部分.

概览

最小化的 Backstage 后端非常轻量级,它是一个单独的软件包,包含一个package.json文件和一个src/index.ts文件,还不包括周围的工具和文档。 软件包通常放置在packages/backend文件夹,但这取决于你。 后端软件包是使用@backstage/create-app因此,您通常不需要自己创建。

创建新项目时,使用@backstage/create-app, 您将获得一个后端软件包,其中包含一个src/index.ts看起来是这样的

import { createBackend } from '@backstage/backend-defaults'; // Omitted in the examples below

const backend = createBackend();

backend.add(import('@backstage/plugin-app-backend/alpha'));
backend.add(import('@backstage/plugin-catalog-backend/alpha'));
backend.add(import('@backstage/plugin-scaffolder-backend/alpha'));
backend.add(
import('@backstage/plugin-catalog-backend-module-scaffolder-entity-model'),
);

backend.start();

初始设置中会增加一些插件和模块,但总体布局是一样的。

我们在这个文件中要做的是创建一个新的后端,使用createBackend插件是独立的功能,模块是对现有插件或模块的扩充,而服务则可用于覆盖行为以进行更深入的定制。 每个模块只能针对一个插件,且该插件必须也存在于同一个后端中。 最后,我们通过调用start方法。

定制

除了在后端安装现有插件和模块外,您还可以通过几种不同的方式来定制后端安装。

配置

最便捷的方法也许是静态配置。写入配置可以配置后端许多不同的方面,包括后端本身的行为,以及许多插件或模块。 您需要参考每个插件或模块的文档,了解可以进行哪些配置。 还请务必查看核心服务,因为其中也涵盖了如何配置这些内容。

服务

说到服务,它们是另一个重要的定制点。 服务允许您对后端进行更深入和更广泛的定制。 它们类似于实用 API在前端系统中,使用依赖注入技术为插件和模块提供通用功能。架构部分.

所有后端都必须安装一套核心服务,用于日志记录、数据库访问、HTTP 服务等。 幸运的是,所有这些服务都会在使用createBackend@backstage/backend-defaults软件包,这就是标准设置中的软件包。

如果需要自定义,所有这些服务都可以用自己的实现来替代。 最简单的方法是使用现有的服务实现,但增加额外的选项。 许多核心服务都可以这样自定义,但不是所有的,因为它们并不都有有意义的选项。

例如,假设我们要定制核心配置服务,以启用远程配置加载。 这将看起来像这样:

import { rootConfigServiceFactory } from '@backstage/backend-app-api';

const backend = createBackend();

backend.add(
rootConfigServiceFactory({
remote: { reloadIntervalSeconds: 60 },
}),
);

这样就可以传递 URL 作为配置目标,并每隔 60 秒轮询这些 URL 是否有变化。

但有一个例外,那就是内置的PluginMetadataService由框架提供,无法覆盖。

定制服务实施

在重写服务时,您并不局限于现有的实现方式,您还可以提供自己的自定义服务工厂。 这样,您就可以用完全自定义的实现方式全局重写服务,或在现有实现方式的基础上添加额外的逻辑。

要覆盖一项服务,需要在services选项,但这次我们需要使用createServiceFactory来创建我们的工厂。 例如,如果您想替换默认的LoggerService用你自己的,可能会是这样:

const backend = createBackend();

backend.add(
createServiceFactory({
service: coreServices.logger,
deps: {
rootLogger: coreServices.rootLogger,
plugin: coreServices.pluginMetadata,
config: coreServices.rootConfig,
},
factory({ rootLogger, plugin, config }) {
const labels = readCustomLogLabelsForPlugin(config, plugin); // custom logic
return rootLogger.child(labels);
},
}),
);

LoggerService负责为每个插件创建专门的日志记录器实例,而RootLoggerService的默认实现。LoggerService将用一个plugin在我们的自定义实现中,我们会从配置中读取并添加其他标签。

这个示例涉及到服务可以有不同的作用域,既可以作用于单个插件,也可以作用于根后端实例。 要了解更多相关信息,请参阅架构部分.

分成多个后端

部署 Backstage 的更高级方法是将后端插件分成多个不同的后端部署。部署文件威胁模型在此,我们将重点介绍如何做到这一点。

要创建一个单独的后端,我们需要创建一个额外的后端软件包。 该软件包将与现有后端分开构建和部署。 目前还没有通过以下方式创建后端的模板yarn new因此,最快捷的方法是复制新软件包并修改。 命名由你自己决定,取决于你如何分割东西。 在这个例子中,我们只使用一个简单的后缀。 你可能会得到这样的目录结构:

packages/
backend-a/
src/
index.ts
package.json <- "name": "backend-a"
backend-b/
src/
index.ts
package.json <- "name": "backend-b"

现在您可以修剪src/index.ts文件,以便只包含你希望成为后端一部分的插件和模块。 例如,如果你想拆分出 scaffolder 插件,你可能会这样做:

const backend = createBackend();

backend.add(import('@backstage/plugin-app-backend/alpha'));
backend.add(import('@backstage/plugin-catalog-backend/alpha'));
backend.add(
import('@backstage/plugin-catalog-backend-module-scaffolder-entity-model'),
);
backend.start();

还有backend-b中清理依赖关系。package.json也是如此:

const backend = createBackend();

backend.add(import('@backstage/plugin-scaffolder-backend/alpha'));
backend.start();

现在我们已经将后端分成了两个独立的部署,但仍需确保它们可以相互通信。 这是最困难也是最繁琐的部分,因为 Backstage 目前还没有提供开箱即用的解决方案来解决这个问题。 您需要使用自定义实现的DiscoveryService的自定义实现,并让它们相互返回正确的 URL。 同样,您还需要为DiscoveryApi在前端,除非你通过一个处理路由的代理将两个后端连接起来。

分离后端部署架构示例

下面是一个更复杂的设置示例,我们有三个不同的后端部署,每个部署都有自己的插件和模块。 在前端应用程序和后端实例之间,我们有一个反向代理,将流量路由到相应的实例。 作为保护后端部署安全的一个选项,该代理也可以设置为验证反向代理,拒绝未经验证的用户访问后端实例。

diagram of a backstage deployment with three separate horizontally scaled backend systems

在此示例中,我们将目录和搜索插件拆分为一个后端部署。 代理将所有流量路由至/api/catalog//api/search/通过这种分离,我们可以独立扩展和部署这两个插件,而且从性能和安全角度来看,它们也是隔离的。 同样,TechDocs 和 Scaffolder 插件也被分离出来,然后我们将其余流量路由到包含 App、Auth 和 Proxy 插件的实例。

我们还可以看到,每个插件都有自己的逻辑数据库,但通常设置为共享实际的数据库管理系统(DBMS)实例。 当然,这并不是必要条件,您可以根据自己的需要进一步划分或合并数据库。