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 小田島 太郎 @shimataro999 2020/8/4 さくらの夕べ Tech Night #2 Online
Slide 2
Slide 2 text
https://shimataro.me/ 自己紹介 ● 小田島 太郎 / https://shimataro.me/ ● ウェブエンジニア ○ フロントエンドとかバックエンドとか ○ インフラもちょこっとだけ ● 趣味は手品 ○ 手品業界→ウェブ業界 2
Slide 3
Slide 3 text
この発表について 対象者 ● Node.js=サーバーサイドJSってことぐらいしか知らない ● バックエンドをPHPとかRubyからNode.jsに書き直しを検討中 ● C10K問題のことをよく知らない 3 Node.js完全に理解した なにもわからない チョットデキル このへん対象 半分くらいこの説明です
Slide 4
Slide 4 text
この発表について 目標 ● Node.jsが解決するものを理解する(何がうれしいの?) ● 他の言語との違いを理解する(他とどう違うの?) ● バックエンド開発の注意点を理解する(何に気をつければいいの?) 4 スライドは公開しています https://speakerdeck.com/shimataro https://shimataro.me/slides/
Slide 5
Slide 5 text
それでは始めます 5
Slide 6
Slide 6 text
Node.jsとは? 6
Slide 7
Slide 7 text
Node.jsとは? 7 JavaScriptの実行環境の1つ ● コマンドラインからJavaScriptを実行できる ● Chromeで使われているV8エンジンを搭載 ● C10K問題を解決するためのバックエンド言語として開発された ● 名前の由来は “Node in Network”
Slide 8
Slide 8 text
Node.jsとは? 8 使われている場所 ● ウェブサービスのバックエンド ● フロントエンド ○ WebpackとかVue.jsのビルドとか ● デスクトップアプリ ○ Electron(Visual Studio CodeとかSlackとか) ● 組み込み
Slide 9
Slide 9 text
C10K問題とは? 9
Slide 10
Slide 10 text
C10K問題(クライアント1万台問題)とは? 10 突然ですが問題です。 クライアント1万台問題とは何でしょう?
Slide 11
Slide 11 text
C10K問題(クライアント1万台問題)とは? 11 解答1: クライアントが1万台になると何かおかしくなる ❌ ● 1万という数値には特別な意味はない ○ 単に「クライアントの台数が多い」という意味 ○ 9999台まではOKで、1万台になった瞬間におかしくなるわけではない ● 何がおかしくなる? ○ サービスの応答が遅くなる
Slide 12
Slide 12 text
C10K問題(クライアント1万台問題)とは? 12 解答2: クライアントの数が多くなると応答が遅くなる ❌ ● 「クライアントの数が多くなる」とは? ○ 1秒に1台ずつ、1万秒かけて接続がある場合でも「クライアントが1万台」には変 わりない ○ 問題は同時接続数
Slide 13
Slide 13 text
C10K問題(クライアント1万台問題)とは? 13 解答3: クライアントの同時接続数が多くなると応答が遅くなる ❌ ● なぜ遅くなる? ○ マシンスペックが足りなくて応答が遅くなるのは当たり前 ■ そんなもんにわざわざ C10K問題なんて名前つける必要はない ■ マシンを買い直せば済む話 ○ マシンスペック以外の原因があるからこそのC10K問題
Slide 14
Slide 14 text
C10K問題(クライアント1万台問題)とは? 14 解答4: マシンスペックは問題ないにもかかわらず、クライアントの同時接続数が 多くなると応答が遅くなる ⭕ ● 何が原因? ● どうすればいい?
Slide 15
Slide 15 text
C10K問題の原因 15
Slide 16
Slide 16 text
C10K問題の原因1: プロセス数の上限 16 Apache HTTP Serverの駆動方式 ● 以前はprefork方式(1リクエスト1プロセス)が一般的 OSのプロセス数制限 ● プロセスにはIDが割り当てられている ○ 32bit Linuxでは32767が上限 ● OSごとに同時に実行できるプロセス数の上限が決まっている prefork方式では、OSごとに決められた数以上のリクエストを処理できない
Slide 17
Slide 17 text
ウェブサーバー プロセス プロセス プロセス C10K問題の原因1: プロセス数の上限 17 リクエスト プロセス プロセス上限オーバー! (処理できない!) リクエスト リクエスト リクエスト プロセスIDを使い切った
Slide 18
Slide 18 text
【コンテキストスイッチ】 CPUが複数のプロセスを並行処理するために、それまで実行していたプロセス の内容を記録し、新たなプロセスの内容を復元すること C10K問題の原因2: コンテキストスイッチのコスト 18 時間軸 プロセスA プロセスB プロセスC B復元 A保存 C復元 B保存 コンテキストスイッチ
Slide 19
Slide 19 text
プロセスが増えると、コンテキストスイッチがCPUに対して占める割合が大きく なり、CPUリソースの大部分を消費する prefork方式(リクエストが増える=プロセスが増える)では、リクエストが増える ほどリクエストを捌けるリソースが少なくなる C10K問題の原因2: コンテキストスイッチのコスト 19 時間軸 プロセスA プロセスB プロセスC B復元 A保存 C復元 B保存 プロセスD D復元 C保存
Slide 20
Slide 20 text
【ファイルディスクリプター】 OSが読み書きしているファイルのID OS全体やプロセスごとに上限が決まっている Linuxでは、1プロセスにつき1024が上限のことが多い C10K問題の原因3: ファイルディスクリプターの上限 20
Slide 21
Slide 21 text
Unix系OSでは、ファイルだけでなくネットワークアクセスにもファイルディスクリ プターを使う DBとのコネクションにもファイルディスクリプターを使う リクエストごとにDBコネクションを張る構成だと、ファイルディスクリプターの上 限を超える同時接続ができない C10K問題の原因3: ファイルディスクリプターの上限 21
Slide 22
Slide 22 text
C10K問題の解決方法 22
Slide 23
Slide 23 text
札束で解決 ● 1台で捌けないなら10台用意すればいい ● 10台で捌けないなら100台用意すればいい ● 用意したサーバーにいい感じに負荷分散する C10K問題の解決方法1: サーバーの台数を増やす 23 ロードバランサー側にもC10K問題が発生しないように注意
Slide 24
Slide 24 text
C10K問題の解決方法2: シングルプロセスで捌く 頭のいい人は考えました 「マルチプロセス方式でプロセスIDの上限に引っかかるなら、シングルプロセス ・シングルスレッドで全リクエストを捌けばいいんじゃね?」 「これならコンテキストスイッチも必要なくね?」 「1つのDBコネクションを複数リクエストで使いまわせばファイルディスクリプター の問題もなくなるんじゃね?」 24 非同期・ノンブロッキングI/O
Slide 25
Slide 25 text
C10K問題の解決方法2: シングルプロセスで捌く 【同期・ブロッキングI/O(従来型)】 指示を出したら処理が終わるまでCPU側でひたすら待つ 25 炊飯 洗濯指示 炊飯指示 炊飯完了 洗濯完了 洗濯 ゲーム 料理 アイロンがけ 待機 待機
Slide 26
Slide 26 text
C10K問題の解決方法2: シングルプロセスで捌く 【非同期・ノンブロッキングI/O】 指示を出したら完了を待たずに別の処理を行う 26 洗濯指示 炊飯指示 炊飯完了 洗濯完了 炊飯 洗濯 ゲーム 料理 アイロンがけ 待機
Slide 27
Slide 27 text
C10K問題の解決方法2: シングルプロセスで捌く 非同期・ノンブロッキングI/Oの特徴 ● ⭕処理の完了を待っている間に別の処理をできる ○ CPUの待ち時間が減るので効率的 ● ⭕CPUを使わない複数の処理を並列で実行できる ● ❌非同期処理の記述が複雑になりがち ○ 投げっぱなしで済む処理はあまり多くないので、どこかで完了を待ち合わせる 必要がある 27
Slide 28
Slide 28 text
Node.jsのアプローチ 28
Slide 29
Slide 29 text
Node.jsのアプローチ ● シングルプロセス・シングルスレッド ○ 処理がキューに追加され、先に入ったものから順次処理される ○ コンテキストスイッチが発生しない ● CPUを使わない処理(通信など)は非同期で行われる ○ 処理が終わったらコールバック関数が呼ばれる ○ コネクション(ファイルディスクリプター)を使いまわせる 29 (きちんとプログラミングすれば)C10K問題は発生しない
Slide 30
Slide 30 text
Node.jsのアプローチ 30 いい感じにHTML出力 リクエストC リクエストB リクエストA キュー リクエストC リクエストB リクエストA 1. DBからデータを取り出す 2. いい感じにHTML出力 リクエストC リクエストB DB 1. データ取得指示 2. データ取得後に 次の処理がキューに積まれる キューの処理はできるだけ短い時間で終わらせるのが鉄則
Slide 31
Slide 31 text
Node.jsを使うときの注意 31
Slide 32
Slide 32 text
Node.jsを使うときの注意1: 非同期処理 32 ● コールバック関数を使いまくるとネストが深くなって見づらい ● コールバック方式だと例外処理を書きづらい ○ Promiseやasync/awaitを使いこなそう ● 面倒だからといって絶対に同期版を使わないこと ○ 処理に時間がかかる=キューが詰まる=他のリクエストを処理できない 他の言語からの移行者は要注意
Slide 33
Slide 33 text
Node.jsを使うときの注意2: グローバル変数 33 ● Node.jsはシングルプロセス・シングルスレッド ● つまりグローバル変数は全リクエストで共有される ● つまりリクエストの内部状態をグローバル変数で管理すると別のリクエスト によって突然書き換えられてしまう ○ 例えばAccept-Languageの値(ja, en-US等) 他の言語からの移行者は要注意
Slide 34
Slide 34 text
Node.jsを使うときの注意3: リソース管理 34 ● Node.jsはシングルプロセス・シングルスレッド ● つまりプロセスは動き続けることが前提 ● つまりリソースは自動的に解放されない=明示的に解放しないと枯渇し、 新しいリクエストを処理できなくなる ○ メモリーはGCが回収してくれるが… 他の言語からの移行者は要注意
Slide 35
Slide 35 text
Node.jsを使うときの注意4: 一部のバグが全体に影響 35 ● Node.jsはシングルプロセス・シングルスレッド ● つまり接続が切れてもプロセスは実行され続ける ● つまり間違えて無限ループを入れてしまったら最後、新しいリクエストを処 理できなくなる ○ マルチプロセスでは接続を切れば無限ループは消える 他の言語からの移行者は要注意
Slide 36
Slide 36 text
Node.jsを使うときの注意5: CPUを使いまくる処理 36 ● Node.jsはシングルプロセス・シングルスレッド ● つまり1つの関数が終わるまで他のリクエストを処理できない ● つまりCPUリソースを大量に消費する処理には不向き ○ 別プロセスや別サービスとしてNode.jsの外側に置く工夫が必要 他の言語からの移行者は要注意
Slide 37
Slide 37 text
まとめ 37
Slide 38
Slide 38 text
まとめ ● Node.jsはJavaScriptの実行環境だよ ● C10K問題を解決できるよ ● シングルプロセス・シングルスレッドだよ ● 非同期I/Oを使ってるよ ● 他の言語から移行するときは色々注意しようね ● 手品に興味がある人はおはなししましょう 38
Slide 39
Slide 39 text
まとめ 目標(再掲) ● Node.jsが解決するものを理解する(何がうれしいの?) ● 他の言語との違いを理解する(他とどう違うの?) ● バックエンド開発の注意点を理解する(何に気をつければいいの?) 39 お わ か り い た だ け た だ ろ う か
Slide 40
Slide 40 text
https://shimataro.me/ 40 「さくらのナレッジ」にも投稿しています https://knowledge.sakura.ad.jp/24148/