【同期・非同期】PHPとnode.jsの違いについて
最近サーバーサイドはnode.jsを使っていたのですが、久しぶりにPHPに舞い戻りました。
PHPの記憶を失いつつあるので、迫っている応用情報の勉強もかねつつnode.jsとの処理の違いについてまとめたいと思います。
PHPとnode.jsは何が違う?
一言でいうと同期処理か非同期処理かです。
PHPは基本的にコードの上から順に処理を実行する=同期処理です。
非同期処理も可能らしいですが、工夫が必要です。
一方、node.jsは
スケーラブルなネットワークアプリケーションを構築するために設計された
非同期型のイベント駆動の JavaScript 環境
と公式で説明されています。
プロセスとスレッド
同期・非同期について説明する前に、プロセスとスレッドについてまとめます。
プロセスとは
プロセスとは、プログラムの実行中の状態を指します。
実行中の状態とは、プログラムがOSによって、メモリ上の領域を割り当てられ、そこでCPUとデータのやり取りを行い、演算処理されている状態です。
タスクマネージャを開くとchromeやdockerなど実行中のアプリが出てきますが、それらが別々のプロセスになります。プロセス同士はメモリを共有することはなく、互いに影響を及ぼしません。
余談ですが応用情報だとタスクという言葉で表現されているらしいです(厳密には違うらしいですが…)
スレッドとは
スレッドとは、CPUから見たプログラムの「実行単位」であり、プロセスに含まれます
マルチスレッドのメリット・デメリット
シングルスレッドのメリット・デメリット
PHP+apacheの問題点
PHPの同期I/Oの問題点
同期I/Oとは、I/O(入出力)処理の間、プログラムを停止(ブロッキング)してI/O処理を待たなければならないことを言います。
C10K問題
node.jsの非同期I/O
node.jsのブロッキングモデル
const fs = require('fs');
const data = fs.readFileSync('/file.md'); // ファイルが読み込まれるまでここでブロック
console.log(data);
moreWork(); // console.logの後に実行
moreWork()は、readFileSyncが正常終了されてconsole.log()が出力された後に実行されます。
Node.jsはシングルスレッド/シングルプロセスが原則ですので、こういった処理を長時間行うと後続の処理がなかなか実行されずサービスがまともに提供できなくなる可能性があります。
そのため、後述のノンブロッキングモデルを用いるのが一般的です。
node.jsのノンブロッキングモデル
const fs = require('fs');
fs.readFile('/file.md', (err, data) => {
if (err) throw err;
console.log(data);
});
moreWork(); // console.log の前に実行
Node.js はこの非同期 I/O を駆使して、時間軸で処理を分散することができます
結局非同期 I/O の何がうれしいの?
また、同期I/OであるPHPは上記非同期IOの強みが弱点となるので実装を工夫していく必要があります。
実際にPHPがどのように大量アクセスに対応しているかというと、apacheではなくnginxを使うケースがあるようです。nginxは非同期IOに対応していて、apacheの10~100倍のアクセスに耐えられるそうです。
nodejsは便利ではありますが、まだ対応しているサーバーが少なかったりします。
参考資料
https://blog.recruit.co.jp/rls/2019-12-13-node-async-io/
https://nodejs.org/ja/docs/guides/blocking-vs-non-blocking
https://dsinside.digitalstage.jp/entry/2021/03/15/171517