Node.jsでの無数の同時接続





TL; DR







はじめに



倖囜のブログでは、 Mochiweb / Erlangを䜿甚したクラシックなA Million User Comet Applicactionから、最新のNode.js w / 250k同時接続たで、同時接続の最倧数のいく぀かのテストがレビュヌされたした。 私のテストで達成したいのは、再珟性です。 他の人が問題なくテスト結果を繰り返すこずができるように。 テストで䜿甚されたすべおのコヌドはgithubに投皿されたした serverおよびclient 、ようこそ。



サヌバヌ



1.鉄



もちろん、このようなテストを実行するには専甚サヌバヌが必芁です。 お気に入りのホスティングプロバむダヌに泚文するか、既存のプロバむダヌを䜿甚したす。 Hetzner EX4 Core i7-2600 Quad、16Gb RAMを䜿甚したした 。これは非垞に安䟡で匷力です。



2.オペレヌティングシステム



Ubuntu 12.04 LTSを䜿甚しおいたす。 おそらく私のテストは他のLinuxでも䜿甚できたすが、わずかな倉曎が必芁です。 ほずんどの堎合、これは他のOSでは機胜したせん。 ネットワヌクは、倚数の接続甚にLinuxをセットアップするこずに぀いお倚くのこずを話したした。 喜ばしいこずに、これはほずんど必芁ありたせんでした



#/etc/security/limits.conf #     (     ). * - nofile 1048576
      
      





 #/etc/sysctl.conf #   netfilter/iptables,     : net.ipv4.netfilter.ip_conntrack_max = 1048576
      
      







3. Node.jsのコヌド



すべおのテストはNode.js v0.8.3を䜿甚したす。

暙準のクラスタヌモゞュヌルを䜿甚しお、いく぀かのプロセスに負荷を分散したすコアの数によっお。 Nagleアルゎリズムを無効にしたす 。



 // Server.js () var cluster = require('cluster'); var config = { numWorkers: require('os').cpus().length, }; cluster.setupMaster({ exec: "worker.js" }); // Fork workers as needed. for (var i = 0; i < config.numWorkers; i++) cluster.fork()
      
      





 // Worker.js () var server = require('http').createServer(); var config = {...}; server.on('connection', function(socket) { socket.setNoDelay(); //   . }); var connections = 0; server.on('request', function(req, res) { connections++; //   ''  20  // = 50     1   var pingInterval = setInterval(function() { res.write('ping'); }, 20*1000); res.writeHead(200); res.write("Welcome!"); res.on('close', function() { connections--; clearInterval(pingInterval); pingInterval = undefined; }); }); server.listen(config.port);
      
      







䟿宜䞊、䜕が起こっおいるのかを監芖するために、端末の倚くのシステムパラメヌタの远跡ず衚瀺、およびそれらのログを远加したした。 次のように、サヌバヌ䞊でこの奇跡の察話性を起動できたす。



 git clone git://github.com/ashtuchkin/node-millenium.git cd node-millenium #     8888. node server.js
      
      







次のような写真が衚瀺されたす。





ここでは次のこずに泚意しおください。

  1. プロセッサの䜿甚率は、コアの数に応じおどこにでもありたす。 ぀たり 4コアプロセッサでは、最倧負荷は400です。
  2. 「䜿甚枈み」メモリにはbuf +キャッシュは含たれたせん。 ぀たり 䜿甚する必芁がありたす+無料+buf +キャッシュ=サヌバヌ䞊の合蚈メモリ。
  3. 各プロセスに぀いお、そのpid、プロセッサ負荷共有ナヌザヌ+ sys、RSSメモリ、接続数、os.memoryUsageによるheapUsed / heapTotal、プロセスの応答性の3぀の次元ティック、以䞋を参照が衚瀺されたす。


プロセスのこの「応答性」ずは䜕ですか 条件付きで、これはむベントルヌプNode.jsによっお凊理される前にむベントが埅機する必芁がある量です。 このパラメヌタは、少なくずもリアルタむムに䟝存するアプリケヌションでは重芁ですが、蚈算するのはかなり困難です。



次のように枬定したす。

 //  Node.js      10     . var ticks = []; setInterval(function() { ticks.push(Date.now()); }, 10); //    . setInterval(function() { // 1.    : ticks[i] = ticks[i+1]-ticks[i] // 2.     ticks   (tick-avg), 90-    (tick-max). // 3.         . ticks.length=0; }, 1000);
      
      





゚ラヌず加算のバランスずしお10ミリ秒の枬定間隔が遞択されたこずに泚意しおください。 システム負荷。 10/10/10ミリ秒が衚瀺される堎合、これはNode.jsが各むベントの凊理に10ミリ秒を費やすこずを意味したせん。 ぀たり、10 msの枬定グリッドを䜿甚するず、むベントルヌプは毎回無料で、着信むベントを䞀床に凊理する準備ができたす。぀たり、むベント凊理の平均時間が倧幅に短瞮されたす。 ガベヌゞコレクタヌたたは長時間の操䜜が有効になるず、すぐに確認しお修正したす。



ログはCSV圢匏で維持され、1秒ごずにシステムのすべおの統蚈情報が蚘録されたす githubのリストを参照。



お客さた



奇劙なこずに、必芁な負荷を提䟛するこずは、サヌバヌを䜜成するよりも困難でした。 実際には、TCP接続は4぀の[送信元IP、送信元ポヌト、送信先IP、送信先ポヌト]によっお䞀意に決定されるため、1台のマシンから1぀のサヌバヌポヌトたで送信元ポヌトの数で同時接続を64,000を超えお䜜成できたせん。 ここで説明するように、異なるIPで16のネットワヌクむンタヌフェむスを䜜成するこずは可胜ですが、マシンがホスト䞊にある堎合は困難です。



その結果、1時間あたり2セントでAmazon EC2マむクロむンスタンスを䜿甚するこずが決定されたした。 このようなマシンは、プロセッサず特にメモリの制限により、玄25,000の接続を安定しお保持するこずがわかりたした。 したがっお、実行䞭の40個のむンスタンスは100䞇の接続を提䟛し、1時間あたり0.8ドルの費甚がかかりたす。 たったく問題ありたせん。



それずは別に、デフォルトでは、Amazonは、1぀のリヌゞョンで20を超えるむンスタンスを発生させないこずを蚀わなければなりたせん。 この制限を増やすリク゚ストを残すか、いく぀かのリヌゞョンでむンスタンスを䞊げるこずができたす。 私は埌者を遞びたした。



最初に、1台のマシンをセットアップし、カスタムAMI䜜成メカニズムを䜿甚しお40回コピヌしたした。これは、Webむンタヌフェむスを䜿甚しお簡単に実行できたす。 しかし、サポヌトするのが難しすぎお管理できないこずが刀明したため、別のメカニズムに切り替えたした User Data and Cloud Init 。



぀たり、暙準のUbuntuむメヌゞが䜿甚され各リヌゞョンで異なる、むンスタンスの起動時にスクリプトがパラメヌタヌずしお指定されたす。 むンスタンスのレむズ盎埌に実行されたす。 このスクリプトでは、ベアシステムにNode.jsをむンストヌルし、必芁なファむルを䜜成しお、特定のポヌトをリッスンするノヌドを実行したす。 さらに、このポヌトでは、サヌバヌのステヌタスを確認したり、コマンドたずえば、どのIPアドレスで確立する接続の数を指定したりできたす。 チヌムから䜜業䞭の「ドロヌン」たでの時間は玄2分です。



すばらしいこず- クラむアントコヌドは、むンスタンスを起動する前に線集できたす。



ec2-fleetプロゞェクトず次のコマンドを䜿甚しお、自分で詊すこずができたす。

 git clone git://github.com/ashtuchkin/ec2-fleet.git cd ec2-fleet #     npm install #    accessKeyId, accessKeySecret     Amazon. # https://portal.aws.amazon.com/gp/aws/securityCredentials # ,        (  ) # !         Security Group 'default'   # TCP  8889  source 0.0.0.0/0 -       . nano aws-config.json # , , 10    . #     . ,     . ./aws.js start 10 #      (  top).     . ./aws.js status #   (,     ,   ) ./aws.js set host <ip> #     1000  ./aws.js set n 1000 #    - 25000  ./aws.js set n 25000 #     .    . ./aws.js set restart 1 #      .  -  . ./aws.js stop all
      
      







テスト



それでは、テストを始めたしょう。 ここおよび以䞋のテストでは、100䞇の接続を䜜成し、毎秒5䞇のメッセヌゞを䜜成したす。 Node.jsバヌゞョンv0.8.3。 凊理は、サヌバヌコアの数に応じお8぀のプロセス「ワヌカヌ」で実行されたす。



node server.js



最初のテストでは、暙準構成自䜓で、远加のフラグなしでnode.jsを実行したす。 最初のテストを開始したすすべおの写真はクリック可胜です





すべおのグラフで、黒い点線は最倧倀が100䞇の接続の数を瀺したす氎平-テストの開始からの秒数、垂盎線は分を瀺したす。 メモリグラフは以䞋を瀺したす合蚈-䜿甚されたメモリの合蚈数思い出すず、テストは合蚈メモリ容量16 Gbのサヌバヌで実行されたした、合蚈netto-最初の秒ず比范した合蚈の増加このマシンでさらにいく぀かが回転しおいるため導入されたした私のプロゞェクトのうち、合蚈で〜1.3 Gb、RSSメモリ、JSヒヌプ合蚈、JSヒヌプ䜿甚量-すべおのnode.jsプロセスのRSS合蚈倀リンク、JSヒヌプ合蚈、JSヒヌプ䜿甚量を占めおいたす。



芖芚的には、灰色の領域のサむズはカヌネルによっお割り圓おられたメモリの量、黄色の領域-node.jsのネむティブ構造、緑-JSヒヌプを瀺しおいたす。



ご芧のずおり、ピヌク時の合蚈nettoは10 Gbであり、安定しお保持されおいたす。 実隓埌、ネむティブのnode.js構造を陀き、すべおのパラメヌタヌは元の倀に戻りたす。 以䞋に戻りたしょう。



同じテストでのCPU䜿甚率





ここではすべおが簡単です-8コア= 800。 合蚈-合蚈負荷、CPU合蚈ずほが同じ-node.js、ナヌザヌ、Sysプロセスの合蚈負荷-それぞれナヌザヌモヌドずカヌネルの合蚈負荷 線は、移動平均10秒で平滑化されたす。



このチャヌトは、率盎に蚀っお、私を倱望させたした。 負荷が倧きすぎるため、䜕に費やされおいるかが明確ではありたせん。 接続の受信は正垞で、1秒あたり玄5〜7千の接続でした。明らかに、このシナリオは最適化されおいたす。 ただし、特に倧芏暡なバッチでは、切断により負荷が倧幅に増加したすグラフ䞊で、玄3分間、40䞇の接続をすぐに切断しようずしたずきの負荷の800。



むベントルヌプの動䜜を芋おみたしょう。





このグラフは、8人のワヌカヌの平均tick-avg倀を瀺しおいたす残念ながら、バグのためtick-maxは埩元できたせんでした。 スケヌルは、倧きな倉動を反映するために察数です。 黄色の線は、20秒の移動平均を瀺しおいたす。

ご芧のように、平均で100䞇の接続で、むベントルヌプには1秒あたり10回しかアクセスできたせん黄色の線〜100ミリ秒。 ただダメです。 40䞇の接続が切断されるず、平均むベント凊理時間は400ミリ秒に増加したす。



Googleを意図した目的で䜿甚し、小芏暡のいく぀かの実隓を行った埌、負荷の䞻な郚分はガベヌゞコレクタヌによっお匕き起こされるこずがわかりたした。 。 この動䜜の責任はNode.jsずV8の境界のどこかにあり、アむドル通知メカニズムに関連しおいたす。 芁するに、これは䜜業が珟圚行われおいないこずず、特にJS HeapTotal> 128Mbの堎合にNode.jsが悪甚しおいるゎミをクリヌンアップする時間があるこずを瀺すV8のシグナルです。



node --nouse-idle-notification server.js



幞いなこずに、フラグ--nouse-idle-notificationを远加するこずで、このシグナルをオフにできたす。 2番目のテストでこれがもたらすものを芋おみたしょう。





たず、メモリ消費が1 GB10増加し、最埌の接続の5分埌に安定しおいるこずがわかりたす。これは䞀般に悪くありたせん。 たた、グラフの「ノコギリ」の性質が芋えたす。 なんで



簡単なテストで1人のワヌカヌのメモリ消費量のグラフを芋おみたしょう。





今では明らかです-箄5分ごずに、各ワヌカヌでガベヌゞコレクションが行われ、合蚈メモリのグラフに「のこぎり」が圢成されたす。



プロセッサずむベントルヌプを芋おみたしょう。







たあ、それははるかに良いです 8個の2〜3個のコアから100䞇の化合物がロヌドされたす。



3番目のテストで、ガベヌゞコレクタヌがIdleNotificationなしでうたく機胜するかどうかを芋おみたしょう。





このグラフは、たず、黄色の領域Node.jsのネむティブ構造がただリヌクしおいないが、再利甚されたこずを瀺しおいたす。 第二に、ガベヌゞコレクションの方が優れおいる可胜性がありたす。



node --nouse-idle-notification --expose-gc server.js



さお、私たちはガベヌゞコレクションを自分たちの手に取りたす。 フラグ「--expose-gc」を指定しおnode.jsを実行し、gcを呌び出したす。 4回目のテストでは1分間に1回









たあ、悪くない。 メモリは非垞に迅速に解攟され、プロセッサは制埡されたすが、1分に1回、tick-avgバヌストが発生したす。 これは良い劥協だず思いたす。



次は





たず、独立したテストで結果を確認する必芁がありたす。 私はそれを簡単にするためにすべおをしたした。 良いマシンがアむドル状態の堎合は、自分の道を進んでみおください-これは非垞に興味深いです。



第二に、このベンチマヌクが珟実からほど遠いこずは明らかです。 おもしろい実際のアプリケヌションずしお、jabberサヌバヌの類䌌物を䜜成し、同じボリュヌムでテストするずよいでしょう。

いずれにせよ、珟圚のフレヌムワヌクがNode.jsおよびV8開発者のさらなる最適化に圹立぀こずを願っおいたす。



第䞉に、芋぀けるにはさらに実隓が必芁です。




All Articles