多个应用服务器上的 MongoDB 连接失败

Posted

技术标签:

【中文标题】多个应用服务器上的 MongoDB 连接失败【英文标题】:MongoDB connection fails on multiple app servers 【发布时间】:2019-03-14 13:02:43 【问题描述】:

我们有用于 golang 的带有 mgo 驱动程序的 mongodb。除了应用程序(golang 二进制文件)之外,还有两个应用程序服务器连接到运行的 mongodb。 Mongodb 作为副本集运行,每个服务器根据副本的当前状态连接两个主要或辅助。

我们在其中一台 mongo 服务器上遇到了SocketException handling request, closing client connection: 9001 socket exception(这导致我们的应用程序与 mongodb 的连接中断。之后,副本集继续正常运行,但我们的第二台服务器(在该服务器上没有出现错误) t发生)连接也断开了。

在golang日志中表现为:

read tcp 10.10.0.5:37698-\u003e10.10.0.7:27017: i/o timeout

为什么会这样?如何预防?

据我了解,mgo 通过 url 连接到整个副本(它通过单个实例的 url 检测整个拓扑)但是为什么其中一台服务器上的连接在第二台服务器上死亡?

编辑:

    使用的完整包路径"gopkg.in/mgo.v2" 很遗憾,这里无法共享 mongo 文件。但除了 socketexecption mongo 日志不包含任何有用的东西。有迹象表明存在某种程度的锁争用,在某些时候锁获取时间相当长,但除此之外没有任何变化 MongoDB 有时会做一些繁重的索引,但最近没有任何异常的峰值,所以没有什么超出正常的

【问题讨论】:

能否分享 mongodb 日志文件和 mongostats(如果可能)?还请向我们展示您定义的套接字选项? 您使用的是哪个mgo 驱动程序?请发布您用于导入它的完整包路径。 你能检查一下你的连接是否在 mongodb 上做一些繁重的操作吗? @icza 在编辑中回答 @LarsHendriks 在编辑中 【参考方案1】:

首先,您正在使用的mgo 驱动程序:gopkg.in/mgo.v2 由 Gustavo Niemeyer 开发(托管在 https://github.com/go-mgo/mgo)不再维护。

改为使用社区支持的 fork github.com/globalsign/mgo。这个继续得到修补和发展。

其变更日志包括:“改进的连接处理”,这似乎与您的问题直接相关。

它的详细信息可以在这里阅读https://github.com/globalsign/mgo/pull/5,它指向原始拉取请求https://github.com/go-mgo/mgo/pull/437:

如果 mongoServer 无法拨号服务器,它将关闭所有活动的套接字,无论它们当前是否正在使用。 有两个缺点:

进行中的请求会被粗暴地打断。

所有套接字同时关闭,并且可能同时拨打服务器。海量拨号请求(高并发场景)中的任何偶然失败都会使所有套接字再次关闭,并重复......(发生在我们的生产环境中)

所以我认为当前使用的套接字应该在空闲后关闭。

请注意,github.com/globalsign/mgo 具有向后兼容的 API,它基本上只是添加了一些新的东西/功能(除了修复和补丁),这意味着您应该能够只更改导入路径并且所有应该都可以在没有的情况下工作进一步的变化。

【讨论】:

谢谢,这是我切换驱动程序的最初想法,因为我知道不再维护 mgo 驱动程序。但是,我想更好地了解问题的根本原因。我的一个想法是,因为 mgo 驱动程序直接连接到副本集并保持与主节点的连接,所以当主节点失败时它会失败。 @RuslanN globalsign/mgo 中有更多与连接相关的修复,我引用的似乎是问题/与您的问题直接相关。切换到globalsign/mgo 能解决您的问题吗?

以上是关于多个应用服务器上的 MongoDB 连接失败的主要内容,如果未能解决你的问题,请参考以下文章

mongoDB高级应用

在 Express.js 应用程序中打开多个 MongoDB 连接

在 Express.js 应用程序中打开多个 MongoDB 连接

如何在烧瓶中使用多个Mongodb

将css类上的日期选择器应用于多个输入元素但失败

MongoDB无法连接/认证失败