.net core高并发_高并发下的Node.js与负载均衡
閱讀本文約需要6分鐘
大家好,我是你們的導師,我每天都會在這里給大家分享一些干貨內容(當然了,周末也要允許老師休息一下哈)。上次老師跟大家分享了下淺談前端自動化構建的相關知識,今天跟大家分享淺談前端自動化構建的相關知識參考來源:https://www.cnblogs.com/tingshuo/archive/2013/01/17/2864280.html眾所周知,node.js基于v8引擎,所以它本身并不支持多線程(有多線程的Module哦),那么為了充分利用server的Multi-core,就必須使用多進程的方式。那么進程之間如何負載均衡就會是一個關鍵所在。
多進程共享監聽socket
Node.js與進程相關的模塊有process,child_process,cluster,這其中cluster用于方便的創建共享端口的多進程模式(The cluster module allows you to easily create a network of processes that all share server ports),這種模式使多個進程間共享一個監聽狀態的socket,并由系統將accept的connection分配給不同的子進程,而且實現起來也非常簡單,cluster為你做了大部分事情,這里有一個test case:
var cluster = require('cluster'); var http = require('http'); var numCPUs = require('os').cpus().length; if (cluster.isMaster) { // Fork workers. for (var i = 0; i < numCPUs; i++) { cluster.fork(); } cluster.on('exit', function(worker, code, signal) { console.log('worker ' + worker.process.pid + ' died'); }); } else { // Workers can share any TCP connection // In this case its a HTTP server http.createServer(function(req, res) { res.writeHead(200); res.end("hello world\n"); }).listen(8000); }但是這種完全依賴于系統的負載均衡存在著一個重要缺陷:在linux和Solaris上,只要某個子進程的accept queue為空(通常為最后創建的那個子進程),系統就會將多個connetion分配到同一個子進程上,這會造成進程間負載極為不均衡。
特別是在使用長連接的時候,單位時間內的new coming connection并不高,子進程的accept queue往往均為空,就會導致connection會不停的分配給同一個進程。所以這種負載均衡完全依賴于accept queue的空閑程度,只有在使用短連接,而且并發非常高的情況下,才能達到負載均衡,但是這個時候系統的load會非常高,系統也會變得不穩定起來。
Nginx是怎么做的?
如果你了解nginx,那么你可能第一時間會想到使用nginx的處理方式,nginx有一個master和多個worker進程,master進程監聽端口,負責accept connection,并把accept 的socket發送給各worker進程,由worker進程接收數據并處理。
linux下,nginx是使用socketpair建立master和worker進程間的通信,并使用sendmsg、recvmsg等api來傳輸命令和文件描述符的。那么node.js是否支持這種方案呢?
答案是肯定的,作出這個回答的依據在于node.js的child_process和cluster模塊均有一個send方法:child.send(message, [sendHandle])
這個方法的第二個參數就是我們想要傳遞的socket,而且node.js文檔上還給出了一個test case:
var normal = require('child_process').fork('child.js', ['normal']); var special = require('child_process').fork('child.js', ['special']); // Open up the server and send sockets to child var server = require('net').createServer(); server.on('connection', function (socket) { // if this is a VIP if (socket.remoteAddress === '74.125.127.100') { special.send('socket', socket); return; } // just the usual dudes normal.send('socket', socket); }); server.listen(1337);child.js process.on('message', function(m, socket) { if (m === 'socket') { socket.end('You were handled as a ' + process.argv[2] + ' person'); } });簡單,精煉!似乎是一個完美的解決方案。我們稍微加工一下,讓他成為一個可以正常運行的http server:
master.js
var http = require('http'), numCPUs = require('os').cpus().length; cp = require('child_process'), net = require('net'); var workers = []; for (var i = 0; i < numCPUs; i++) { workers.push(cp.fork('app.js', ['normal'])); } net.createServer(function(s) { s.pause(); var worker = worker.shift(); worker.send('c',s); workers.push(worker); }).listen(80); var http = require('http'), cp = require('child_process'), net = require('net'); var server = http.createServer(function(req,res){ res.writeHead(200, {"Content-Type": "text/plain", "Connection": "close"}); res.end("hello, world"); }); console.log("webServer started on " + process.pid); process.on("message", function(msg,socket) { process.nextTick(function(){ if(msg == 'c' && socket) { socket.readable = socket.writable = true;socket.resume(); server.connections++; socket.server = server; server.emit("connection", socket); socket.emit("connect"); } }); });我們在worker進程中創建了一個http server,但是這個http server并不監聽,也不綁定端口,在收到master傳輸過來的socket時,調用server.emit("connection", socket);就可以觸發server的connection事件了
看起來很不錯,簡單的測試之后可以正常工作,這個方案幾近于完美。在經歷過共享監聽socket方案的失敗后,我們把服務遷移到這種架構上來。
但是,我們遇到了問題。我們發現master進程的cpu和內存在逐漸增長,并最終到達100%,或者node.js崩潰(Assertion `fd_to_send >= 0' failed),這令我很抓狂,百般無奈之下我們求助于node.js的開發人員,在github上報告了我們遇到的問題(Issue #4587)。
就在當天晚上,node.js的開發人員indutny找到了問題所在,主要在于主進程在將socket發送給子進程之后,并沒有銷毀,而是保留在socketList中,這會導致socket在主進程中逐步累積,并最終達到上限。
indutny很快解決了這個問題,于第二天提交了這個commit,按照這個commit,indutny給send函數增加了第三個可選參數,修改后的send函數將變為:
child.send(message,[socket], [{ track: false, process: false }])我們的master進程不需要track每個socket狀態,所以我們將它設為false即可。到此,這個問題得到了完美的解決
今天就分享這么多,關于高并發下的Node.js與負載均衡,你學會了多少?歡迎在留言區評論,對于有價值的留言,我們都會一一回復的。如果覺得文章對你有一丟丟幫助,請點右下角【在看】,讓更多人看到該文章。如果有想了解的,也可以進行留言總結
以上是生活随笔為你收集整理的.net core高并发_高并发下的Node.js与负载均衡的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: html鼠标响应事件吗,学习JavaSc
- 下一篇: java获取文件新增内容_关于java生