Skip to main content

调用现有的应用程序接口

本文介绍了 Backstage 前端插件在与已有的服务 API 通信时的各种选择。 下面的每一部分都介绍了一种可能的选择,以及在什么情况下适合这种选择。

在这些示例中,我们将最终从虚构的 FrobsCo API 中请求数据。

直接发出请求

最基本的选择是直接从插件前端代码向 FrobsCo 应用程序接口发出请求,例如使用fetch或支持库,如axios.

例如

// Inside your component
fetch('https://api.frobsco.com/v1/list')
.then(response => response.json())
.then(payload => setFrobs(payload as Frob[]));

在 Spotify 内部,这种选择并不常见。 第三方 API 有时也会这样访问。 只有少数内部 API 还费尽周折,以直接从浏览器使用的方式暴露自己,但即便如此,通常也不是从公共互联网访问,而是仅支持已在公司 VPN 上的用户。

可以在以下情况下使用

  • The API already does/exposes exactly what you need. * The request/response patterns of the API match real world usage needs in Backstage frontend plugins. For example, if the end use case is to show a small summary in Backstage, but the only available API endpoint gives a 30 megabyte blob with large amounts of redundant information, it would hurt the end user experience. Particularly on mobile. The same goes for cases where you want to show many individual pieces of information: if a common use case is to show large tables where one API request per cell is necessary, the browser will quickly become swamped and you may want to consider performing aggregation elsewhere instead. * The API can maintain interactive request/response times at your required peak request rates. The end user experience will be degraded if they spend a lot of time waiting for the data to arrive. * The API endpoint is highly available. The browser does not have builtin facilities for load balancing, service discovery, retries, health c

使用Backstage代理

Backstage 后端有一个可选的代理插件,可用于为下游 API 轻松添加代理路由。

例如

# In app-config.yaml
proxy:
'/frobs': http://api.frobsco.com/v1
// Inside your component
const backendUrl = config.getString('backend.baseUrl');
fetch(`${backendUrl}/api/proxy/frobs/list`)
.then(response => response.json())
.then(payload => setFrobs(payload as Frob[]));

代理由http-proxy-middleware包装代理配置选项的完整说明。

在 Spotify 内部,代理选项一直是最受插件制作者欢迎的选择。 由于我们拥有基于 DNS 的服务发现功能和微服务框架,暴露纯 HTTP 是轻而易举的事,因此只需添加几行Backstage配置,就能让用户的网络浏览器也能轻松、稳健地访问我们的服务。

在下列情况下,可以用这种方法代替直接请求:

  • 您需要执行 HTTPS 终止和/或 CORS 处理,因为应用程序接口本身并不提供这些功能。 您需要在请求中注入一个简单的静态Secret,例如在请求头中添加一个授权头。 您希望使用其他代理设施,例如重试、故障转移、健康检查、路由、请求记录、重写等。 您已经通过外围暴露了Backstage后端本身,并发现只需处理一个入口点,只用Backstage配置治理入口是非常实用的。

创建Backstage后端插件

与Backstage前端一样,Backstage后端也有一个插件系统。 上面提到的代理其实就是这样一个插件。 如果你需要更多的集成,而不仅仅是直接访问 FrobsCo API,或者需要保持状态,你可能会想要制作这样一个插件。

例如

// Inside your component
const backendUrl = config.getString('backend.baseUrl');
fetch(`${backendUrl}/frobs-aggregator/summary`)
.then(response => response.json())
.then(payload => setSummary(payload as FrobSummary));
// Inside a new frobs-aggregator backend plugin
router.use('/summary', async (req, res) => {
const agg = await Promise.all([
fetch('https://api.frobsco.com/v1/list'),
fetch('http://flerps.partnercompany.com:8080/flerp-batch'),
database.currentThunk(),
]).then(async ([frobs, flerps, thunk]) => {
return computeAggregate(await frobs.json(), await flerps.json(), thunk);
});
res.status(200).json(agg);
});

有关更详细的示例,请参阅light house插件在数据库中存储某些状态,并为底层应用程序接口添加新功能。

在 Spotify 内部,出于不同的原因,这一直是一个相当受欢迎的选择。 通常,后端被用作缓存和数据处理层,用于速度较慢的 API 或请求/响应形状或速度不适合前端直接使用的 API。 例如,这使得从前端发出高效的批量查询成为可能,例如,在大列表或表格中,想要从底层服务提供的较大列表中解析大量稀疏数据。

在下列情况下,可以用它来代替上述方法:

您需要执行复杂的模型转换或协议转换,这超出了代理所能处理的范围 * 您希望在后端而不是前端执行聚合或汇总 * 您希望启用批处理或缓存较慢或较不可靠的 API * 您需要为插件维护状态,或许可以使用后端内置的数据库支持 * 您需要注入Secret或以其他方式与 API 的其他部分或其他服务进行协商,以便执行您的工作 * 您希望代表 API 对操作执行最终用户身份验证/授权,并进行会话处理或类似操作 * 您希望在后端执行聚合或汇总 * 您希望在后端而不是前端执行聚合或汇总 * 您希望启用批处理或缓存较慢或较不可靠的 API * 您需要为插件维护状态,或许可以使用后端内置的数据库支持 * 您需要注入Secret或以其他方式与 API 的其他部分或其他服务进行协商,以便执行您的工作

什么时候应该为某个目的制作一个完全独立的后端,什么时候应该制作一个改编现有功能的Backstage插件,这两者之间需要取得平衡。 一般建议不好给出,但如果您有任何疑问,请在 Discord 上联系我们,我们或许可以提供指导。

扩展 GraphQL 模型

可扩展的 GraphQL 后端层尚未构建,届时将对本节进行扩展,敬请期待!