Node.jsデザインパターンを読んで
by
ryota kise
Link
Embed
Share
Beginning
This slide
Copy link URL
Copy link URL
Copy iframe embed code
Copy iframe embed code
Copy javascript embed code
Copy javascript embed code
Share
Tweet
Share
Tweet
Slide 1
Slide 1 text
Node.jsデザインパターン を読んで 2022 / 6 / 23
Slide 2
Slide 2 text
ゴール - libuvとはなんなのか? - Reactor Patternとはなんなのか? - イベントループとはなんなのか? がなんとなく理解できるようになること
Slide 3
Slide 3 text
Node js 公式より Node.js はスケーラブルなネットワークアプリケーションを構築するために設計された非同期 型のイベント駆動の JavaScript 環境です。 特徴としては - シングルスレッド - ノンブロッキング I / O + イベントループ(libuv) = 非同期 I / O が挙げられます
Slide 4
Slide 4 text
シングルスレッドとは - CPUの処理単位のことでCPUの利用単位としてはプロセスとスレッドがあり、プロ セスが一つ以上のスレッドをもつ - シングルスレッドは文字通りスレッド一つでプログラムを処理すること
Slide 5
Slide 5 text
補足 マルチスレッド マルチスレッドでは以下のように処理を複数のスレッドに分散させることができる。 シングルスレッドでは処理をスレッドに分散するのではなく時間軸で分散する
Slide 6
Slide 6 text
ノンブロッキングI / O ノンブロッキングI / O - I / O処理が走った時にI / O処理ができない場合は即座にエラーを返しブロックさせ ない方式 - データが処理可能になるまでリクエストを送る必要がある 非同期I / O - I / O処理が走った時に処理が完了するまでバックグラウンドで待機しI / O処理が 完了したタイミングで通知を返すことによってブロックしない方式
Slide 7
Slide 7 text
Busy Wait - ノンブロッキングI / Oの処理方法の一つ - I / Oの処理が戻されるまでループを回してポーリングする方法のこと - この方法ではI / O処理可能になるまでループするためCPUを食うことになる
Slide 8
Slide 8 text
Reactor Pattern I / Oに基づいた処理はI / O完了の通知を受け取ってからデータを取り出し行う必要が ある シングルスレッドで複数の処理を行うために - ノンブロッキングI / O - イベント多重分離(Event demultiplexing) - イベントループ がある dataを読み取ってinputに 代入する前にconsole.log に到達するので 何も出力されない
Slide 9
Slide 9 text
イベント多重分離(event demultiplexing) 一つにまとまった処理を複数に分離することをデマルチプレキシング(多重分離)という この機能はOSに提供されており、I / Oの完了が完了した時に〇〇するができるように この方法を使用することによって時間軸で処理を分散させシングルスレッドでも並行に 処理を実行することができる
Slide 10
Slide 10 text
libuv デマルチプレクサの実装はOSごとに異なっている(Linuxのepoll, macOSのkqueueな ど) OS差分を抽象化し吸収するために、Nodeのコア開発チームはlibuvというCのライブラ リを作成している。 libuvがこのあと出てくるイベントループや非同期処理をNode.jsに提供している
Slide 11
Slide 11 text
Reactor PatternでのI / Oリクエスト時の実際の動き - 基本的にはI / Oタスクのそれぞれにハンドラ( Node.jsではコールバック)を対応させる - イベントループにおいて新イベントが生成・処理されるたびにハンドラが呼び出される
Slide 12
Slide 12 text
1 アプリがデマルチプレクサに対して I / O要 求を発行する その際にハンドラが指定され、 I / O要求の 発行はノンブロッキングな関数呼び出しな ので即座にアプリケーションに処理が戻る
Slide 13
Slide 13 text
2 I / O要求が届くとデマルチプレクサが キューに入れる
Slide 14
Slide 14 text
3, 4 - イベントループにおいて、キューの 中の全てのイベントが操作されて処 理される - 各イベントに対して、登録済みのハ ンドラが呼び出される
Slide 15
Slide 15 text
5a, 5b - ハンドラの呼び出しが完了するとイ ベントループで次のイベントが処理 される - ハンドラ内で更にI / O要求が発行さ れた場合はイベントループに処理を 戻す前に1の処理を繰り返す
Slide 16
Slide 16 text
6 イベントループで全てのイベントが処理さ れると新しいイベントが送られてくるまで待 機する
Slide 17
Slide 17 text
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が提供しているキューが実行される
Slide 18
Slide 18 text
Event loop イベントループには6つのフェーズがあり、 3・4・5aがこの6つの順番で行われる それぞれのフェーズは実行するコールバッ クのFIFOキューをもつ JavaScriptの実行はidle,prepare以外のど こかのフェーズで実行され キューが空になるかコールバックの上限に 達したらイベントは次のフェーズへ遷移す る
Slide 19
Slide 19 text
3, 4, 5a - イベントループにおいて、キューの 中の全てのイベントが操作されて処 理される - 各イベントに対して、登録済みのハ ンドラが呼び出される - ハンドラの呼び出しが完了するとイ ベントループで次のイベントが処理 される 再掲
Slide 20
Slide 20 text
イベントループとキューの対応表 libuvは各フェーズ毎に結果を JavaScriptに伝える この時にnextTickQueueとmicroTaskQueue に入れられた内容を処理する
Slide 21
Slide 21 text
nextTickQueue process.nextTickのコールバックが実行される 非同期処理の中で最初に実行される
Slide 22
Slide 22 text
microTaskQueue Promiseオブジェクトのコールバックが実行される
Slide 23
Slide 23 text
nextTickの方が先に実行される
Slide 24
Slide 24 text
補足 イベントループ
Slide 25
Slide 25 text
イベントループ
Slide 26
Slide 26 text
Event loop (Timer) setTimer, setIntervalなどのタイマー系APIの期限切れコールバックが実行される
Slide 27
Slide 27 text
Event loop (pending callback) I / O操作の成功、エラーのコールバック関数が実行される この場合だと console.log(err) か console.log(data)
Slide 28
Slide 28 text
Event loop (idle, prepare, poll) オプショナルなフェーズでpollフェーズが行われる場合はidle / prepareフェーズが行わ れる - I / O をブロックしてポーリングする時間を計算する - キュー内のイベントをキューが空になるかシステム固有の上限に達するまで処理す る
Slide 29
Slide 29 text
Event loop (check) - setImmediateのコールバック専用のフェーズ - setImmediateで登録された全てのコールバックを実行する
Slide 30
Slide 30 text
Event loop (close callback) 全てのcloseフェーズのコールバックが実行される
Slide 31
Slide 31 text
実際に
Slide 32
Slide 32 text
Node.jsのアーキテクチャ
Slide 33
Slide 33 text
まとめ - Node.jsはイベントループ + ノンブロッキング I / O、非同期 I / Oを使うことでI / O 待ちの時間を時間軸に分散している - イベントループ、I / O完了通知などの根幹の部分はOS差分を吸収するためにlibuv というライブラリを使用している
Slide 34
Slide 34 text
ご清聴ありがとうございました
Slide 35
Slide 35 text
参考資料 - 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/