-
-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Health / liveness check for Worker #994
Comments
Just to add, as a use case for which we'd benefit of the worker listening to HTTP requests, the need for it to receive a "push" request to perform jobs. This is needed, for example, when running the worker in a serverless environment, where it is not guaranteed to run continuously but must be "awaken" with an HTTP request. |
One non-http way to implement this would be to create a simple job on health status request, not only it would show if the worker is alive or dead, it would also show how busy it is at the moment based on how long it took to complete the job. |
Some suggestions from the NestJS discord: tak1n — Yesterday at 10:30 AM
BrunnerLivio — Yesterday at 6:47 PM
|
Ran a few performance tests comparing the difference between bootstrapping the worker as a standalone app (the way we currently do it) vs as a full-blown Nest server including http layer. I also created a new WorkerModule which is just the same as the AppModule but omits the ApiModule import, since we would not need that for the worker. The code looks like this (irrelevant parts elided): export async function bootstrapWorker(
userConfig: Partial<VendureConfig>,
): Promise<{ app: INestApplicationContext; startJobQueue: () => Promise<void> }> {
const mode: 'standalone' | 'server' = 'standalone';
const module: 'app' | 'worker' = 'worker';
console.time('bootstrap');
// ...
let workerApp: INestApplication | INestApplicationContext;
let moduleClass: any;
if (module === 'app') {
const appModule = await import('./app.module');
moduleClass = appModule.AppModule;
} else {
const workerModule = await import('./worker.module');
moduleClass = workerModule.WorkerModule;
}
if (mode === 'standalone') {
const appModule = await import('./app.module');
workerApp = await NestFactory.createApplicationContext(moduleClass, {
logger: new Logger(),
});
} else {
const workerModule = await import('./worker.module');
workerApp = await NestFactory.create(moduleClass, {
logger: new Logger(),
});
await (workerApp as any).listen(config.apiOptions.port + 1, config.apiOptions.hostname);
}
// ...
console.log(
`Mode: ${mode}, module: ${moduleClass.name} - The script uses approximately ${
Math.round(used * 100) / 100
} MB`,
);
console.timeEnd('bootstrap');
return { app: workerApp, startJobQueue };
} Here are the results (3 runs of each): standalone with AppModule (status quo)
server with AppModule
standalone with WorkerModule
server with WorkerModule
ConclusionMy intuition that bootstrapping a full server is much heavier than a standalone app is not correct. The main overhead is the So it looks perfectly viable to bootstrap the worker as a full NestJS server app, which will give us an HTTP layer we can use for the health check and at the same time reduce startup time by a factor of ~4-5x, (2s down to 400ms) which is also very helpful for the serverless use-case! API proposalWhen bootstrapping the worker as a Nest server, we need to provide a post & hostname. I propose adding an optional 2nd argument to the Health ChecksStill to be solved is how to enable a health check indicator for the worker in the Admin UI using the existing
Perhaps we can have an endpoint on the server than can be called to register a worker? Need to think more about this one. |
Thanks for this improvement, just wanted to understand if this new feature is usable also to let the worker listen to incoming (REST) push requests regarding the tasks to perform, as for the use case I mentioned in my comment above |
@artcoded-dev This change will allow the worker to listen for HTTP requests like this: bootstrapWorker(config)
.then(worker => worker.startJobQueue())
.then(worker => worker.startHealthCheckServer({ port: 3020 }))
.catch(err => {
console.log(err);
});
If your use-case requires some other kind of http endpoint, please provide more details. |
Is your feature request related to a problem? Please describe.
Since shifting to the standalone NestJS architecture for the worker in v1.0, we've lost the ability to use the
HealthCheckRegistryService
to monitor the health of worker processes.There is also no easy way to do a liveness check for things like kubernetes deployments of the worker process.
Since the worker no longer has a networking layer, we cannot just add an HTTP endpoint, which is the usual way of handling it.
Describe the solution you'd like
Some way to support both the internal
HealthCheckRegistryService
checks (so it appears in the Admin UI) and also support for a generic liveness check.Describe alternatives you've considered
Some ideas:
The text was updated successfully, but these errors were encountered: