DingMing

丁大铭的个人空间,用来分享一些前端小技巧,默默成长吧,哈哈

项目优化复盘Mongoose

  |  
 阅读次数

序言

这不年底了,得更细一下技术博客了,年终总结什么的目前暂无打算,记录一下、前一段优化mongoose问题,顺带记录一下自己的了解,继续提升自己技能宽度…

问题 目前的node项目接口访问数据库10s后会自动超时

我想延长数据库访问链接时间,差了网上很多关于Mongoose的文档,结果介绍的都很入门,不能满足我目前的需求。

所以我决定苦读 官方文档

其实解决这个问题只需要添加几个选项设置就好,对于了解的人当然不在话下,但是对于开拓者来说还是比较困难的,需要一遍遍的设置、重启、调试、修改

接下来我细细复盘我的优化之路

问题定位

好在我之前在项目中加入了一些列的操作日志,进行了接口监控 之前的文章->(Koa2+Log4js+PM2持久化日志及使用问题)

了解了具体接口的报错,那就能着手进行dome的调试,定位问题点,发现接口访问超过10s就会报500的错误。

了解http code码的同学应该清楚,500+ 证明访问就没有进来(同时我查看了全局没有500的报错封装)。

我第一反应是,我是不是引用的中间件 拦截报出的错误,我开始查看 koa-onerror 项目文档,发现没有相关介绍,然后我就看是尝试读源码,看看他是怎么拦截的,结果一桶忙碌下来,屁都没有发现,反而觉得人家分装的还不错(狗头)

然后我就进行断点调试,才发现卡在了mongoose这一步

知道问题点了,就全力解决吧

问题搜索与调试

随后,我就开始查阅网上的教程,结果都太基础了,也没有人出现我这同样的问题,还有人写 reconnectInterval(误人子弟呀,这个参数不存在的,千万不要用) 网上的文章他妈的都是复制粘贴的

被迫只能去查看官方文档,终于找到了我想要的参数

1
2
3
4
{
serverSelectionTimeoutMS: 20000,
heartbeatFrequencyMS: 20000,
}

但是我怎么尝试都会报错,提示参数无效!!! 我就有点摸不着头了。node_modules里不就有代码么,看源码!!!确实没有参数

原来是自己的npm包版本不够(好歹也是5.x.x呢),官网已经6+了 我们就升到6

经过了反复调试,终于设置好了符合这项目的参数,如下:

1
2
3
4
5
6
7
8
9
10
11
mongoose.set('strictQuery', false);

mongoose.connect(config.mongodb, {
useNewUrlParser: true,
useUnifiedTopology: true,
// reconnectInterval: 20 * 1000,
maxPoolSize: 10,
serverSelectionTimeoutMS: 20000,
heartbeatFrequencyMS: 20000,
family: 4,
});

总结

网络文章有的很不靠谱,让我误入歧途很久,当时让我很愤怒,为了解决问题看官方文档还是最靠谱的,本来想写 参数介绍的,结果写着写着,写成了优化复盘。哈哈 写文章就是这么的奇妙

mongoose connect 参数简单介绍

该connect方法还接受一个options将传递给底层 MongoDB 驱动程序的对象。

mongoose.connect(uri, options);

完整的选项列表可以在MongoDB-Node.js驱动程序文档 中找到MongoClientOptions。Mongoose 将选项不加修改地传递给驱动程序,模数下面解释的一些异常。

  • bufferCommands - 这是禁用Mongoose 缓冲机制的 mongoose 特定选项(未传递给 MongoDB 驱动程序)
  • user/ pass - 用于身份验证的用户名和密码。这些选项是特定于 Mongoose 的,它们等同于 MongoDB 驱动程序的auth.username和auth.password选项。
  • autoIndex - 默认情况下,猫鼬会在连接时自动构建在您的模式中定义的索引。这对于开发非常有用,但对于大型生产部署来说并不理想,因为索引构建会导致性能下降。如果设置autoIndex为 false,mongoose 将不会自动为与此连接关联的任何模型构建索引。
  • dbName - 指定要连接到哪个数据库并覆盖连接字符串中指定的任何数据库。如果您无法像某些mongodb+srv语法连接那样在连接字符串中指定默认数据库,这将很有用。

下面是一些对调整 Mongoose 很重要的选项。

  • promiseLibrary - 设置底层驱动程序的承诺库。
  • maxPoolSize - MongoDB 驱动程序将为该连接保持打开的最大套接字数。默认情况下,maxPoolSize是 100。请记住,MongoDB 一次只允许每个套接字执行一个操作,因此如果您发现有一些慢速查询正在阻止更快的查询继续进行,您可能需要增加此值。请参阅MongoDB 和 Node.js 中的慢速列车。maxPoolSize如果您遇到连接限制,您可能想要减少。
  • minPoolSize - MongoDB 驱动程序将为该连接保持打开的最小套接字数。MongoDB 驱动程序可能会关闭一段时间不活动的套接字。minPoolSize如果您希望您的应用程序经历较长的空闲时间并希望确保您的套接字保持打开状态以避免在活动开始时运行缓慢,则可能需要增加。
  • socketTimeoutMS - 由于初始连接后 不活动,MongoDB 驱动程序在终止套接字之前将等待多长时间。由于没有活动或长时间运行的操作,套接字可能处于非活动状态。这是30000默认设置,如果您希望某些数据库操作的运行时间超过 20 秒,则应将其设置为最长运行操作的 2-3 倍。在 MongoDB 驱动程序成功完成后,此选项将传递给Node.jssocket#setTimeout()函数。
  • family - 是使用 IPv4 还是 IPv6 进行连接。此选项传递给Node.js 的dns.lookup()函数。如果不指定此选项,MongoDB 驱动程序将首先尝试 IPv6,然后在 IPv6 失败时尝试 IPv4。如果您的mongoose.connect(uri)通话时间较长,请尝试mongoose.connect(uri, { family: 4 })
  • authSourceuser - 使用和 进行身份验证时要使用的数据库pass。在 MongoDB 中,用户被限定在一个数据库中。如果您遇到意外的登录失败,您可能需要设置此选项。
  • serverSelectionTimeoutMS - MongoDB 驱动程序将尝试找到一个服务器来发送任何给定的操作,并持续重试serverSelectionTimeoutMS几毫秒。如果未设置,MongoDB 驱动程序默认使用30000(30 秒)。
  • heartbeatFrequencyMS - MongoDB 驱动程序每隔一段时间发送一次心跳heartbeatFrequencyMS以检查连接状态。心跳受制于serverSelectionTimeoutMS,因此 MongoDB 驱动程序默认会重试失败的心跳最多 30 秒。Mongoose 仅​​在心跳失败后才发出’disconnected’事件,因此您可能希望减少此设置以减少服务器关闭与 Mongoose 发出之间的时间’disconnected’。我们建议您不要将此设置设置为低于 1000,过多的心跳会导致性能下降。