作者:伍旭飛,騰訊云數(shù)據(jù)庫高級工程師,主要負(fù)責(zé)騰訊云Redis、MongoDB開發(fā)。
在官渡等地區(qū),都構(gòu)建了全面的區(qū)域性戰(zhàn)略布局,加強(qiáng)發(fā)展的系統(tǒng)性、市場前瞻性、產(chǎn)品創(chuàng)新能力,以專注、極致的服務(wù)理念,為客戶提供成都做網(wǎng)站、成都網(wǎng)站設(shè)計(jì) 網(wǎng)站設(shè)計(jì)制作按需定制開發(fā),公司網(wǎng)站建設(shè),企業(yè)網(wǎng)站建設(shè),品牌網(wǎng)站建設(shè),營銷型網(wǎng)站建設(shè),成都外貿(mào)網(wǎng)站建設(shè),官渡網(wǎng)站建設(shè)費(fèi)用合理。故事從一個MongoDB數(shù)據(jù)庫連接超時(shí)案例說起。該異常導(dǎo)致2次合服失敗,前面已在服務(wù)器上抓包并dump下來,下方是客戶端超時(shí)現(xiàn)場截圖:
從截圖不難看出,這是一個Nodejs服務(wù)出錯信息,推測DBA應(yīng)該是用的nodejs mongodb來實(shí)現(xiàn)連接數(shù)據(jù)庫并進(jìn)行操作,找到這個driver的官網(wǎng) https:// -mongodb-native ,clone了一份代碼下來。簡單看了下,再結(jié)合上圖,初步分析出錯連接是在第38個連接超時(shí)的。
由于前面已經(jīng)在出錯服務(wù)器上抓包了,因此,首先我用wireShark打開從服務(wù)器上dump下來的文件,wireShark很智能,能分析多種常用協(xié)議,很方便,但是也容易帶來誤判。比如我們的數(shù)據(jù)庫連接很多地方都被誤判為X11協(xié)議:
一開始很糾結(jié)這個錯誤,其實(shí)這當(dāng)然不是什么x11協(xié)議,只是碰巧模式匹配上了,到wireShark設(shè)置了下,取消了X11的分析,很容易從端口和連接看出,就是數(shù)據(jù)庫連接。
仔細(xì)檢查了抓包內(nèi)容,大致如下:
(1)開始有個連接從數(shù)據(jù)庫拉取了大概3M多的數(shù)據(jù)。
(2)后面陸續(xù)有常規(guī)的三次握手連接建立成功,但是都基本沒有實(shí)質(zhì)性的數(shù)據(jù)傳輸,就走了正常的tcp結(jié)束流程了。
(3)從抓包內(nèi)容來看,服務(wù)器不存在未回應(yīng)客戶端syn連接包的情況。
好了,到這里分析的內(nèi)容,似乎完全解釋不了為什么會超時(shí),那么下一步就是和用戶溝通,獲取更多的信息了。
(4)所有的tcp鏈接均為客戶端發(fā)起FIN主動關(guān)閉,不存在服務(wù)器主動關(guān)閉客戶端連接的情況。
通過溝通,拿到了出錯部分工具的代碼片段(最開始沒有完整的函數(shù),后面才拿到完整函數(shù)):
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 !!!"); } }); } ); }