CBA 模拟考 A
首次创建新的 Backstage 应用时,正确做法是什么?
- 添加核心包依赖后,应用结构会自动生成
- 直接克隆 upstream 仓库并迁入内部仓库使用
- 运行官方应用生成器创建应用骨架,并在组织内部管理该仓库
- 直接运行公开容器镜像即可
在本地开发中启动开发服务器后会发生什么?
- 生成生产 bundle,输出静态文件后退出
- 只启动后端,前端必须另行启动
- 只执行数据库迁移后退出
- 同时启动前端和后端,并即时反映代码变更
Backstage 应用仓库为何区分 packages/ 和 plugins/ 目录?
packages/存放应用自身的前端和后端,plugins/存放在该仓库中开发的插件packages/仅供前端使用,plugins/仅供后端使用packages/存放构建产物,plugins/才是源码目录packages/会发布到公共 registry,而plugins/不会发布
开发服务器运行正常时,为什么仍要单独执行类型检查?
- 因为 bundler 遇到类型错误一定会立即停止构建
- 因为开发服务器的 bundler 会跳过类型检查,运行时可能看不出类型错误
- 因为只有类型检查完成后才会安装依赖
- 因为只有 TypeScript 编译器能解析 JSX
向 workspace 添加新的插件包,哪种方法合适?
- 使用提供的生成命令,选择类型并创建插件骨架
- 重新创建一个 Backstage 应用,再把插件放进去
- 在 catalog 中注册新的 Component entity,代码就会生成
- 先在数据库中创建插件表
为什么应提交 Backstage 仓库的依赖锁文件?
- 只有存在锁文件,插件才能注册到 catalog
- 锁文件会同时保存应用配置值
- 没有锁文件,TypeScript 就无法编译
- 防止不同构建环境解析出不同的传递依赖版本,从而获得可复现构建
生产环境的后端构建命令做什么?
- 只生成前端静态文件
- 创建容器镜像并推送到 registry
- 把后端包打包成可放入容器镜像的形式
- 向数据库应用 schema
Backstage 文档推荐的默认容器构建方式是什么?
- 把全部源码放进镜像,并从容器内开始安装依赖
- 先在宿主机完成构建,再只把产物复制进镜像
- 不构建,直接把开发服务器固化为镜像
- 前端和后端必须拆成不同镜像
生产配置文件已放入镜像,如何让不同环境使用不同的值?
- 为每个环境单独构建镜像
- 容器启动时用脚本覆盖配置文件
- 把配置写成源码常量并按环境分支
- 在配置中使用环境变量替换,并在运行时注入变量
前端 bundle 会包含构建时配置,因此要注意什么?
- bundle 中的值可以在运行时随时安全修改
- bundle 会完整包含后端配置
- 构建时固化的值会暴露给浏览器,因此不能放入秘密
- 前端完全不使用配置
要在本地确认后端插件的行为,首先应查看哪里?
- 浏览器开发者工具的元素检查标签页
- 运行开发服务器的终端中的后端日志
- catalog entity 页面的概览卡片
- 构建产物目录中的 bundle 文件
一次性升级 Backstage 相关包版本的命令有什么作用?
- 将仓库中的 Backstage 包一起升级到彼此兼容的组合
- 提高应用 release 标签并发布新版本
- 升级数据库 schema 版本
- 把 catalog entity 的 apiVersion 改为最新版
Backstage 项目的默认测试命令执行什么?
- 打开浏览器验证端到端场景
- 通过测试 runner 执行各包的单元测试
- 只做类型检查并跳过测试
- 只检查 lint 规则违规
构建 Backstage 时为何要使用项目要求范围内的 Node.js 版本?
- Node 版本会改变 catalog schema
- Node 版本不同会改变配置文件语法
- 原生模块构建和包声明的运行环境约束与版本绑定,超出范围可能导致安装或运行失败
- Node 版本决定门户默认主题
哪项正确描述 Backstage 的客户端—服务器结构?
- 浏览器中的 React 应用通过 HTTP 与 Node.js 后端通信,由后端负责外部系统集成
- 浏览器直接调用外部系统 API,后端只提供静态文件
- 后端在服务器生成 HTML,是服务端渲染结构
- 前后端在同一进程中运行,是单一 binary 结构
同时读取默认配置文件和生产配置文件时会怎样?
- 后一个文件整体替换前一个文件
- 两个文件的值不同时启动失败
- 生产文件只作用于前端
- 两个文件会合并,后指定文件的值覆盖前面的值
为什么生产 Backstage 推荐使用 PostgreSQL?
- catalog 和多个后端插件需要持久存储,而默认内存存储会在重启后消失
- 只有使用 PostgreSQL,文档插件才能构建
- SQLite 无法在 TypeScript 中使用
- 只有使用 PostgreSQL,认证插件才能工作
部署到生产后,前端的所有后端请求都失败,首先检查什么配置?
- catalog 的静态 location 列表
- 应用和后端的 base URL,以及跨域许可设置
- 文档插件的构建方式
- 认证提供方的 callback URL
用同一 hostname 提供前端和后端有什么好处?
- 不安装后端插件也能显示页面
- 可以把配置文件数量减为一个
- 能减少数据库连接数
- 浏览器不会产生跨域请求,相关设置和 cookie 处理更简单
为什么生产环境不能保留 guest 认证提供方?
- 使用 guest 会使后端无法启动
- 使用 guest 无法读取 catalog
- 任何人都能登录,基于身份和所有权的授权判断将失去意义
- guest 无法与 PostgreSQL 一起使用
为源码管理系统集成配置 token 的目的是什么?
- 代替登录页面显示
- 代替执行构建工作流
- 把 catalog entity 备份到源码仓库
- 让后端读取仓库内容,并获得更充足的 API 调用额度
如何不把 token 直接写入配置文件,而从外部注入?
- 在值的位置写环境变量引用,并在运行环境中提供该变量
- 加密整个配置文件,再由后端解密
- 把 token 放入数据库表并从配置中引用
- 把 token 放进前端 bundle,再让后端读取
将 Backstage 部署到 Kubernetes 时,如何让容器重启后数据仍保留?
- 给 Pod 挂载持久卷以保存本地文件数据库
- 把副本固定为一个以阻止重启
- 连接外部 PostgreSQL,并用 secret 注入连接信息
- 延长 catalog 处理周期以减少重新采集
将 Backstage 后端扩展到两个以上副本时,应确认什么?
- 每个副本都要构建不同的前端 bundle
- 多个实例共享同一数据库,并确认周期任务会协调而不会重复执行
- 让每个副本拥有独立 catalog 数据库
- 按副本数量分别签发集成 token
为什么不让浏览器直接调用内部 API,而使用后端 proxy 配置?
- 因为前端不能使用 TypeScript
- 因为 proxy 会缓存所有响应,始终更快
- 因为凭据可留在后端,同时避免跨域问题
- 因为即使内部 API 不是 REST,也会自动转换
把 Backstage 升级到新 release 时,推荐什么流程?
- 从头创建新应用,用它直接覆盖现有源码后部署
- 统一升级版本,并应用 upgrade helper 指出的变更,然后在本地确认能启动
- 只手工修改 package 文件中的版本字符串
- 只更换容器镜像 tag 并重新部署
启用 permission framework 后,实际决定的是什么?
- 用户可通过哪个认证提供方登录
- 后端在哪个端口接收请求
- catalog 数据保存在哪个数据库
- 特定用户能否对特定 entity 或操作发起请求
catalog 中 Location entity 的作用是什么?
- 指向其他 entity 定义所在位置,让 catalog 从中读取
- 记录 entity 部署所在的物理数据中心
- 指定文档所在 bucket 路径
- 表示用户所属办公室
在配置文件的 location 列表中填写 URL 的静态注册方式,有什么特性?
- 从门户页面删除后,配置文件中的条目也会消失
- 配置文件是来源,因此即使从页面删除,下次采集时还会重新出现
- 静态注册只支持 Component,不支持 API
- 静态 location 不受处理周期影响,只读取一次
annotation backstage.io/managed-by-location 表示什么?
- 负责 entity 的团队联系方式
- entity 部署到的 Kubernetes namespace
- entity 最后更新时间
- 该 entity 定义被读取自何处
注册仓库中的 entity 没有显示,哪种诊断最高效?
- 初始化数据库并重启后端
- 重新构建前端 bundle
- 查看该 location 的处理错误,并检查 manifest schema 与访问权限
- 改名后重新注册 entity
关于 entity 的 name 字段约束,哪项正确?
- 只能使用小写字母、数字和少数分隔符,并且有长度上限
- 可直接写包含空格、便于人阅读的句子
- 必须至少包含一个大写字母
- 必须把 namespace 写作前缀
catalog 中的关系是如何生成的?
- processor 解析 entity 的 spec 字段,生成双向关系
- 管理员必须在页面上手工连接两个 entity
- 必须另建专门的关系 entity 类型
- 必须直接向数据库关系表插入记录
数据库或对象存储等服务所依赖基础设施,应使用哪种 entity?
- System entity
- Domain entity
- Resource entity
- Location entity
在 Component 定义中声明依赖某个 Resource 后会发生什么?
- 该资源会自动 provision
- entity 页面会显示连接字符串
- 如果 Resource 尚不存在,entity 注册会被拒绝
- 两个 entity 之间会建立依赖关系,可在彼此页面查看
自动扫描组织仓库并查找、注册 entity 定义文件的方式叫什么?
- 执行 scaffolder action
- 通过 entity provider 进行 discovery
- 评估 permission policy
- 注册 proxy endpoint
仓库中的 entity 定义文件已删除,但 entity 仍存在,如何解释?
- 这是正常状态,重启后端后会消失
- 这是错误状态,会导致后端启动失败
- 它会标记为 orphan,并可按配置成为清理对象
- 它会进入 lock 状态,无法继续修改
指定 annotation backstage.io/source-location 的目的是什么?
- 让用户从 entity 页面直接跳转到实际源码位置
- 指定构建流水线下载源码的路径
- 指定文档 builder 查找文档源文件的路径
- 改变 catalog 读取 entity 定义的位置
为什么 catalog 会定期重新处理已注册的 entity?
- 为了重建数据库索引
- 为了反映原始 manifest 或引用目标的变化,保持 catalog 最新
- 为了重新签发 entity identifier
- 为了重新评估 permission policy
注册一个写有不存在 entity 类型的定义文件后会怎样?
- 未知类型仍会注册,页面显示为空
- 后端启动失败,整个门户停止
- 自动纠正为最相近的类型后注册
- 该 location 会记录处理错误,entity 不会注册
如何把新的前端插件接入应用?
- 安装插件包后 route 会自动添加
- 在后端注册插件后,前端也会同时生效
- 在 app package 中添加依赖,并在应用代码中显式连接 route 和 UI element
- 只需在配置文件中写插件名称
要给 entity 页面增加新 tab,通常修改哪里?
- 在 app package 的 entity 页面配置文件中添加 layout route
- 直接修改后端 catalog 插件源码
- 在 entity 定义文件中添加 tab 定义
- 给数据库 entity 表增加一列
只在具有特定 annotation 的 entity 上显示卡片,应怎么做?
- 为每种 annotation 创建独立的 entity 页面文件
- 卡片内发现缺少 annotation 时抛出错误
- 在后端过滤,只保留这类 entity
- 使用条件渲染机制,仅在 annotation 存在时绘制卡片
扩展 Backstage UI 时,为什么使用与 core 相同的 UI library?
- 因为只有该 library 支持 TypeScript
- 因为它与 core component 基于同一套体系,theme 和 style 能保持一致
- 因为使用它一定能减小 bundle 大小
- 因为系统禁止安装其他 UI library
如何让整个门户的颜色和 typography 符合公司品牌?
- 逐个修改各插件的 style 文件
- 创建 custom theme,注册到应用并重定义所需 palette 值
- 在配置文件的 organization 项中填写颜色代码
- 使用浏览器 extension 覆盖 style
前端 component 获取后端数据时,推荐哪种方式?
- 在 component 内直接生成 token 后发送请求
- 把响应存入 global variable 并持续复用
- 把后端地址写成源码常量后调用
- 从 API registry 获取 client,在 hook 中调用,并同时处理 loading 和 error 状态
向应用添加后端插件时需要做什么?
- 在 backend package 中把该插件注册到 backend instance
- 在前端 route 中添加页面 component
- 在 catalog 中注册为 Component entity
- 直接在数据库中创建插件表
把插件与外部服务通信的 client 注册为 factory,有什么好处?
- 减小 bundle,使首次加载更快
- 可以绕过后端直接调用
- 可替换 implementation,或在测试中换成 mock
- 无需配置也能自动发现服务地址
如何给 scaffolder 添加公司专用步骤?
- 创建 custom action,注册到 scaffolder 后端,再从 template 调用该 action
- 直接在 template 文件中写 shell script
- 由前端 component 直接执行该任务
- 把逻辑放入 catalog processor
要在 template 输入页面加入可从内部系统选择值的输入框,应怎么做?
- 在 schema 的 enum 中列出所有可能值
- 让用户自由输入,再由 action 验证
- 创建 custom field extension,并在 template 中使用该字段
- 只添加 proxy 配置,列表会自动出现
插件之间创建链接时,为什么使用 route reference 而不是路径字符串?
- 没有 route reference 时链接会在新 tab 打开
- 即使应用改变插件的实际挂载路径,链接也会跟随更新
- 只有 route reference 才会执行 permission check
- 路径字符串会在生产构建中被删除
测试 Backstage 前端 component 时,为什么使用测试应用 wrapper?
- 因为测试时必须启动真实后端
- 因为 wrapper 会自动生成 component 类型
- 因为没有 wrapper,测试 runner 无法解析 TypeScript
- 因为需要在测试中提供 component 所依赖的 API 和 routing context
希望为不同团队提供不同的门户首页,哪种方法合适?
- 按团队分别部署 Backstage 实例
- 在 entity 定义文件中写页面配置
- 让各团队把筛选页面保存为书签
- 在应用代码中组装首页卡片,并根据用户信息差异化渲染
如何把内部 wiki 文档纳入搜索结果?
- 在搜索页面添加一个跳转到 wiki 的链接
- 添加索引 wiki 文档的 collator,并为该结果类型加入显示 component
- 把所有 wiki 文档注册为 Component entity
- 通过 proxy 配置直接暴露 wiki search API
想改变 core component 的默认外观,最安全的方法是什么?
- 直接修改已安装 package 目录中的 core 源码
- 用 global style 覆盖 core 的 class name
- 使用 theme 的 component override 或公开 extension point
- fork core package 并发布到内部 registry
插件包中的开发目录有什么作用?
- 定义一个最小应用,可单独启动插件进行开发和检查
- 存放插件的生产构建产物
- 存放插件文档源文件
- 存放插件使用的数据库 migration
如何只允许 owner 团队删除 catalog entity?
- 在认证提供方中只允许这些用户登录
- 在 permission policy 中为该操作添加 ownership 条件
- 在前端隐藏 delete 按钮
- 撤销数据库用户的 delete 权限
在 entity 页面并排布置卡片,哪种方式合适?
- 组合 grid container 和 item,使列数随屏幕宽度变化
- 为每张卡片指定固定 pixel 宽度
- 用 table 标签包裹卡片进行布局
- 为每张卡片指定 absolute position
如何在多个 Backstage 实例间共享仅供内部使用的插件?
- 把文件复制到每个实例的源码中
- 把插件代码附加到 catalog entity
- 在配置文件中填写插件源码路径,运行时远程读取
- 构建为 package,发布到内部 registry,再由各应用作为依赖安装
大量修改应用代码后,为什么升级会变难,如何缓解?
- 升级会自动还原应用代码,因此只需备份
- 修改过的文件会被排除在升级之外,无需关注
- 修改点越分散,merge 成本越高,应尽量集中到独立 plugin 或 extension point
- 升级只改变依赖,与应用代码无关