后端应用程序贡献
后端应用程序贡献允许 Eclipse Theia 扩展连接到 Theia 后端的生命周期。 后端应用程序贡献在启动后端应用程序后立即实例化。所以如果一个服务在整个生命周期都需要被用到,就非常适合使用后端应用程序贡献来实现。
要注册后端应用程序贡献,扩展需要在后端模块中绑定接口 BackendApplicationContribution 的实现。
export default new ContainerModule(bind => { bind(MemoryTracker).toSelf().inSingletonScope(); bind(BackendApplicationContribution).toService(MemoryTracker); });
BackendApplicationContribution 接口提供了钩子,这些钩子都是可选的,因此实现可以自由选择他们感兴趣的钩子中的哪一个,而不必实现其他钩子。对于后端服务的初始化,最常见的钩子是在 Theia 后端初始化后立即调用的 initialize() 方法。
例如,让我们实现一个后端服务,该服务将在 Theia 后端的整个生命周期内运行,以跟踪其内存使用情况。为了简单起见,只要它的变化超过某个阈值,它就会将内存打印到日志中。
因此,一个名为 MemoryTracker 的 BackendApplicationContribution 绑定在依赖注入上下文中,如上面的代码所示。 MemoryTracker 的实现对钩子 initialize() 做出反应,并每两秒定期执行方法 logMemory()。此方法获取当前使用的内存,将其与之前的内存进行比较,并在与之前的内存的差异超过 0.1 MB 时将消息打印到日志中。
@injectable() export class MemoryTracker implements BackendApplicationContribution { @inject(ILogger) protected readonly logger: ILogger; protected logTimer: NodeJS.Timer; protected memoryUsed = 0; initialize(): MaybePromise<void> { this.logTimer = setInterval(() => this.logMemory(), 2000); } protected logMemory(): void { const currentMemoryUsed = this.currentRoundedMemoryUsage(); const diff = currentMemoryUsed - this.memoryUsed; if (Math.abs(diff) > 0.1) { const timestamp = new Date().toUTCString(); this.logger.info( `[${timestamp}] PID ${process.pid} uses ${currentMemoryUsed} MB (${diff > 0 ? '+' : ''}${diff.toFixed(2)})` ); this.memoryUsed = currentMemoryUsed; } } protected currentRoundedMemoryUsage() { return Math.round(process.memoryUsage().heapUsed / 1024 / 1024 * 100) / 100; } onStop(): void { if (this.logTimer) { clearInterval(this.logTimer); } } }
一旦注册了此后端应用程序贡献并启动了后端,它就会开始记录输出,类似于以下内容:
root INFO Theia app listening on http://localhost:3000. root INFO Configuration directory URI: 'file:///home/foobar/.theia' root INFO [Fri, 20 Aug 2021 12:20:43 GMT] PID 46590 uses 18.14 MB (+18.14) root INFO [Fri, 20 Aug 2021 12:20:47 GMT] PID 46590 uses 18.94 MB (+0.80) root INFO [Fri, 20 Aug 2021 12:20:51 GMT] PID 46590 uses 15.25 MB (-3.69) root INFO [Fri, 20 Aug 2021 12:21:07 GMT] PID 46590 uses 15.36 MB (+0.11) root INFO [Fri, 20 Aug 2021 12:21:21 GMT] PID 46590 uses 15.47 MB (+0.11) root INFO [Fri, 20 Aug 2021 12:21:41 GMT] PID 46590 uses 15.6 MB (+0.13) root INFO [Fri, 20 Aug 2021 12:21:59 GMT] PID 46590 uses 15.71 MB (+0.11)
通常,此类后端应用程序贡献还提供可由其他后端服务调用的方法,例如,需要在应用程序启动后,立即可用的外部进程。 如数据库连接、REST 服务等。
除了在后端启动时就初始化后端服务,后端应用贡献还可以配置和扩展 Theia 后端使用的 HTTP 服务器。 因此BackendApplicationContribution接口提供了三个方法configure(app: express.Application), onStart(app: express.Application), and onStop(app: express.Application)。 可以使用自定义设置配置 HTTP 服务器,甚至可以扩展的其他endpoints。(endpoints其实就是增加一个新的url路由)
下面给出了一个配置名为 /myendpoint 的endpoints的示例。
import { injectable } from '@theia/core/shared/inversify'; import { json } from 'body-parser'; import { Application, Router } from '@theia/core/shared/express'; import { BackendApplicationContribution } from '@theia/core/lib/node/backend-application'; @injectable() export class MyCustomEndpoint implements BackendApplicationContribution { configure(app: Application): void { app.get('/myendpoint', (request, response) => { … }); } }
有关如何配置 HTTP 端点和处理事件请求的更多信息,请参阅 Express API。(https://expressjs.com/en/4x/api.html)