Nextcloudにおけるphp-fpmのチューニング

# やたらNextcloudの動作が重い
前回Nextcloudのセットアップを記事にしましたが、そのまま使うとメモリが足りなかったりCPUのスレッドを食いつぶしたりすることが判明したので、それぞれのスペックに合わせたチューニングを書いておこうと思います。

# 前提条件
* php-fpm+nginxの環境で動作していること。
* Nextcloudの最低推奨メモリ量である512MB以上を割り当てられるシステムメモリが搭載されていること。
* php-fpmのプロセスマネージャモードがdynamicになっていること。

# PHP-FPMのプロセスに関する項目の解説

### pm(プロセスマネージャモード)および関連設定値
プロセスマネージャが子プロセスの数を制御する方法と、子プロセスの最大、最小数の設定値。

```
static
 >  子プロセスの数を固定して稼働させる。
    負荷が掛かってもメモリ使用量とCPU使用率があまり変化しない分、パフォーマンスが低下しやすい。

ondemand
 > これについてはよく把握出来ていません。すみません。

dynamic <-今回はこの設定になっている前提でチューニングをします。
 > 関連設定の内容によって、起動する子プロセスの数を動的に制御する。
 > 設定を間違えると必要も無いのに大量のプロセスを起動してハングアップを起こす可能性がある。

    dynamicモードの設定値
    
      > pm.max_children
      > 作成される子プロセスの最大数。
      > 高負荷状態での最大数と考えてok。

      > pm.start_servers
      > php-fpm本体(マスタープロセス)を起動した時に作成される子プロセスの数。
      > pm設定がdynamicの場合のみ有効。

      > pm.min_spare_servers
      > アイドル時(低負荷時)に起動しておく子プロセスの最小数。
      > リソース消費の少ないサービスならば極端な話1でもいい。

      > pm.max_spare_servers
      > アイドル時(低負荷時)に起動しておく子プロセスの最大数。
```

# 各値の暫定設定
適当に打ち込んで都度都度修正していたら一生終わらないので、ある程度の基準を設定する。

* 各設定値はCPU使用率を考えて計算値*2になるようにする。
* メモリはそちらに合わせていく。

### サーバーの搭載メモリ

```
$ free
              total        used        free      shared  buff/cache   available
Mem:        8008576      945972      201244      238784     6861360     6565280
Swap:             0           0           0
```
totalを1/1000にしておおよそ4000で4GB、8000で8GB、16000で16GBとする。

### CPUスレッド数
こちらは4スレッドCPUとして計算していく。
なおコア数、メモリ量別に多いであろう組み合わせは後ほど表に記述する。

## pm.max_children
この値を他の値とphp.ini内の`memory_limit`設定の基準にする。

4スレッドCPU、8GBのRAMの場合、スレッド数とプロセス数が釣り合うのは
phpの`memory_limit`が2048Mで、搭載RAMが8000なので
`8000 / 2048 = 3.9`
4なのだが、基準によって*2するので、この場合の`max_children`の値は8となる。
軽いサービスの場合は16などに設定してもいいが、Nextcloudは重量級のためロードアベレージの低下を目的にCPU*2程度にしておく。

:::note
十分な余裕のあるCPUとメモリ構成なら、128程度でも良いかもしれません。
他の項目はconfigに記載のある基準に沿って設定してみて下さい。
:::

## pm.start_servers
マスタープロセスを起動したときの子プロセス数。
とりあえずメモリの35%を使用する設定にする。

`8000 * 0.35 / 2048 = 1.36`

ここはウルトラ適当でOKなので基準に従いおおよそで2にしておく。

## pm.min_spare_servers
最小負荷時のプロセス数なので、`start_server`時と同じ2でOK。

## pm.max_spare_servers
ここはメモリの70%を目安にして、
`8000 * 0.7 / 2048 = 2.7`
3なので、こちらも基準に従い6にする。


### テスト
この状態で起動して、ファイルのアップロードや動画の再生などをしてみて異常がなければOK。

```
WARNING: [pool www] server reached pm.max_children setting (8), consider raising it
```
のようなエラーが出る場合は、値を絞りすぎているのでmax_childrenの値を少しづつ上げて調整する。

# おおよそのメモリ設定値の目安

|   | 4GB | 8GB | 16GB |
|:-:|:-:|:-:|:-:
| 2T  |  2048MB |  4096MB  |  8192MB |
| 4T | 1024MB  | 2048MB  | 4096MB  |
| 8T |  512MB |  1024MB |  2048MB |
これを参考にphp.iniの`memory_limit`と各設定値をチューニングしてください。

## 追記
やたらI/Owaitが発生するのでmariaDB側の設定も見直してみました。
/etc/my.cnf.d/server.cnfの[server]ディレクティブ以下に追記します

```
[server]
skip-name-resolve
innodb_buffer_pool_size = 512M
innodb_buffer_pool_instances = 1
innodb_flush_log_at_trx_commit = 2
innodb_log_buffer_size = 64M
innodb_max_dirty_pages_pct = 90
query_cache_type = 1
query_cache_limit = 8M
query_cache_min_res_unit = 2k
query_cache_size = 128M
tmp_table_size= 64M
max_heap_table_size= 64M

```

## さらに追記
どうやらAPCuの最適化ができていなかったようなので、こちらも正しく設定してあげます。

``` file:/etc/php.d/10-opcache.ini
opcahce.enable=1
opcache.enable_cli=1
;opcache.memory_consumption=128
 
↓変更
;opcahce.enable=1
;opcache.enable_cli=1
opcache.memory_consumption=2048
```

``` file:/etc/php.d/40-apcu.ini
;apc.shm_size=32M
;apc.ttl=3600
;apc.gc_ttl=3600

↓変更
;apc.shm_size=1024M
;apc.ttl=86400
;apc.gc_ttl=86400
```