[RFC] egg readiness 改造
- Dominant language
- TypeScript
- Stars
- 19k
- Forks
- 1.8k
- PR merge metrics
- No merged PRs in 30d
Description
# 背景
## readiness 定义
>https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/
liveness: The kubelet uses liveness probes to know when to restart a Container. For example, liveness probes could catch a deadlock, where an application is running, but unable to make progress. Restarting a Container in such a state can help to make the application more available despite bugs.
readiness: The kubelet uses readiness probes to know when a Container is ready to start accepting traffic. A Pod is considered ready when all of its Containers are ready. One use of this signal is to control which Pods are used as backends for Services. When a Pod is not ready, it is removed from Service load balancers.
简单来说 liveness 代表应用是不是挂了,readiness 代表应用是不是可访问的。
# 启动
## 启动依赖
目前 egg 使用 ready 来代表插件是否启动完成,应用是否启动完成。目前在插件依赖关系复杂的情况下,应用启动时间很长。原因是不管什么插件,是否是弱依赖的,都需要准备完成。而事实上是部分插件在不 ready 的情况下应用也应该是可访问的。
举个例子:有个缓存插件,会阻塞应用启动。但是业务场景是无缓存的时候可以 fallback 到 db 去。
```js
// cache-plugin
// app.js
module.exports = () => {
app.beforeStart(async () => {
await app.cache.ready();
});
};
// cache.js
module.exports = app => {
return class Cache extends Base {
async _init() {
await app.cacheConn.ready();
}
async fetchCache(key) {
return app.cacheConn.get(key);
}
}
};
```
可以做如下修改,在弱依赖的时候,不阻塞应用的启动。
```js
// config.default.js
module.exports = {
const config = {
cache: {
dependency: false,
},
};
return config;
};
// sdk-base.js
...
async ready() {
if (this.options.dependency === false) {
return true;
}
...
}
get isReady() {
...
}
...
// cache.js
module.exports = app => {
return class Cache extends Base {
async _init() {
await app.cacheConn.ready();
}
async fetchCache(key) {
return app.cacheConn.isReady && app.cacheConn.get(key);
}
}
};
```
## 启动过程
目前的启动过程是,master 会去监听 cluster 的 listening 事件,在 worker 监听了正确的端口之后,就会认为启动是完成了。
按照 liveness 和 readiness,应该是 worker 在启动时候就要开始监听端口,liveness 是通了,然后会去访问 worker 的 readiness 接口判断是否 ready 了。
但是受限于 node 的多进程模型,可能 worker 进程的状态是不一致的,所以需要 master 进程对状态做聚合。
- master 进程存活,则 liveness 是通的
- 有一个 worker 进程不是 readiness 的,则 readiness 就是不通的
# 访问
> Readiness probes runs on the container during its whole lifecycle.
目前的 ready 在应用启动完成之后就没有用了,但是 readiness 是在整个生命周期中都是会调用的。所以 ready 接口在插件、应用的状态发生改变之后,也需要做出变化,体现在 readiness 的返回结果上。
cc: @eggjs/core
Contributor guide
Assessment
This issue has not been assessed yet.