Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Node.jsデザインパターンを読んで

 Node.jsデザインパターンを読んで

テックベンチという社内のLT会で発表した資料です。
Node.jsのアーキテクチャにおける、libuvの部分の話について深ぼって話しました。

3d06fa4b3230d37a8d940405cc4abcc6?s=128

ryota kise

June 25, 2022
Tweet

Other Decks in Programming

Transcript

  1. Node.jsデザインパターン を読んで 2022 / 6 / 23

  2. ゴール - libuvとはなんなのか? - Reactor Patternとはなんなのか? - イベントループとはなんなのか? がなんとなく理解できるようになること

  3. Node js 公式より Node.js はスケーラブルなネットワークアプリケーションを構築するために設計された非同期 型のイベント駆動の JavaScript 環境です。 特徴としては -

    シングルスレッド - ノンブロッキング I / O + イベントループ(libuv) = 非同期 I / O が挙げられます
  4. シングルスレッドとは - CPUの処理単位のことでCPUの利用単位としてはプロセスとスレッドがあり、プロ セスが一つ以上のスレッドをもつ - シングルスレッドは文字通りスレッド一つでプログラムを処理すること

  5. 補足 マルチスレッド マルチスレッドでは以下のように処理を複数のスレッドに分散させることができる。 シングルスレッドでは処理をスレッドに分散するのではなく時間軸で分散する

  6. ノンブロッキングI / O ノンブロッキングI / O - I / O処理が走った時にI

    / O処理ができない場合は即座にエラーを返しブロックさせ ない方式 - データが処理可能になるまでリクエストを送る必要がある 非同期I / O - I / O処理が走った時に処理が完了するまでバックグラウンドで待機しI / O処理が 完了したタイミングで通知を返すことによってブロックしない方式
  7. Busy Wait - ノンブロッキングI / Oの処理方法の一つ - I / Oの処理が戻されるまでループを回してポーリングする方法のこと

    - この方法ではI / O処理可能になるまでループするためCPUを食うことになる
  8. Reactor Pattern I / Oに基づいた処理はI / O完了の通知を受け取ってからデータを取り出し行う必要が ある シングルスレッドで複数の処理を行うために -

    ノンブロッキングI / O - イベント多重分離(Event demultiplexing) - イベントループ がある dataを読み取ってinputに 代入する前にconsole.log に到達するので 何も出力されない
  9. イベント多重分離(event demultiplexing) 一つにまとまった処理を複数に分離することをデマルチプレキシング(多重分離)という この機能はOSに提供されており、I / Oの完了が完了した時に〇〇するができるように この方法を使用することによって時間軸で処理を分散させシングルスレッドでも並行に 処理を実行することができる

  10. libuv デマルチプレクサの実装はOSごとに異なっている(Linuxのepoll, macOSのkqueueな ど) OS差分を抽象化し吸収するために、Nodeのコア開発チームはlibuvというCのライブラ リを作成している。 libuvがこのあと出てくるイベントループや非同期処理をNode.jsに提供している

  11. Reactor PatternでのI / Oリクエスト時の実際の動き - 基本的にはI / Oタスクのそれぞれにハンドラ( Node.jsではコールバック)を対応させる -

    イベントループにおいて新イベントが生成・処理されるたびにハンドラが呼び出される
  12. 1 アプリがデマルチプレクサに対して I / O要 求を発行する その際にハンドラが指定され、 I / O要求の

    発行はノンブロッキングな関数呼び出しな ので即座にアプリケーションに処理が戻る
  13. 2 I / O要求が届くとデマルチプレクサが キューに入れる

  14. 3, 4 - イベントループにおいて、キューの 中の全てのイベントが操作されて処 理される - 各イベントに対して、登録済みのハ ンドラが呼び出される

  15. 5a, 5b - ハンドラの呼び出しが完了するとイ ベントループで次のイベントが処理 される - ハンドラ内で更にI / O要求が発行さ

    れた場合はイベントループに処理を 戻す前に1の処理を繰り返す
  16. 6 イベントループで全てのイベントが処理さ れると新しいイベントが送られてくるまで待 機する

  17. Event Queue libuvから提供されるキューとNode.jsが提供するキューがある libuv - Expired timers / intervals queue 

    - IO Events Queue  - Immediates Queue  - Close Handlers Queue Node.js - nextTick Queue - microTask Queue libuvが提供しているキューはイベントループの各フェーズに紐づいており、フェーズが実行され る毎にNode.jsが提供しているキューが実行される
  18. Event loop イベントループには6つのフェーズがあり、 3・4・5aがこの6つの順番で行われる それぞれのフェーズは実行するコールバッ クのFIFOキューをもつ JavaScriptの実行はidle,prepare以外のど こかのフェーズで実行され キューが空になるかコールバックの上限に 達したらイベントは次のフェーズへ遷移す

  19. 3, 4, 5a - イベントループにおいて、キューの 中の全てのイベントが操作されて処 理される - 各イベントに対して、登録済みのハ ンドラが呼び出される

    - ハンドラの呼び出しが完了するとイ ベントループで次のイベントが処理 される 再掲
  20. イベントループとキューの対応表 libuvは各フェーズ毎に結果を JavaScriptに伝える この時にnextTickQueueとmicroTaskQueue に入れられた内容を処理する

  21. nextTickQueue process.nextTickのコールバックが実行される 非同期処理の中で最初に実行される

  22. microTaskQueue Promiseオブジェクトのコールバックが実行される

  23. nextTickの方が先に実行される

  24. 補足 イベントループ

  25. イベントループ

  26. Event loop (Timer) setTimer, setIntervalなどのタイマー系APIの期限切れコールバックが実行される

  27. Event loop (pending callback) I / O操作の成功、エラーのコールバック関数が実行される この場合だと console.log(err) か

    console.log(data)
  28. Event loop (idle, prepare, poll) オプショナルなフェーズでpollフェーズが行われる場合はidle / prepareフェーズが行わ れる -

    I / O をブロックしてポーリングする時間を計算する - キュー内のイベントをキューが空になるかシステム固有の上限に達するまで処理す る
  29. Event loop (check) - setImmediateのコールバック専用のフェーズ - setImmediateで登録された全てのコールバックを実行する

  30. Event loop (close callback) 全てのcloseフェーズのコールバックが実行される

  31. 実際に

  32. Node.jsのアーキテクチャ

  33. まとめ - Node.jsはイベントループ + ノンブロッキング I / O、非同期 I /

    Oを使うことでI / O 待ちの時間を時間軸に分散している - イベントループ、I / O完了通知などの根幹の部分はOS差分を吸収するためにlibuv というライブラリを使用している
  34. ご清聴ありがとうございました

  35. 参考資料 - https://www.oreilly.co.jp/books/9784873118734/ - https://blog.insiderattack.net/event-loop-and-the-big-picture-nodejs-event-loop-part-1-1cb67a182 810 - https://zenn.dev/estra/books/js-async-promise-chain-event-loop - https://blog.takanabe.tokyo/2015/03/%E3%83%8E%E3%83%B3%E3%83%96%E3%83%AD%E

    3%83%83%E3%82%AD%E3%83%B3%E3%82%B0i/o%E3%81%A8%E9%9D%9E%E5%90%8 C%E6%9C%9Fi/o%E3%81%AE%E9%81%95%E3%81%84%E3%82%92%E7%90%86%E8%A 7%A3%E3%81%99%E3%82%8B/ - https://blog.hiroppy.me/entry/nodejs-event-loop - https://engineer.recruit-lifestyle.co.jp/techblog/2019-12-13-node-async-io/ - https://nodejs.org/en/about/ - https://libuv.org/