/levelup-nodejs

Learning node.js

Primary LanguageJavaScript

『レベルアップNode.js』の学習用レポジトリ

第1・2章メモ

dependenciesになんかパッケージをインストールしたとき

"dependencies": {
	"express": "^4.17.1"
}

^ ← これはキャレットと読むらしい。

キャレットがあると、完全なバージョン固定にならない! 完全なバージョン固定にするには、、、

  1. package.jsonを開いてキャレットを削除したり、
  2. インストールする時に、npm install --save-exact express としたり

でもこれは面倒。それを解決するのが、、、、「.npmrc」ファイル!!! はい、早速よく分からんファイル名。なんやねんrcって。 場所は、ホームディレクトリ直下にあった! Qiitaの記事も載っけておこう。 project毎のnpmコマンドをいい感じにするnpmrc & config達 - Qiita

npx something-package --initは使えるね。

パッケージ選定基準

  1. メンテナンスが継続されているか(メンテナンス性) →最終更新日、コントリビューター数
  2. パッケージに関する情報量(人気や知名度) →GitHubスター数、ネット検索ヒット件数

パッケージ名を間違えてマルウェアに感染する事例あり!!

タイプミスでマルウェアに感染とか笑えん。。。

間違えない為の対策

リポジトリーのページで記載されている正規のコマンドを使う NPMのページに行って、そこからコピペする

Yarn

Yarnは速い、安全、信頼!がコンセプト。NPMとも互換性がある。

第3章メモ

シングルプロセスとシングルスレッド

Node.jsは単一のプロセスと単一のスレッドだけで複数のリクエストを処理する!

はい、もう意味わからん。

プロセスって何?

プロセスとは、処理のことである。情報処理においてプログラムの動作中のインスタンスを意味し、プログラムのコードおよび全ての変数やその他の状態を含む。オペレーティングシステム によっては、プロセスが複数のスレッドで構成される場合があり、命令を同時並行して実行する。(from wiki)

プログラムの動作中のインスタンスってのが、正確かどうかわからないけど、Macで立ち上げるアプリ(VSCodeとかChromeとか)一つ一つのこと。

もちろんそれぞれのアプリを一つのプロセスで複数のスレッドで立ち上げることも出来るのか?でもそれのデメリットは複数スレッドを立ち上げて、そのうちの一つがプロセスをストップさせるようなこと(クラッシュ?)が発生すると、芋づる式に他の健全なスレッドも死んでしまう危険性がある。

スレッドって何?

スレッドとは、CPU利用の単位。プロセスに比べて、プログラムを実行するときのコンテキスト情報が最小で済むので切り替えが速くなる。スレッドは、thread of executionという言葉を省略したものである。 プログラミングの観点からみると、アプリケーションの処理の「実行の脈絡」は1つでないことが多い。(from wiki)

あかん、wikiじゃわからん。 スレッド (thread)とは|「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典も参考にしよう。

うん、スレッドについてはなんとなーくわかった。

よしこれも読んで参考にしよう

まぁ言ったら、「並行処理」があるか無いかの違いらしい。

はい、並行処理って何?

もうわからん言葉が出てきすぎ、、、でもがんばれ。 これを読むのだ。なんか題名にすでに「並行」処理 vs「並列」処理って。。。 【小ネタ】並列処理とは何か?そして並列処理と並行処理の違いとは? - Qiita

並行処理は1つのコアで各プロセスを高速に切り替えて1処理ずつ行なっていると書きましたね。これに比べて並列処理は実際に複数のコアで同時に処理を行なっていることを指しています。

んー、シングルスレッドは並行処理(一つのコアが高速で切り替わって処理を行うこと)がない、って感じかな。

マルチプロセッシングモジュール(MPM)ってなんやねん!

まぁ、単一プロセス、単一スレッドは、なんとなくわかったけど、Node.js以外にもWebサーバー向けのソフトウェアは他にもある。そうApache!

なんか知らんけど、preforkっていうモジュールがUnixではデフォルト設定されていることが多いらしく、そのpreforkが子プロセスをいくつも生成して複数のリクエストを捌くんだと。。。

マルチプロセッシングモジュール (MPM) - Apache HTTP サーバ バージョン 2.4

クラスタリング

Node.jsは基本シングルプロセス・シングルスレッドで、効率的なサーバー稼働を実現するけど、逆にマルチプロセスじゃないから4コアCPUでも1コアCPUしか使えないから残りの3つのCPUコアが遊んでしまうデメリットがあると、基本的には!

そこでクラスタリングが登場。

pidってなんやねん

例に使われてるコードになんかpidって出てきてるよー、わからんよー。

プロセスID (PID)とは|「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典

Process Identifier、略してPID。おけ。わかった。

クラスタリングを使わずにマルチプロセス化することもできる

単純にNodeを複数走らせればOK。でも、ポートNoを変えないと、ポート衝突が起きてしまう。

クラスタリングの大きいメリットはポート衝突が無いこと。

マスタープロセス(親プロセス)から複数の子プロセスにForkすることできて、子プロセス等は一つのポートを親プロセスと共有することを許されている!だから複数ポートの管理をclusterモジュールがやってくれるってこと。便利。

Node.jsのClusterをセットアップして、処理を並列化・高速化する!!!

IPCを使っているから、マスターは各ワーカー(多分、子プロセスのこと)にポートハンドルを送るだけ。

あかん、、またよくわからん言葉が出てきた。

IPCとは、コンピュータ上で実行中のプログラムの間でデータをやり取りするための仕組み。あるプログラムから別のプログラムへデータやメッセージを通知したり、データの提供依頼や処理依頼を行ったり、依頼に対する結果を返したりすることができる。

へぇー

  • 何、ポートハンドルって うん、これはググったけど明確に何かを説明しているものが無かったから、飛ばす!

Clusterはロードバランサーも兼ねている

はい、いつも通りわからん。

  • ロードバランサーって?

ロード(load、負荷)+バランサー(Balancer、平衡を保つためのもの)で、サーバーやネットワークに関連する用語であり、装置の名称です。この仕組みにより、Webサイトへのアクセス集中やサーバー故障などの場合でも、アクセス中の利用者に安定したサービス提供を継続可能になります。参考→ロードバランサーとは?負荷分散の仕組み

ロードバランサーには2つの種類があるようだ。
Two-Arm(inline) One-Arm
配置場所 通信経路上 見た目はサーバー類と並列
メリット 構成がシンプル 負荷軽減、ロードバランサー自体がボトルネックにならない
デメリット ロードバランサー自体を冗長化しないと機器の障害対応ができない 通信経路を把握しづらい

なんで腕(Arm)が1本(One)とか2本(Two)とかで区別しているんじゃ?わからん。
2本なのはクライアントとサーバーを繋ぐ、入口と出口があるから2つ?
じゃあ、1本はどういうこと?誰か教えてー。

ロードバランサー(Two-Arm)は、
  1. HTTP(S)リクエストをサーバーに振り分ける
  2. 通信データを暗号化・復号化
  3. リクエストがすべて集約される
ロードバランサーの役割は、
  1. 速度低下を防ぐ ・・・ 処理件数が増加するとサーバーのリソース(CPUやメモリなど)を奪い合うから低速になるんだと
  2. メンテ中あるいはダウンしたサーバーへリクエストを送らない ・・・ 確かに止まってるサーバーにリクエスト送ったらクライアントが困るよね
  3. 特定のユーザーのアクセスを同じサーバーへ送る ・・・ パーシステンス(persistence/永続性、っていう英単語)と呼ぶらしい。一連の処理を保つことが出来るんだと。セッションとかクッキーとかそうゆう系かな。。。知らんけど。
負荷分散はロードバンランサー以外でもいける。DNSラウンドロビン!!!

ロードバランサーを使わんくても負荷分散は可能。それがDNSラウンドロビンだ。(ヤバイ、知らんこと多すぎ。。。)
DNSサーバーの設定ファイルの一部に、設定情報を書き込んで実現する。。。はぁ。。。
DNSサーバーに複数のipアドレスを登録しておいて、リクエストが来た時に順次アクセスするサーバーを変える。

3台サーバーが登録しておいて、リクエストが来たら、まずはAサーバーに、次のリクエストにはBサーバーに、その次はCサーバー。4つ目のリクエストはAサーバーに、5つ目は、、、、みたいな感じかな。

ロードバランサーとDNSラウンドロビンの比較

価格面ではDNSラウンドロビンが安い。設定だけ。 でも、DNSラウンドロビンは、、サーバーがぶっ壊れた時の障害通知が通常は不可能だし、永続性・persistenceがないから、オンラインショッピング向きじゃない。あと、負荷の大小に関係なく、馬鹿の一つ覚えみたいに、A→B→C→A→B→C。。。というふうにリクエストを割り振る。柔軟性に欠ける。

んー、ロードバランサーの方が使えるんじゃないかって気がするが、どうなんだろうか。頭の片隅にそっとおいておこう。

Clusterの設定は「cluster.schedulingPolicy」という設定で切替可能!
  • cluster.SCHED_RR ・・・ ラウンドロビン
  • cluster.SCHED_NONE ・・・ OSに任せる

その他小話(コンピューターの歴史)

インターネットが普及する前の時代では、コンピュータそれ自体がスタンドアローンで動くことが前提で、マルチプロセスが普通だったらしい。でもインターネットが普及してたくさんのWebサービス・アプリが出てきて、コンピュータがそれまでのようにマルチプロセス・マルチスレッドで処理していてはリソース活用に無駄が多く、それを改善しないといけなくなった。

そこでJavaがJVM(Java Virtual Machine)で、シングルプロセス・マルチスレッドという仕組みを実現して、色々と改善された。

Node.jsは更にコンピュータのCPUとかメモリとかのリソース活用を効率的に行う為に、シングルプロセス・シングルスレッドという仕組みを実現させてその目的を達成しようとした。

ちなみに、この小話は人から聞いて自分なりの解釈を書いているだけだから詳細が間違っているかもしれないから、今後この辺は勉強していきたいと思う。(間違っているところあったら教えてください...)

プロセスマネージャー

アプリケーション・サーバーに似ていて、デプロイメントを容易に行えるようにして、可溶性を実現し、アプリケーションを実行時に管理できるようにする、アプリケーションの「コンテナー」です。

デーモンって何?

第一印象は、「まじ悪いやつ」だよね。間違いない。

デーモンを一言で表現するならば、常駐プログラムとして動作するバックグラウンドプロセス、です。

はぁ。普通にnodeを起動するとフォアグラウンドプロセスになるらしい。

参考:

コンピュータソフトウェアのプロセスにおいて、バックグラウンドは相対的に低い優先度で動作し、入力がごく少ないか全くなく、最小限の出力を行うプロセスを表す。(wiki)

nodeをバックグラウンドプロセスとして起動するには&を後ろに付けるとOK

$ node app.js &
[1] 90694 // 生成されたバックグラウンドプロセスのIDが出力される

プロセスマネージャーと使ったデーモン化の利点

  • アプリケーションが異常終了した場合に自動的に再始動する(高可溶性の実現)
  • ランタイム・パフォーマンスとリソース使用料に関するインサイトを得る
  • パフォーマンスを向上させる為に設定を動的に変更する
  • クラスタリングを制御する

Forever は、特定のスクリプトが確実に継続的 (永続的) に実行されるようにするための単純なコマンド・ライン・インターフェース・ツールです。Forever のインターフェースは単純であるため、Node.js アプリケーションおよびスクリプトの小規模なデプロイメントを実行するのに理想的です。

$ forever start app.js 
$ forever logs
$ forever list
$ ps aux | grep app.js 
$ kill 3220
$ ps aux | grep app.js 
$ forever logs app.js 
data:    app.js:3217 - master 3217 is running
data:    app.js:3217 - worker 3218 started
data:    app.js:3217 - worker 3219 started
data:    app.js:3217 - worker 3221 started
data:    app.js:3217 - worker 3220 started
data:    app.js:3217 - worker 3220 died
data:    app.js:3217 - exit null : SIGTERM
data:    app.js:3217 - worker 3291 started
  • オプションコマンド
$ forever start --watch app.js // --watchオプションおかげで
$ forever logs app.js // 例えばapp.jsのコードに変更を加えてもログが残る。

PM2 は、ロード・バランサーが組み込まれた、Node.js アプリケーション用の実動プロセス・マネージャーです。PM2 では、アプリケーションの稼働を永続的に維持して、ダウン時間を発生させずに再ロードすることができ、共通のシステム管理タスクを簡単に実行できます。PM2 では、アプリケーションのロギング、モニター、クラスタリングを管理することもできます。

StrongLoop Process Manager (StrongLoop PM) は、Node.js アプリケーション用の実動プロセス・マネージャーです。StrongLoop PM には、ロード・バランシング、モニター、マルチホスト・デプロイメント、およびグラフィカル・コンソールが組み込まれています。

SystemDは現代のLinuxディストリビューションにおける、デフォルトのプロセスマネージャです。SystemDに基づいたノードサービスの実行は非常に簡単です。

→→ PM2 vs Forever vs StrongLoop PM 比較表