LoginSignup
47
43

More than 5 years have passed since last update.

Apache チューニング スクリプト (MaxClientsを自動計算する)

Last updated at Posted at 2016-07-13

Apache の MaxClients の設定値を自動計算する

MySQL のチューニングをサポートするスクリプトとして MySQLTuner が有名だが、似たような発想で Apache の MaxClients (Apache 2.4 以降は MaxRequestWorkers) の設定値を自動計算するスクリプトがある。

MaxClients の最適値に関する議論は「Apache の MaxClients の適正値」に別途まとめたので参照されたい。

海外製

海外製で一番それっぽいのが Apache2 Buddy だが、子プロセスの共有メモリなどは考慮せずに単純計算をしているようだ。結果的に MaxClients は小さい数字になるので、無難に設定したい場合はこれを利用すればよい。と思ったが、Remaining Memory の計算が特定のサービスの除算しかしてないので、分母のメモリ量が多くなり大きい数字になってしまう場合があるので注意。

        Your server's physical RAM:                                   993 MB
        Remaining Memory after other services considered:             993 MB
        Apache's MaxClients directive:                                256       <--------- Current Setting
        Apache MPM Model:                                             prefork
[ !! ]  Your MaxRequestWorkers setting is too high.
        Your recommended MaxRequestWorkers setting is between 168 and 187.      <------- Acceptable Range (10% of MAX)
        Max potential memory usage:                                   1354 MB
        Percentage of TOTAL RAM allocated to Apache:                  136.38  %
        Percentage of REMAINING RAM allocated to Apache:              136.38  %

子プロセスのメモリ出力

子プロセスのメモリ出力では、伊藤直也氏の記事で有名な shared_memory_size.pl の流れを汲んだ none_shared_memory_fetcher.pl が子プロセスの非共有メモリを計算してくれるが、 MaxClients の値は自分で計算する必要がある。

PID     RSS     SHARED          NONE_SHARED
12538   3780    3072 (81%)      708
12540   3048    2836 (93%)      212
12541   3060    2840 (92%)      220
12542   3152    2908 (92%)      244
12543   3060    2840 (92%)      220

自動計算

get_max_clients.sh は、不完全ではあるものの、子プロセスの共有メモリを考慮した MaxClients の数値を自動計算してくれるので、ぎりぎりを攻めたいようであればこれを利用すると良いだろう。

Memory Total / (Rss Average - Shr Average) = 1020076 / (3626 - 3263)
Memory Free  / (Rss Average - Shr Average) = 635560 / (3626 - 3263)
MaxClients = 1750 ~ 2810

海外製

Apachetuner.sh

Gustav Maskowitz (@gusmaskowitz) によるコンセプトの記録としてのシェルスクリプト。当人による後述の Apachebuddy.pl に代替されている。

コマンド
curl -sL https://raw.githubusercontent.com/gusmaskowitz/apachetuner/master/apachetuner.sh | sh
出力例
=========================SYSTEM=========================
CentOS release 6.8 (Final)

Server Name:                    localhost.localdomain
Total Physical Memory:          996 MB

=========================APACHE=========================
Version:                        Apache/2.2.15 (Unix)
RPM:                            httpd-2.2.15-53.el6.centos.x86_64
httpd binary:                   /usr/sbin/httpd
Whats running on port 80        12538/httpd
Apache Architecture:            64-bit
Serverlimit is:                 256
MaxClients is:                  256
httpd root                      /etc/httpd
httpd server config file        /etc/httpd/conf/httpd.conf
httpd default errorlog          /etc/httpd/logs/error_log

=========================PHP============================
/etc/php.ini memory_limit is:   128M

=====================APACHE RUNTIME=====================
Apache user:                    apache
Average Memory use:             2.07 MB per child
Number of children:             8

=========================REPORT==========================
Current memory footprint        16.56 MB
Maximum memory footprint        529.92 MB (53% of installed RAM)

System memory divided by MaxClients             4
System memory divided by Apache child size      481

Apache Buddy

Apache Buddy は Gustav Maskowitz (gusmaskowitz) により apachetuner.sh の代替として作成されたが、ohaio-solo に同等の実装がされているのでアクティブな開発は行っていない、としている。

コマンド
curl -sL apachebuddy.pl | perl
出力例
########################################################################
# Apache Buddy v 0.3 ###################################################
########################################################################
Gathering information...
We are checking the service running on port 80
The process listening on port 80 is /usr/sbin/httpd
The process running on port 80 is Apache/2.2.15 (Unix)
Apache has been running 0d 0h 18m 39s
The full path to the Apache config file is: /etc/httpd/conf/httpd.conf
Apache is using prefork model

Examining your Apache configuration...
Apache runs as apache
Your max clients setting is 256

Analyzing memory use...
Your server has 996 MB of memory
The largest apache process is using 2.08 MB of memory
The smallest apache process is using 2.08 MB of memory
The average apache process is using 2.08 MB of memory
Going by the average Apache process, Apache can potentially use 532.49 MB RAM (53.47 % of available RAM)
Going by the largest Apache process, Apache can potentially use 532.49 MB RAM (53.47 % of available RAM)

Generating reports...
### GENERAL REPORT ###

Settings considered for this report:

        Your server's physical RAM:             996MB
        Apache's MaxClients directive:          256
        Apache MPM Model:                       prefork
        Largest Apache process (by memory):     2.08MB
[ OK ]  Your MaxClients setting is within an acceptable range.
        Max potential memory usage:             532.48 MB

        Percentage of RAM allocated to Apache   53.47 %

-----------------------------------------------------------------------
-----------------------------------------------------------------------

Henry Wong (somethingweird) フォーク

apachebuddy.pl に対する CentOS 7.0 - Apache 2.4.6 対応パッチ版

curl https://raw.githubusercontent.com/somethingweird/apachebuddy.pl/master/apachebuddy.pl | perl

Apache2 Buddy

Richard Forth (@richardforth) による Apache Buddy のフォーク。
物理メモリをApacheプロセスの平均メモリで割った値、およびその9割を MaxClients の許容範囲としていて、子プロセスの共有メモリなどは考慮していない模様。
netstat コマンドを使用しているため RHEL/CentOS 7.x では事前に yum install net-tools の実行が必要。

コマンド
curl -sL apache2buddy.pl -o apache2buddy.pl
perl apache2buddy.pl -r
出力例
[ CRITICAL ] Going by the average Apache process, Apache can potentially use 1354.25 MB RAM:
                Without considering services: 136.38 % of total installed RAM
                Considering extra services: 136.38 % of remaining RAM
[ CRITICAL ] Going by the largest Apache process, Apache can potentially use 1354.25 MB RAM:
                Without considering services: 136.38 % of total installed RAM
                Considering extra services: 136.38 % of remaining RAM
--------------------------------------------------------------------------------
Apache2buddy.pl report for server: localhost (14.3.31.162):

Settings considered for this report:

        Your server's physical RAM:                                   993 MB
        Remaining Memory after other services considered:             993 MB
        Apache's MaxClients directive:                                256       <--------- Current Setting
        Apache MPM Model:                                             prefork
[ !! ]  Your MaxRequestWorkers setting is too high.
        Your recommended MaxRequestWorkers setting is between 168 and 187.      <------- Acceptable Range (10% of MAX)
        Max potential memory usage:                                   1354 MB
        Percentage of TOTAL RAM allocated to Apache:                  136.38  %
        Percentage of REMAINING RAM allocated to Apache:              136.38  %
--------------------------------------------------------------------------------

子プロセスのメモリ出力

shared_memory_size.pl (naoya版)

Linux のプロセスが Copy on Write で共有しているメモリのサイズを調べる - naoyaのはてなダイアリー
大変よく参照されるが、以下の shared_memory_size.pl は Linux::Smaps が必要なため、他のスクリプトを利用する方が良いだろう。

スクリプト
cat << _EOF_ > shared_memory_size.pl
#!/usr/bin/env perl
use strict;
use warnings;
use Linux::Smaps;

@ARGV or die "usage: %0 [pid ...]";

printf "PID\tRSS\tSHARED\n";

for my \$pid (@ARGV) {
    my \$map = Linux::Smaps->new(\$pid);
    unless (\$map) {
        warn \$!;
        next;
    }

    printf
        "%d\t%d\t%d (%d%%)\n",
        \$pid,
        \$map->rss,
        \$map->shared_dirty + \$map->shared_clean,
        int(((\$map->shared_dirty + \$map->shared_clean) / \$map->rss) * 100)
}
_EOF_
コマンド
perl shared_memory_size.pl `pgrep httpd`
出力例
PID     RSS     SHARED
4847    8272    6180 (74%)
4876    5544    5292 (95%)
4935    5544    5292 (95%)
4976    5544    5292 (95%)
4999    5544    5292 (95%)

shared_memory_size.pl (yumatsumo版)

プロセスのCoW共有しているメモリのサイズ - マツモブログ
Linux::Smaps 不要版。

スクリプト
cat << _EOF_ > shared_memory_size.pl
#!/bin/env perl

use strict;
use warnings;

use List::Util ();

@ARGV or die "usage: %0 [pid ...]";

my @output;

for my \$pid (@ARGV) {
   die "invalid pid '\$pid'" if \$pid =~ /\D/;
   my @smaps = \`cat /proc/\$pid/smaps\`;
   die if \$? != 0;
   my @shared = map { /(\d+)\s+kB/; \$1 } grep { /^Shared_(Clean|Dirty)/ } @smaps;
   my \$shared_total = List::Util::sum(@shared);
   my @rss = map { /(\d+)\s+kB/; \$1 } grep { /^Rss/ } @smaps;
   my \$rss_total = List::Util::sum(@rss);
   my \$parcent = sprintf '(%d %%)', int((\$shared_total / \$rss_total) * 100);
   push @output, [\$pid, \$rss_total, \$parcent];
}

unshift @output, [qw(PID RSS SHARED)];

for my \$out (@output) {
    print join "\t", @\$out;
    print "\n";
}
_EOF_
コマンド
perl shared_memory_size.pl `pgrep httpd`
出力例
PID     RSS     SHARED
2505    3460    (75 %)
2506    2960    (93 %)
2507    2960    (93 %)
2508    2960    (93 %)
2509    2960    (93 %)
2510    2960    (93 %)

getmem.sh / getshmem.sh

Apacheのメモリ使用量を調べる - satooshi@blog

getmem.sh

スクリプト
cat << _EOF_ > getmem.sh
#!/bin/sh

#1 process name
if [ \$# -ne 1 ]; then
  exit
fi

# print header
printf "PID\tVmPeak\tVmSize\tVmHWM\tVmRSS\n"

# get memory size
pid=\`pgrep \$1\`

for p in \$pid
do
  if [ -f /proc/\$p/status ]; then
    vm=\`grep -e '^VmPeak:\|VmSize:\|VmHWM:\|VmRSS:' /proc/\$p/status | awk '{print \$2}'\`
    printf "%d\t%d\t%d\t%d\t%d\n" \$p \$vm
  fi
done
_EOF_
コマンド
sh getmem.sh httpd
出力例
PID     VmPeak  VmSize  VmHWM   VmRSS
2193    307688  307688  11828   11828
2194    307708  307688  6096    6096
2195    307708  307688  6096    6096
2196    307708  307688  6096    6096
2197    307708  307688  6096    6096
2198    307708  307688  6096    6096

getshmem.sh

スクリプト
cat << _EOF_ > getshmem.sh
#!/bin/sh

# \$1 process name
if [ \$# -ne 1 ]; then
  exit
fi

# print header
printf "PID\tRSS\tSHARED\n"

# get shared memory size
pid=\`pgrep \$1\`

for p in \$pid
do
  if [ -f /proc/\$p/smaps ]; then
    vm=\`grep -e '^Rss:\|^Shared_Clean:\|^Shared_Dirty:' /proc/\$p/smaps |
    awk '
      BEGIN {
        rss = 0;
        clean = 0;
        dirty = 0;
      }
      {
        if(\$1 == "Rss:") {
          rss += \$2;
        }
        else if(\$1 == "Shared_Clean:") {
          clean += \$2;
        }
        else if(\$1 == "Shared_Dirty:") {
          dirty += \$2;
        }
      }
      END {
        per = (rss == 0) ? 0 : (clean+dirty)*100/rss;
        printf("%d\t%d\t%d\n", rss, clean+dirty, per);
      }
    '\`

    printf "%d\t%d\t%d (%d%%)\n" \$p \$vm
  fi
done
_EOF_
コマンド
sh getshmem.sh httpd
出力例
PID     RSS     SHARED
2193    11832   8368 (70%)
2194    6208    6012 (96%)
2195    6208    6016 (96%)
2196    6208    6016 (96%)
2197    6208    6016 (96%)
2198    6208    6016 (96%)

smaps.sh

hollyなblog:2010-09-23の技術こねた
シェルスクリプト版。Perl も Linux::Smaps も不要。
単位としてKB、項目としてVSZ(Virtual Memory Size)が追加されている。

スクリプト
cat << _EOF_ > smaps.sh
#!/bin/sh

echo -e "PID\tVSZ\t\tRSS\tShared"
for pid in \$@; do
    smaps="/proc/\$pid/smaps"
    vsz=\$(grep -E "^Size" \$smaps | awk 'BEGIN{ num = 0 } { num += \$2 } END{ print num }')
    rss=\$(grep -E "^Rss" \$smaps | awk 'BEGIN{ num = 0 } { num += \$2 } END{ print num }')
    shared=\$(grep -E "^Shared" \$smaps | awk 'BEGIN{ num = 0 } { num += \$2 } END{ print num }')
    percent=\$(echo "scale=2; (\$shared / \$rss) * 100" | bc | cut -d "." -f 1)
    echo -e "\$pid\t\${vsz}KB\t\${rss}KB\t\${shared}KB(\${percent}%)"
done
_EOF_
コマンド
sh smaps.sh `pgrep httpd`
出力例
PID     VSZ             RSS     Shared
4847    232840KB        8272KB  6180KB(74%)
4876    232840KB        5544KB  5292KB(95%)
4935    232840KB        5544KB  5292KB(95%)
4976    232840KB        5544KB  5292KB(95%)
4999    232840KB        5544KB  5292KB(95%)

none_shared_memory_fetcher.pl

Apacheとかforkしたプロセスのメモリチューニングに関するメモとスクリプト | hirobanex.net
VSZ の代わりに NONE_SHARED が計算、出力されている。

スクリプト
cat << _EOF_ > none_shared_memory_fetcher.pl
#!/usr/bin/env perl
use strict;
use warnings;

@ARGV or die "usage: %0 [pid ...]";

printf "PID\tRSS\tSHARED\tNONE_SHARED\n";

for my \$pid (@ARGV) {
    open my \$fh, "< /proc/\$pid/smaps" or (warn \$! and next);
    my @rows = <\$fh>;
    my \$rss    = mem_size_fetcher('Rss',@rows) or next;
    my \$shared = mem_size_fetcher('Shared_Clean',@rows) + mem_size_fetcher('Shared_Dirty',@rows);
    printf
        "%d\t%d\t%d (%d%%)\t%d\n",
        \$pid,
        \$rss,
        \$shared,
        int((\$shared / \$rss) * 100),
        (\$rss - \$shared),
}

sub mem_size_fetcher {
    my (\$target,@rows) = @_;
    my \$mem_size = 0;
    for my \$row (@rows) {
        my (\$mem) = \$row =~ /^\$target:\s*(\d+)/i;
        \$mem_size +=(\$mem||0);
    }
    return \$mem_size;
}
_EOF_
コマンド
perl none_shared_memory_fetcher.pl `pgrep httpd`
出力例
PID     RSS     SHARED          NONE_SHARED
12538   3780    3072 (81%)      708
12540   3048    2836 (93%)      212
12541   3060    2840 (92%)      220
12542   3152    2908 (92%)      244
12543   3060    2840 (92%)      220
12544   3048    2836 (93%)      212
12545   3060    2840 (92%)      220
12546   3060    2840 (92%)      220
12547   3060    2840 (92%)      220

自動計算

get_max_client.php

apacheのMaxClientを算出するスクリプトを作った - webネタ

コマンド
curl -sL https://raw.githubusercontent.com/ryoppy/Get-MaxClients./master/get_max_client.php | php
出力例
--------------------------------
memorySize / (rssAverage - shrAverage) = 1020076KB / (5673KB - 5364KB) = 3301
MaxClient maximum value is 3301.
--------------------------------

kenjis フォーク

コマンド
curl -sL https://raw.githubusercontent.com/kenjis/Get-MaxClients./my_change/get_max_client.php | php
出力例
--------------------------------
rssAverage - shrAverage = (5673KB - 5364KB) = 309KB
memorySize / (rssAverage - shrAverage) = 1020076KB / 309KB = 3301
MaxClient maximum value is 3301.
--------------------------------

get_max_clients.sh

Apacheチューニング: MaxClientsに設定できる上限値を計算する - (DxD)∞
get_max_client.php のシェルスクリプト版。 $_MIN_MAX_CLIENTS については以下の通り。

空きメモリ量からMaxClientsを算出しています。ただし、起動済みのApacheプロセスが使用しているメモリ量を考慮していないので不完全です。

スクリプト
cat << _EOF_ > get_max_clients.sh
#!/bin/bash

_PIDS=(\`pgrep httpd\`)
_PROC_COUNT=\${#_PIDS[@]}

_MEMORY_TOTAL=\`free | grep Mem | awk '{print \$2;};'\`
_MEMORY_FREE=\`vmstat -a | awk 'NR==3{print \$4+\$5;};'\`
_RSS_TOTAL=0
_SHARED_TOTAL=0

for _PID in \${_PIDS[@]}; do
    _SMAPS=\`cat /proc/\$_PID/smaps\`
    _RSS=\`echo "\$_SMAPS" | grep Rss | awk '{value += \$2} END {print value;};'\`
    _SHARED=\`echo "\$_SMAPS" | grep Shared | awk '{value += \$2} END {print value;};'\`
    _RSS_TOTAL=\`expr \$_RSS_TOTAL + \$_RSS\`
    _SHARED_TOTAL=\`expr \$_SHARED_TOTAL + \$_SHARED\`
done

_RSS_AVERAGE=\`expr \$_RSS_TOTAL / \$_PROC_COUNT\`
_SHARED_AVERAGE=\`expr \$_SHARED_TOTAL / \$_PROC_COUNT\`
_PROC_MEMORY=\`expr \$_RSS_AVERAGE - \$_SHARED_AVERAGE\`
_MIN_MAX_CLIENTS=\`expr \$_MEMORY_FREE / \$_PROC_MEMORY\`
_MAX_MAX_CLIENTS=\`expr \$_MEMORY_TOTAL / \$_PROC_MEMORY\`

echo "Memory Total / (Rss Average - Shr Average) = \$_MEMORY_TOTAL / (\$_RSS_AVERAGE - \$_SHARED_AVERAGE)"
echo "Memory Free  / (Rss Average - Shr Average) = \$_MEMORY_FREE / (\$_RSS_AVERAGE - \$_SHARED_AVERAGE)"
echo "MaxClients = \$_MIN_MAX_CLIENTS ~ \$_MAX_MAX_CLIENTS"

exit 0
_EOF_
コマンド
sh get_max_clients.sh
出力例
Memory Total / (Rss Average - Shr Average) = 1020076 / (3626 - 3263)
Memory Free  / (Rss Average - Shr Average) = 635560 / (3626 - 3263)
MaxClients = 1750 ~ 2810

Apache 関連情報

47
43
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
47
43