设为首页 收藏本站
查看: 808|回复: 0

[经验分享] 在测试Adhesive的时候发现一个Mongodb官方驱动1.1.0.4184比较严重的BUG

[复制链接]

尚未签到

发表于 2015-7-6 09:27:16 | 显示全部楼层 |阅读模式
  在测试Adhesive的时候发现,使用过一段时间后台之后,就会不能连接到数据库,查看日志发现报的错误大致是
  connection refused because too many open connections: 819
  通过mongostat查看连接数的确很夸张有近819个连接,尝试在启动的时候指定最大连接数到10000,重新启动Mongodb这个问题似乎解决了
  但是在刷新几下页面之后连接数串到了4000,以前在使用的过程中即使在线上非常大的压力情况下连接数也在50之内,几千的连接数还是第一次见到
  首先想是不是程序问题引起的,因为在程序中我们的折线图一次需要进行100次左右的Count操作来得到每一个点的总数:
DSC0000.png
  虽然在程序中使用了并行库但是在只有一条折线的情况下是单线程的,因此排除并行库问题
  而且发现每一次刷页面连接数都会大幅上涨,根本没有回落的时候
  这想到了是连接没有释放,经过查看官方文档知道并不需要在每次调用之后显式释放连接
  写了一个最简单的程序来测试:
      static MongoServer server = MongoDB.Driver.MongoServer.Create("mongodb://192.168.129.172:20000/?slaveok=true");
static void Main(string[] args)
{
while (true)
{
Console.ReadLine();
var db = server.GetDatabase("qqtest");
var col = db.GetCollection("test");
try
{
Console.WriteLine(col.Count());
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
  很明显,按一次回车,连接数涨1!但是奇怪的是,写入数据的Master却不会有这个问题,于是把连接字符串修改为Master的地址
  mongodb://192.168.129.142:20000/
  居然正常了,不管怎么按回车,或是循环几百次连接始终只增加了一个,说明连接复用了
  至此,肯定是连接Slave的时候才会有这个问题,这问题也算是隐蔽。
  当时的这个版本是直接从NuGet引用的,没有源代码,于是下载到1.1.0.4184的源代码调试
  在调试后发现MongoServer.cs其中有一个方法:

private void InstanceStateChanged(
object sender,
object args
) {
lock (instances) {
if (instances.Any(i => i.State == MongoServerState.Connected && i.IsPrimary)) {
// Console.WriteLine("Server state: Connected");
state = MongoServerState.Connected;
return;
}
if (settings.SlaveOk) {
if (instances.Any(i => i.State == MongoServerState.Connected && (i.IsSecondary || i.IsPassive))) {
// Console.WriteLine("Server state: Connected");
state = MongoServerState.Connected;
return;
}
}
if (instances.Any(i => i.State == MongoServerState.Connecting)) {
// Console.WriteLine("Server state: Connecting");
state = MongoServerState.Connecting;
return;
}
// Console.WriteLine("Server state: Disconnected");
state = MongoServerState.Disconnected;
}
}
  把注释语句去掉,看看运行的情况:
DSC0001.png
  这个方法中会根据连接状态改变来改变服务器的状态,在连接上数据库之后,由于SlaveOk进入了黑体的语句,instances其中已经有一个状态是Connected的项了,但是由于i又不是IsSecondary也不是IsPassive,因此不能满足条件,直接变为了state = MongoServerState.Disconnected。也就是对于SlaveOk每次都是不能认为数据库已连接,每次都是重新连接!从图中可以看到,每次最后都转到了state = MongoServerState.Disconnected,其实应该是运行state = MongoServerState.Connected。我想这里作者的意思大概是为了增加一个SlaveOk的判断吧,而对于Slave的情况,IsSecondary和IsPassive都为false的,那么我把黑体代码改为如下:

if (instances.Any(i => i.State == MongoServerState.Connected && (!i.IsPrimary))) {
  再运行程序,发现这个问题解决了。。。再来看看运行情况:
DSC0002.png
  这次就对了,在进行一次连接之后,后面的请求都没有再初始化一个连接
  
  想到是否可以更新下客户端看看最新的客户端版本是否解决了这个问题,去官网下载了最新的1.3版本,发现没有了这个问题。那么我想看看作者是怎么修改的,查看这个文件的历史,在某一个历史中看到了这段代码的改动记录:
DSC0003.png
DSC0004.png
  可以看到原先的这段判断被删除了,这下思路清晰很多了!直接进行对应状态的设置,SlaveOk的判断和状态的设置不在有关系。
  分享此次排查问题的过程,抛砖引玉,提醒下大家在使用开源组件的时候需要小心测试。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-83668-1-1.html 上篇帖子: Mongodb集群配置(sharding with replica set) 下篇帖子: MongoDB 之 Find查询
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表