Apacheにサーバーのメモリを食い尽くさせない


環境

  • Amazon Linux AMI 2018.03
  • Apache/2.4.34 (Amazon)

Apache(prefork)がサーバーのメモリを食い尽くしていたのでチューニングしました。
その際に行なった調査や計算をメモとして残します。

なお、preforkからeventに変更できる場合や、nginxに移行できるのであれば
そちらの方がいいかもしれません。
今回はあくまでpreforkをチューニングする前提での手順です。

サーバー物理メモリ確認

まず、サーバーの物理メモリを調べます

# cat /proc/meminfo | head -n 1
MemTotal:        2004484 kB

このサーバーの搭載メモリは2GBのようです。

現在のメモリ使用状況確認

まずサーバー全体の使用メモリを確認します。
以下のワンライナーで出します。(単位はMB)

# ps aux | awk '{print $6}' | awk '{sum=sum+($1/1024);cnt++;} END{print "sum="sum}'
sum=919.656

次にhttpdの子プロセスの使用メモリを確認します。
以下のワンライナーで出します。(単位はMB)

# ps aux | grep httpd | grep apache | awk '{print $6}' | awk '{sum=sum+($1/1024);cnt++;} END{print "sum="sum " cnt="cnt " ave="sum/cnt;}'
sum=804.273 cnt=20 ave=40.2137

出力結果は以下のようにしています。

項目 意味
sum 現時点のhttpd子プロセスが使っている総メモリ
cnt httpd子プロセスの数
ave httpd子プロセス1つが利用している平均メモリ

※補足

サーバー全体のメモリ使用量は前述の/proc/meminfoやfreeコマンドからでも出せるのですが
それだとpsコマンドの結果と少しずれてしまうのでpsコマンドに統一しています。

計算

ここまでで分かった事を整理します。

  • サーバーの搭載メモリ = 約2GB ・・・①
  • 現時点の総使用メモリ = 約920MB ・・・②
    • うち、Apache子プロセスの使用メモリ = 約800MB ・・・③
    • Apache子プロセス以外の使用メモリ = 約120MB ・・・④(②−③)
  • Apache子プロセス1つあたりが使うメモリ = 約40MB ・・・⑤

ここからざっくり計算していきます。

  • Apache子プロセス以外用に残すメモリ = 500MB ・・・⑥(④を元に超ざっくり&余裕を持って)
  • Apache子プロセスで使うメモリ = 1500MB程度 ・・・⑦(①−⑥)
  • 生成できるApacheプロセス数 = 35個程度 ・・・⑧(⑦÷⑤)

Apacheの設定にてこれを設定します。

<IfModule mpm_prefork_module>
StartServers               5
MinSpareServers            5
MaxSpareServers           10
ServerLimit               35 #先ほど計算した結果に変更
MaxClients                35 #先ほど計算した結果に変更
MaxConnectionsPerChild     0
</IfModule>

既存のApacheの設定ファイルに上記が設定されている箇所が存在しない場合は
httpd.confに追記するか/etc/httpd/conf.d/配下に新設定ファイルを作成して記載するのでも良いです。

他にも基本的にhttpd子プロセスは常時20個くらい動いていて欲しかったりして、
最終的に以下の設定にしました。

<IfModule mpm_prefork_module>
StartServers              20 #httpd起動時にプロセスを20個動かす
MinSpareServers            5
MaxSpareServers           20 #リクエスト待ちプロセスは最大20個とする
ServerLimit               35
MaxClients                35
MaxConnectionsPerChild  5000 #ある程度処理したら子プロセスには産まれ変わってもらう
</IfModule>