重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
作者:伍旭飞,腾讯云数据库高级工程师,主要负责腾讯云Redis、MongoDB开发。
在官渡等地区,都构建了全面的区域性战略布局,加强发展的系统性、市场前瞻性、产品创新能力,以专注、极致的服务理念,为客户提供成都做网站、成都网站设计 网站设计制作按需定制开发,公司网站建设,企业网站建设,品牌网站建设,营销型网站建设,成都外贸网站建设,官渡网站建设费用合理。故事从一个MongoDB数据库连接超时案例说起。该异常导致2次合服失败,前面已在服务器上抓包并dump下来,下方是客户端超时现场截图:
从截图不难看出,这是一个Nodejs服务出错信息,推测DBA应该是用的nodejs mongodb来实现连接数据库并进行操作,找到这个driver的官网 https:// -mongodb-native ,clone了一份代码下来。简单看了下,再结合上图,初步分析出错连接是在第38个连接超时的。
由于前面已经在出错服务器上抓包了,因此,首先我用wireShark打开从服务器上dump下来的文件,wireShark很智能,能分析多种常用协议,很方便,但是也容易带来误判。比如我们的数据库连接很多地方都被误判为X11协议:
一开始很纠结这个错误,其实这当然不是什么x11协议,只是碰巧模式匹配上了,到wireShark设置了下,取消了X11的分析,很容易从端口和连接看出,就是数据库连接。
仔细检查了抓包内容,大致如下:
(1)开始有个连接从数据库拉取了大概3M多的数据。
(2)后面陆续有常规的三次握手连接建立成功,但是都基本没有实质性的数据传输,就走了正常的tcp结束流程了。
(3)从抓包内容来看,服务器不存在未回应客户端syn连接包的情况。
好了,到这里分析的内容,似乎完全解释不了为什么会超时,那么下一步就是和用户沟通,获取更多的信息了。
(4)所有的tcp链接均为客户端发起FIN主动关闭,不存在服务器主动关闭客户端连接的情况。
通过沟通,拿到了出错部分工具的代码片段(最开始没有完整的函数,后面才拿到完整函数):
function merge_union_info(dbs) { var union_data = []; async.each( dbs, function(path, cb) { mongodb.connect(path, (err, db) => { if (err) { cb(err); return } db.collection('union').find().sort({level: -1, exp: -1}).toArray((err1, v) => { if (err1) { db.close(); console.log(err1); return } let loop = v.length > 50 ? 50 : v.length; let u_data = []; for (let i = 0; i < loop; i++) { v[i].merge_flag = 1; u_data.push(v[i]); } union_data.push(u_data); db.close(); cb(); }); }) }, function(err) { if (err) { console.log("[ERROR]merge union-data failed !!!"); return } async.waterfall([ function(cb1) { mongodb.connect(dbs[0], (err1, db) => { if (err1) { cb1(`[ERROR]gen union-data [drop] failed for ${err1}`) return } var col = db.collection('union'); db.collection('union').drop((err2, r2) => { db.close(); cb1(err2); }); }); }, function(cb1) { async.each( union_data, function(u_data, cb2) { mongodb.connect(dbs[0], (err1, db) => { if (err1) { cb2(`[ERROR]gen union-data [insert] failed for ${err1}`) return } var col = db.collection('union'); col.insertMany(u_data, (err2, r2) => { db.close(); cb2(err2); }); }); }, function(errN) { cb1(errN); } ); }, ], function(errX, r) { if (errX) { console.log("[ERROR]gen union-data failed for ", errX); }else { console.log("4 - update union-data ok !!!"); } }); } ); }