首页 > 解决方案 > 在 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()回调。我们有各种状态的事件处理程序,比如disconnectederror等等,这些事件被捕获,但这无助于在/healthcheck端点中获得正确的状态。

我想我可以使用这些事件处理程序来设置 /healthcheck 可以接收并返回的状态,但我真的更喜欢进行实际查询并使用它的成功/失败作为结果。

标签: node.jsmongodbmongoose

解决方案


这一切都变成了一个红鲱鱼。/healthcheck这里的问题是在到达端点之前有一个 Express 中间件层正在使用 Mongo 。

在这种情况下,它是一个 Mongo 会话管理器。

解决方案是从会话中间件中排除/healthcheckURL。

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。


推荐阅读