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

An introduction to Node.js

shimataro
August 04, 2020

An introduction to Node.js

さくらの夕べ Tech Night #2 Onlineの発表資料です
https://sakura-tokyo.connpass.com/event/182387/

shimataro

August 04, 2020
Tweet

More Decks by shimataro

Other Decks in Technology

Transcript

  1. いまさら聞けないNode.js
    小田島 太郎 @shimataro999
    2020/8/4 さくらの夕べ Tech Night #2 Online

    View Slide

  2. https://shimataro.me/
    自己紹介
    ● 小田島 太郎 / https://shimataro.me/
    ● ウェブエンジニア
    ○ フロントエンドとかバックエンドとか
    ○ インフラもちょこっとだけ
    ● 趣味は手品
    ○ 手品業界→ウェブ業界
    2

    View Slide

  3. この発表について
    対象者
    ● Node.js=サーバーサイドJSってことぐらいしか知らない
    ● バックエンドをPHPとかRubyからNode.jsに書き直しを検討中
    ● C10K問題のことをよく知らない
    3
    Node.js完全に理解した
    なにもわからない
    チョットデキル
    このへん対象
    半分くらいこの説明です

    View Slide

  4. この発表について
    目標
    ● Node.jsが解決するものを理解する(何がうれしいの?)
    ● 他の言語との違いを理解する(他とどう違うの?)
    ● バックエンド開発の注意点を理解する(何に気をつければいいの?)
    4
    スライドは公開しています
    https://speakerdeck.com/shimataro
    https://shimataro.me/slides/

    View Slide

  5. それでは始めます
    5

    View Slide

  6. Node.jsとは?
    6

    View Slide

  7. Node.jsとは?
    7
    JavaScriptの実行環境の1つ
    ● コマンドラインからJavaScriptを実行できる
    ● Chromeで使われているV8エンジンを搭載
    ● C10K問題を解決するためのバックエンド言語として開発された
    ● 名前の由来は “Node in Network”

    View Slide

  8. Node.jsとは?
    8
    使われている場所
    ● ウェブサービスのバックエンド
    ● フロントエンド
    ○ WebpackとかVue.jsのビルドとか
    ● デスクトップアプリ
    ○ Electron(Visual Studio CodeとかSlackとか)
    ● 組み込み

    View Slide

  9. C10K問題とは?
    9

    View Slide

  10. C10K問題(クライアント1万台問題)とは?
    10
    突然ですが問題です。
    クライアント1万台問題とは何でしょう?

    View Slide

  11. C10K問題(クライアント1万台問題)とは?
    11
    解答1: クライアントが1万台になると何かおかしくなる

    ● 1万という数値には特別な意味はない
    ○ 単に「クライアントの台数が多い」という意味
    ○ 9999台まではOKで、1万台になった瞬間におかしくなるわけではない
    ● 何がおかしくなる?
    ○ サービスの応答が遅くなる

    View Slide

  12. C10K問題(クライアント1万台問題)とは?
    12
    解答2: クライアントの数が多くなると応答が遅くなる

    ● 「クライアントの数が多くなる」とは?
    ○ 1秒に1台ずつ、1万秒かけて接続がある場合でも「クライアントが1万台」には変
    わりない
    ○ 問題は同時接続数

    View Slide

  13. C10K問題(クライアント1万台問題)とは?
    13
    解答3: クライアントの同時接続数が多くなると応答が遅くなる

    ● なぜ遅くなる?
    ○ マシンスペックが足りなくて応答が遅くなるのは当たり前
    ■ そんなもんにわざわざ C10K問題なんて名前つける必要はない
    ■ マシンを買い直せば済む話
    ○ マシンスペック以外の原因があるからこそのC10K問題

    View Slide

  14. C10K問題(クライアント1万台問題)とは?
    14
    解答4: マシンスペックは問題ないにもかかわらず、クライアントの同時接続数が
    多くなると応答が遅くなる ⭕
    ● 何が原因?
    ● どうすればいい?

    View Slide

  15. C10K問題の原因
    15

    View Slide

  16. C10K問題の原因1: プロセス数の上限
    16
    Apache HTTP Serverの駆動方式
    ● 以前はprefork方式(1リクエスト1プロセス)が一般的
    OSのプロセス数制限
    ● プロセスにはIDが割り当てられている
    ○ 32bit Linuxでは32767が上限
    ● OSごとに同時に実行できるプロセス数の上限が決まっている
    prefork方式では、OSごとに決められた数以上のリクエストを処理できない

    View Slide

  17. ウェブサーバー
    プロセス
    プロセス
    プロセス
    C10K問題の原因1: プロセス数の上限
    17
    リクエスト
    プロセス プロセス上限オーバー!
    (処理できない!)
    リクエスト
    リクエスト
    リクエスト
    プロセスIDを使い切った

    View Slide

  18. 【コンテキストスイッチ】
    CPUが複数のプロセスを並行処理するために、それまで実行していたプロセス
    の内容を記録し、新たなプロセスの内容を復元すること
    C10K問題の原因2: コンテキストスイッチのコスト
    18
    時間軸
    プロセスA プロセスB プロセスC
    B復元
    A保存 C復元
    B保存
    コンテキストスイッチ

    View Slide

  19. プロセスが増えると、コンテキストスイッチがCPUに対して占める割合が大きく
    なり、CPUリソースの大部分を消費する
    prefork方式(リクエストが増える=プロセスが増える)では、リクエストが増える
    ほどリクエストを捌けるリソースが少なくなる
    C10K問題の原因2: コンテキストスイッチのコスト
    19
    時間軸
    プロセスA プロセスB プロセスC
    B復元
    A保存 C復元
    B保存 プロセスD
    D復元
    C保存

    View Slide

  20. 【ファイルディスクリプター】
    OSが読み書きしているファイルのID
    OS全体やプロセスごとに上限が決まっている
    Linuxでは、1プロセスにつき1024が上限のことが多い
    C10K問題の原因3: ファイルディスクリプターの上限
    20

    View Slide

  21. Unix系OSでは、ファイルだけでなくネットワークアクセスにもファイルディスクリ
    プターを使う
    DBとのコネクションにもファイルディスクリプターを使う
    リクエストごとにDBコネクションを張る構成だと、ファイルディスクリプターの上
    限を超える同時接続ができない
    C10K問題の原因3: ファイルディスクリプターの上限
    21

    View Slide

  22. C10K問題の解決方法
    22

    View Slide

  23. 札束で解決
    ● 1台で捌けないなら10台用意すればいい
    ● 10台で捌けないなら100台用意すればいい
    ● 用意したサーバーにいい感じに負荷分散する
    C10K問題の解決方法1: サーバーの台数を増やす
    23
    ロードバランサー側にもC10K問題が発生しないように注意

    View Slide

  24. C10K問題の解決方法2: シングルプロセスで捌く
    頭のいい人は考えました
    「マルチプロセス方式でプロセスIDの上限に引っかかるなら、シングルプロセス
    ・シングルスレッドで全リクエストを捌けばいいんじゃね?」
    「これならコンテキストスイッチも必要なくね?」
    「1つのDBコネクションを複数リクエストで使いまわせばファイルディスクリプター
    の問題もなくなるんじゃね?」
    24
    非同期・ノンブロッキングI/O

    View Slide

  25. C10K問題の解決方法2: シングルプロセスで捌く
    【同期・ブロッキングI/O(従来型)】
    指示を出したら処理が終わるまでCPU側でひたすら待つ
    25
    炊飯
    洗濯指示
    炊飯指示 炊飯完了
    洗濯完了
    洗濯
    ゲーム
    料理
    アイロンがけ
    待機 待機

    View Slide

  26. C10K問題の解決方法2: シングルプロセスで捌く
    【非同期・ノンブロッキングI/O】
    指示を出したら完了を待たずに別の処理を行う
    26
    洗濯指示
    炊飯指示 炊飯完了
    洗濯完了
    炊飯
    洗濯
    ゲーム 料理 アイロンがけ
    待機

    View Slide

  27. C10K問題の解決方法2: シングルプロセスで捌く
    非同期・ノンブロッキングI/Oの特徴
    ● ⭕処理の完了を待っている間に別の処理をできる
    ○ CPUの待ち時間が減るので効率的
    ● ⭕CPUを使わない複数の処理を並列で実行できる
    ● ❌非同期処理の記述が複雑になりがち
    ○ 投げっぱなしで済む処理はあまり多くないので、どこかで完了を待ち合わせる
    必要がある
    27

    View Slide

  28. Node.jsのアプローチ
    28

    View Slide

  29. Node.jsのアプローチ
    ● シングルプロセス・シングルスレッド
    ○ 処理がキューに追加され、先に入ったものから順次処理される
    ○ コンテキストスイッチが発生しない
    ● CPUを使わない処理(通信など)は非同期で行われる
    ○ 処理が終わったらコールバック関数が呼ばれる
    ○ コネクション(ファイルディスクリプター)を使いまわせる
    29
    (きちんとプログラミングすれば)C10K問題は発生しない

    View Slide

  30. Node.jsのアプローチ
    30
    いい感じにHTML出力
    リクエストC リクエストB リクエストA
    キュー
    リクエストC リクエストB
    リクエストA
    1. DBからデータを取り出す
    2. いい感じにHTML出力
    リクエストC リクエストB DB
    1. データ取得指示
    2. データ取得後に
    次の処理がキューに積まれる
    キューの処理はできるだけ短い時間で終わらせるのが鉄則

    View Slide

  31. Node.jsを使うときの注意
    31

    View Slide

  32. Node.jsを使うときの注意1: 非同期処理
    32
    ● コールバック関数を使いまくるとネストが深くなって見づらい
    ● コールバック方式だと例外処理を書きづらい
    ○ Promiseやasync/awaitを使いこなそう
    ● 面倒だからといって絶対に同期版を使わないこと
    ○ 処理に時間がかかる=キューが詰まる=他のリクエストを処理できない
    他の言語からの移行者は要注意

    View Slide

  33. Node.jsを使うときの注意2: グローバル変数
    33
    ● Node.jsはシングルプロセス・シングルスレッド
    ● つまりグローバル変数は全リクエストで共有される
    ● つまりリクエストの内部状態をグローバル変数で管理すると別のリクエスト
    によって突然書き換えられてしまう
    ○ 例えばAccept-Languageの値(ja, en-US等)
    他の言語からの移行者は要注意

    View Slide

  34. Node.jsを使うときの注意3: リソース管理
    34
    ● Node.jsはシングルプロセス・シングルスレッド
    ● つまりプロセスは動き続けることが前提
    ● つまりリソースは自動的に解放されない=明示的に解放しないと枯渇し、
    新しいリクエストを処理できなくなる
    ○ メモリーはGCが回収してくれるが…
    他の言語からの移行者は要注意

    View Slide

  35. Node.jsを使うときの注意4: 一部のバグが全体に影響
    35
    ● Node.jsはシングルプロセス・シングルスレッド
    ● つまり接続が切れてもプロセスは実行され続ける
    ● つまり間違えて無限ループを入れてしまったら最後、新しいリクエストを処
    理できなくなる
    ○ マルチプロセスでは接続を切れば無限ループは消える
    他の言語からの移行者は要注意

    View Slide

  36. Node.jsを使うときの注意5: CPUを使いまくる処理
    36
    ● Node.jsはシングルプロセス・シングルスレッド
    ● つまり1つの関数が終わるまで他のリクエストを処理できない
    ● つまりCPUリソースを大量に消費する処理には不向き
    ○ 別プロセスや別サービスとしてNode.jsの外側に置く工夫が必要
    他の言語からの移行者は要注意

    View Slide

  37. まとめ
    37

    View Slide

  38. まとめ
    ● Node.jsはJavaScriptの実行環境だよ
    ● C10K問題を解決できるよ
    ● シングルプロセス・シングルスレッドだよ
    ● 非同期I/Oを使ってるよ
    ● 他の言語から移行するときは色々注意しようね
    ● 手品に興味がある人はおはなししましょう
    38

    View Slide

  39. まとめ
    目標(再掲)
    ● Node.jsが解決するものを理解する(何がうれしいの?)
    ● 他の言語との違いを理解する(他とどう違うの?)
    ● バックエンド開発の注意点を理解する(何に気をつければいいの?)
    39
    お わ か り い た だ け た だ ろ う か

    View Slide

  40. https://shimataro.me/
    40
    「さくらのナレッジ」にも投稿しています
    https://knowledge.sakura.ad.jp/24148/

    View Slide