node.js - 在 Express 路由中检测 Mongoose/MongoDB 错误而不是 Mongoose.connect 回调
问题描述
我们的许多运行 Express/Node.js 的系统已经实现了一个/healthcheck
端点,我们的负载均衡器和其他监控系统可以监视该端点,以检测我们的一个应用程序何时出现问题。基本上,端点检查与应用程序具有的所有下游依赖项的连接,包括 MongoDB。
这个问题是,当/healthcheck
端点尝试运行它的测试事务并且它失败时,没有明显的方法来捕获端点中的错误,以便我可以让它报告 MongoDB 依赖项有问题。相反,服务器会为请求抛出 500 错误/healthcheck
(虽然仍然可以检测为问题,但没有那么有用)。
这段代码基本上显示了我们在做什么。它不完整且可运行,但具有 Mongoose 经验的 Express 用户应该很容易识别它。
const mongoose = require('mongoose')
const Schema = mongoose.Schema
const HealthcheckSchema = new Schema({
widget: {
type: String,
required: true,
unique: false,
},
createdAt: Date,
})
const HealthCheck = mongoose.model('Healthcheck', HealthcheckSchema, 'healthcheck')
const mongoCheck = () => Healthcheck.remove({}).exec()
.then(() => Healthcheck.create({widget: 'xyzpdq'}))
.then((results) => Healthcheck.findOne({widget: results.widget}).exec())
.then(() => true)
.catch(() => false)
const healthCheckEndpoint = (req, res) => {
let status = {}
Promise.all([mongoCheck()]) // normally there are other checks as well
.then(function (values) {
status.mongoUp = values[0]
return res.status(200).json(status) // always return 200; the payload gives the health status, not the HTTP status code
})
}
app.get('/healthcheck', healthCheckEndpoint)
在应用程序的主要设置中,不特定于健康检查,我们使用mongoose.connect()
回调。我们有各种状态的事件处理程序,比如disconnected
和error
等等,这些事件被捕获,但这无助于在/healthcheck
端点中获得正确的状态。
我想我可以使用这些事件处理程序来设置 /healthcheck 可以接收并返回的状态,但我真的更喜欢进行实际查询并使用它的成功/失败作为结果。
解决方案
这一切都变成了一个红鲱鱼。/healthcheck
这里的问题是在到达端点之前有一个 Express 中间件层正在使用 Mongo 。
在这种情况下,它是一个 Mongo 会话管理器。
解决方案是从会话中间件中排除/healthcheck
URL。
function excludeSessionsForStaticURLs (req, res, next) {
if (!new RegExp(/\/about|\/api\/heartbeat|\/healthcheck|\.css|\.js|\.jpg|\.png'/)
.test(req.originalUrl)) {
return sessionMiddleware(req, res, next)
}
return next()
}
app.use(excludeSessionsForStaticURLs)
因此,既然这个排除已经到位,Promises 的正常 try/catch (async/await) 和 .catch() 可以正常工作,并且 Mongo 的状态在适当的时候反映为 False。
推荐阅读
- checkbox - 使用复选框创建树视图
- sql-server - 隐式转换 - SQL
- wpf - 如何添加 Microsoft Edge WebView2 运行时作为先决条件
- php - 多行,一个 INSERT INTO
- java - Spring为什么要改变异常的类型
- node.js - NestJs mongoose pre hooks 没有触发
- c++ - 数据成员应该写在构造函数的初始化列表中吗?数组和向量的不同实现?
- django - 如何从父表单开始创建 Django 外键模型实例?
- java - java中不重复的随机数
- python - 尝试在 ECC 上添加两个点,但第三个点始终不在曲线上