node 集群與穩定

2022-06-08 22:45:15 字數 4856 閱讀 4612

node集群搭建好之後,還需要考慮一些細節問題。

node子程序物件除了send()方法和messge事件外,還有如下事件:

上述這些事件是在父程序能監聽到的與子程序相關的事件。除了send()外,還能通過kill()方法給子程序傳送訊息。kill()方法並不能真正的將通過ipc相連的子程序殺死,它只是給子程序傳送

了乙個系統訊號。預設情況下,父程序將通過kill()方法給子程序傳送乙個sigterm訊號。它與程序預設的kill()方法類似。

//

子程序child.kill([signal]);

//當前程序

process.kill(pid, [signal]);

有了父子程序之間的相關事件後,就可以在這些關係之間建立出需要的機機制了。監聽子程序的exit事件來獲知其退出的資訊,並在主程序中加入一些子程序管理的機制,比如重新啟用乙個

新的工作程序來繼續服務。

實現**如下所示:

master.js

var fork = require('child_process').fork;

var cpus = require('os').cpus();

var server = require('net').createserver();

server.listen(1337, () =>)

var workers ={};

var createworker = function

() )

//控制代碼**

worker.send('server', server);

workers[worker.pid] =worker;

console.log('create worker. pid: ' +worker.pid);

}for (var i = 0; i < cpus.length; i++)

//程序自己退出時,讓所有工作程序退出

})

上述**的處理流程是,一旦有未捕獲的異常出現,工作程序就會立即停止接收新的連線;當所有連線斷開後,退出程序。主程序在偵聽到工作程序的exit後,將會立即啟動新的程序服務,以此

保證整個集群中總是有程序在為使用者服務的。

上述**存在的問題是要等到所有連線斷開後程序才退出,在極端情況下,所有工作程序都停止接收新的連線,全處在等待退出的狀態。但在等到程序完全退出才重啟的過程中,所有新來的請求

可能存在沒有工作程序為新使用者服務的情景,這會丟掉大部分請求。

為此需要改進這個過程,不能等到工作程序退出後才重啟新的工作程序。當然也不能暴力退出程序,因為這樣會導致已連線的使用者直接斷開。於是在退出的流程中增加乙個自殺連線,當所有的連線斷開後才退出。主程序在接收到自殺訊號後,立即建立新的工作程序服務。**改動如下:

//

worker.js

process.on('uncaughtexception', () =>);

//停止接受新的連線

worker.close(() =>);

})//

master.js

var createworker = function

() });

//退出時重新啟動新的程序

worker.on('exit', () =>)

//控制代碼**

worker.send('server', server);

workers[worker.pid] =worker;

console.log('create worker. pid: ' +worker.pid);

}

至此我們完成了程序的平滑重啟,一旦有異常出現,主程序就會建立新的工作程序來為使用者服務,舊的程序一旦處理完了已有連線就自動斷開。整個過程使得我們的應用穩定性和健壯性大大提高。

這裡存在問題的是有可能我們的連線是長連線,不是http服務的這種短連線,等待長時間斷開可能需要較久的時間。為此為已有連線的斷開設定乙個超時時間是必要的,在限定時間裡強制退出。

//

worker.js

process.on('uncaughtexception', () =>);

//停止接受新的連線

worker.close(() =>);

//5秒後退出

settimeout(() =>, 5000)

})

程序中如果出現未能捕獲的異常,就意味著有那麼一段**在健壯性上是不合格的。為此退出程序前,通過日誌記錄下問題所在是必須要做的事情,它可以幫我們很好地定位和追蹤**異常出現的位置,如下所示:

process.on('uncaughtexception', (err) =>);

//停止接受新的連線

worker.close(() =>);

//5秒後退出

settimeout(() =>, 5000)

})

通過自殺訊號告知主程序可以使得新連線總是有程序服務,但是依然還是有極端的情況。工作程序不能無限制的被重啟,如果啟動的過程中就發生了錯誤,或者啟動後接到連線就收到錯誤,

會導致工作程序被頻繁重啟,這種頻繁重啟不屬於我們捕捉未知異常的情況,因為這種短時間內頻繁重啟已經不符合預期的設定,極有可能是程式編寫的錯誤。

為了消除這種無意義的重啟,在滿足一定規則的限制下,不應當反覆重啟。比如在單位時間內規定只能重啟多少次,超過限制就觸發giveup事件,告知放棄重啟工作程序這個重要事情。

為了完成限量重啟的統計,引入乙個佇列來做標記,在每次重啟工作程序之間進行打點並判斷重啟是否太過頻繁,如下所示:

var fork = require('child_process').fork;

var cpus = require('os').cpus();

var server = require('net').createserver();

server.listen(1337, () =>)

//重啟次數

var limit = 10;

//時間單位

var during = 60000;

var restart =;

var istoofrequently = function

()

//最後一次重啟到前10次重啟之間的時間間隔

return restart.length >= limit && restart[restart.length - 1] - restart[0]

}var workers ={};

var createworker = function

()

var worker = fork(__dirname + '/worker.js');

//啟動新的程序

worker.on('message', (message) =>

});//退出時重新啟動新的程序

worker.on('exit', () =>)

//控制代碼**

worker.send('server', server);

workers[worker.pid] =worker;

console.log('create worker. pid: ' +worker.pid);

}for (var i = 0; i < cpus.length; i++)

//程序自己退出時,讓所有工作程序退出

process.on('exit', () =>

})

giveup事件是比uncaughtexception更嚴重的異常事件。uncaughtexception只代表集群中某個工作程序退出,在整體性保證下,不會出現使用者得不到服務的情況,但是這個giveup事件則表示

集群中沒有任何程序服務了,十分危險。為了健壯性了考慮,我們應在giveup事件中新增重要日誌,並讓監控系統監視到這個嚴重錯誤,進而報警等。

在多程序之間監聽相同的介面,使得請求能夠分散到多個程序上進行處理,這帶來的好處是可以將cpu資源都呼叫起來。node預設提供的機制是採用作業系統的搶占式策略。所謂的搶占式就是

在一堆工作程序中,閒著的程序對到來的請求進行爭搶,誰搶到誰服務。

一般而言,這種搶占式策略對大家是公平的,各個程序可以根據自己的繁忙度來進行搶占。但是對於node而言,需要分清的是它的繁忙是有cpu、i/o兩個部分構成的,影響搶占的是cpu的繁忙度。對於不同的業務,可能存在i/o繁忙,而cpu較為空閒的情況,這可能造成某個程序能夠搶到較多請求,形成負載不均衡的情況。

為此node在v0.11中提供了一種新的策略使得負載均衡更合理,這種新的策略叫round-robin,又叫輪叫排程

。輪叫排程的工作方式是由主程序接受連線,將其一次分發給工作程序。分發的策略

是在n個工作程序中,每次選擇第i = ( i + 1 ) mod n個程序來傳送連線。

round-robin非常簡單,可以避免cpu和i/o繁忙差異導致的負載不均衡。round-robin策略也可以通過**服務來實現,但是它會導致伺服器上消耗的檔案描述符是平常方式的兩倍。

穩定與不穩定

1 氣泡排序 氣泡排序就是把小的元素往前調或者把大的元素往後調。比較是相鄰的兩個元素比較,交換也發生在這兩個元素之間。所以,如果兩個元素相等,我想你是不會再無聊地把他們倆交換一下的 如果兩個相等的元素沒有相鄰,那麼即使通過前面的兩兩交換把兩個相鄰起來,這時候也不會交換,所以相同元素的前後順序並沒有改...

穩定與不穩定排序

首先,排序演算法的穩定性大家應該都知道,通俗地講就是能保證排序前2個相等的數其在序列的前後位置順序和排序後它們兩個的前後位置順序相同。在簡單形式化一下,如果ai aj,ai原來在位置前,排序後ai還是要在aj位置前。其次,說一下穩定性的好處。排序演算法如果是穩定的,那麼從乙個鍵上排序,然後再從另乙個...

Etcd 集群穩定性測試記錄

2017年 5月 2日 集群節點個數 3個 集群節點環境 1.每秒新增資料,每3秒檢測一次集群狀態。2.每秒新增資料,每5秒禁用一次網絡卡,等待時間15秒。重新啟動網絡卡。3.每秒新增資料,每5秒禁用一次網絡卡,等待時間15秒。重新啟動網絡卡。測試結果如下 乙個小時後的測試資料 節點1,2,3均正常...