Strapiの公式ドキュメントにProcess managerというページがありpm2を使った例が紹介されています。
ですがこの例のまま設定すると本番環境のホストサーバーのCPUが2つ以上ある場合、CPUリソースが無駄になります。
例えばコアが2つある場合
pm2 start --name="sample" server.js -i 2
と実行するとパフォーマンスが向上します。
以下、一応検証した結果のまとめ
セットアップ
StrapiをローカルPCのDocker上で動作させます。
公式の手順に沿ってこんな感じでプロジェクトを作りました。
npx create-strapi-app@latest strapi_20220628
cd strapi_20220628
npm i
npm run start
次にパフォーマンス測定のためにAPIを作る必要があります。
適当なコンテンツタイプを作成し、データを1000件ほど投入します。
管理画面から入れるのは骨が折れるのでコードで書きます。例えばこんな感じに
## sample.js
const axios = require('axios')
const createArticle = async () => {
for (let i = 0; i < 1000; i++) {
const response = await axios.post('http://localhost:1337/api/articles', {
data: {
title: 'hello',
content: 'world!world!world!world!world!world!world!',
}
})
console.log(response.status)
}
}
createArticle()
同期で1000件実行してるのはローカルなので・・と多めに見てもらえると😅
上記実行前にSettings→Rolesから当該コンテンツタイプのcreateとfindをpublicで許可しておく必要があります。これで準備OK
とりあえずAPIレスポンスを測定
実行時間を簡単に測りたいのでabコマンドで実行します。
ab -c 100 -n 5000 http://localhost:1337/api/articles
↓上記コマンドを3回実行した結果
# 1回目
Time taken for tests: 7.616 seconds
Complete requests: 5000
Failed requests: 0
Total transferred: 31305000 bytes
HTML transferred: 27255000 bytes
Requests per second: 656.55 [#/sec] (mean)
Time per request: 152.311 [ms] (mean)
# 2回目
Time taken for tests: 6.638 seconds
Complete requests: 5000
Failed requests: 0
Total transferred: 31305000 bytes
HTML transferred: 27255000 bytes
Requests per second: 753.19 [#/sec] (mean)
Time per request: 132.769 [ms] (mean)
# 3回目
Time taken for tests: 6.227 seconds
Complete requests: 5000
Failed requests: 0
Total transferred: 31305000 bytes
HTML transferred: 27255000 bytes
Requests per second: 802.94 [#/sec] (mean)
Time per request: 124.542 [ms] (mean)
コアを2つにしてStrapi起動
まずはpm2をインストールします。
npm install -g pm2
# 起動
pm2 start --name="sample" server.js -i 2
そしてもう一度測ってみました。
# core 2つ 1回目
Time taken for tests: 5.228 seconds
Complete requests: 5000
Failed requests: 0
Total transferred: 31305000 bytes
HTML transferred: 27255000 bytes
Requests per second: 956.43 [#/sec] (mean)
Time per request: 104.555 [ms] (mean)
# core 2つ 2回目
Time taken for tests: 4.287 seconds
Complete requests: 5000
Failed requests: 0
Total transferred: 31305000 bytes
HTML transferred: 27255000 bytes
Requests per second: 1166.38 [#/sec] (mean)
Time per request: 85.735 [ms] (mean)
# core 2つ 3回目
Time taken for tests: 3.761 seconds
Complete requests: 5000
Failed requests: 0
Total transferred: 31305000 bytes
HTML transferred: 27255000 bytes
Requests per second: 1329.47 [#/sec] (mean)
Time per request: 75.218 [ms] (mean)
# core 2つ 4回目
Time taken for tests: 5.183 seconds
Complete requests: 5000
Failed requests: 0
Total transferred: 31305000 bytes
HTML transferred: 27255000 bytes
Requests per second: 964.67 [#/sec] (mean)
Time per request: 103.663 [ms] (mean)
# core 2つ 5回目
Time taken for tests: 4.132 seconds
Complete requests: 5000
Failed requests: 0
Total transferred: 31305000 bytes
HTML transferred: 27255000 bytes
Requests per second: 1210.16 [#/sec] (mean)
Time per request: 82.634 [ms] (mean)
# core 2つ 6回目
Time taken for tests: 3.750 seconds
Complete requests: 5000
Failed requests: 0
Total transferred: 31305000 bytes
HTML transferred: 27255000 bytes
Requests per second: 1333.41 [#/sec] (mean)
Time per request: 74.996 [ms] (mean)
結果に波があったのでさっきより多い回数実行してみましたが、いずれもさっきより良い結果が出ています。
余談
パフォーマンス絡みでもう一つ検証したことがあります。
config/server.jsのserveAdminPanelをfalseにすると管理画面を無効にすることができます。
APIと管理画面を分離するようなサーバー構成の場合、これもパフォーマンス向上になるのではと思ったのですが結果はほぼ変わりありませんでした。
たしかにadmin系は開発時(strapi develop --watch-admin)の方がリソース食いそうですが、startにはほぼ影響ないんだろうか。。
CPU/メモリの動きを細かく追っていくと微々たる違いはあるかもですね。