LIFULL Creators Blog

LIFULL Creators Blogとは、株式会社LIFULLの社員が記事を共有するブログです。自分の役立つ経験や知識を広めることで世界をもっとFULLにしていきます。

PHPコンパイルによる高性能のFastCGIウェブサーバー構築とチューニングに関するお話し(2)

こんにちは。新規事業本部・金融グループの金(成奉)です。

前回(PHPコンパイルによる高性能のFastCGIウェブサーバー構築とチューニングに関するお話し(1) - 株式会社ネクスト エンジニアBlog)に引き続き、FastCGI基盤ウェブサーバーのPHPコンパイル構築、チューニング、設定などについてお話したいと思います。

PHP高速化について

OPcache+APCu の構成でハイ・パフォーマンスPHP環境を構築します。OPcacheはネイティブのOPコードのキャッシュ機能をサポートし、APCuはユーザーデータのキャッシュ機能をサポートする。以前APCは両機能が一つになっていましたが、PHP5.5ではネイティブコードキャッシュのZend Opcacheがサポートされるようになりました。

PHP構築設定内容

apache2用のモジュール(prefork用)も一緒に生成します。 今回構築するサーバはFastCGIでの運用であるため、シェアド・オプションでコンパイルしたバイナリをインストールします。スレッドセーフ(Threads Safe)のPHPはまだ対応していないモジュール(PHPエクステンション)が多くあり、「Non Threads model」でコンパイルします。スレッドセーフにしたい場合は、「–enable-maintainer-zts」を追加します。スレッドセーフにコンパイルして構築すると、スレッドセーフに対応していないエクステンション(geos.cなど)を後で追加したくてもコンパイルできないため、とても不便です。残念なことに高機能のモジュールがコンパイルできないケースが多くて困る時がしばしばあります。

ミドルウェア・ビルド・ポリシについて

CentOS系では、できるだけ、開発ライブラリー(xxx-devel.x86_64)系は、yumのデフォルト・レポジトリからインストールするようにします。特に「openssl」は、コンパイルして、ビルドした場合、最近のHeartBleedと呼ばれたセキュリティ脆弱性が発見された際には、ライブラリーを含めてすべてコンパイルしなおさなければなりません。バージョンが合わないため、やむを得ず、ライブラリーを構築しなければならないケースは例外とします。apacheの場合も、特別な理由がなければ、yumのデフォルト・レポジトリからインストールし、設定でセキュリティ対策を行うことをお薦めします。その他、yumレポジトリにインストールするバイナリがなく、パフォーマンス対策を行う必要がある場合、コンパイル・インストールします。yumレポジトリについても、デフォルト以外のものを無やみに追加しないようなポリシでサーバーを構築していきます。

PHPビルドの事前準備

phpダウンロード

ビルドは/opt/srcディレクトリで行うと仮定します。
以下の作業はすべてroot権限で行います。

su -
cd /opt/src
wget -q http://jp1.php.net/get/php-5.5.16.tar.gz/from/this/mirror -O php-5.5.16.tar.gz
tar zxvf php-5.5.16.tar.gz

Shared Memory Allocationコンパイル・インストール

セッションを共有メモリで扱うとパフォーマンスは向上します。このライブラリーは、Threads Safeに対応していないモジュールです。Non Threads modelでの構築の場合、もしくはセション処理が専門用途のサーバーとしてビルドする場合、検討する価値はあるかもしれません。このエクステンションの設定はここでは行いません。

wget ftp://ftp.ossp.org/pkg/lib/mm/mm-1.4.2.tar.gz
tar zxvf mm-1.4.2.tar.gz
cd mm-1.4.2
./configure --prefix=/usr --libdir='${prefix}/lib64'
make
make install
cd ../

セッションは、下のようにRAMディスクにマウントして設定する方法もあります。

mkdir /tmp/ramdisk
chmod 777 /tmp/ramdisk
mount -t tmpfs -o size=512M tmpfs /tmp/ramdisk/
vi php.ini
session.save_path="/tmp/ramdisk"

Igbinaryモジュールセットアップ

cd /opt/src/php-5.5.16/ext
wget -q https://github.com/phadej/igbinary/archive/master.zip -O igbinary.zip
unzip igbinary.zip
mv igbinary-master igbinary

Redis(remote dictionary server)モジュールセットアップ

Redis KVS(格納するバリューがデータ構造)クライアントモジュール

cd /opt/src/php-5.5.16/ext
wget -q https://github.com/nicolasff/phpredis/archive/master.zip -O phpredis.zip
unzip phpredis.zip
mv phpredis-master redis

APCu(APC User Cache)モジュール

cd /opt/src/php-5.5.16/ext
wget -q https://github.com/krakjoe/apcu/archive/master.zip -O apcu.zip
unzip apcu.zip
mv apcu-master apcu

PHPコンパイル・オプション追加設定

セットアップしたモジュール(Extension)をconfigureに認識させます。

cd /opt/src/php-5.5.16
./buildconf --force

オプションに追加されているかを確認します。

./configure --help | grep "redis\|igbinary\|apcu"
  --enable-igbinary          Enable igbinary support
  --enable-redis           Enable redis support
  --disable-redis-session      Disable session support
  --enable-redis-igbinary      Enable igbinary serializer support

igbinay/redis/apcuは、ソースファイルをダウンロードして、
phpize; phpize; ./configure;make; make installコマンドでもインストールが出来ます。

ビルド環境構築

既にインストールされていればスキップします。

yum -y install autoconf
yum -y install automake
yum -y install libtool.x86_64
yum -y install flex.x86_64
yum -y install bison.x86_64
yum -y install gcc.x86_64
yum -y install gcc-c++.x86_64
yum -y install make.x86_64
yum -y install kernel-headers.x86_64
yum -y install kernel-devel.x86_64

PHPビルド環境構築

既にインストールされていればスキップします。
httpd-develはHTTPD用のPHPバイナリも一緒に生成するためです。
ライブラリーごと一行にしているのは、みやすくするためです。

yum install -y httpd-devel.x86_64
yum install -y libxml2-devel.x86_64
yum install -y bzip2-devel.x86_64
yum install -y libcurl-devel.x86_64
yum install -y libpng-devel.x86_64
yum install -y openjpeg-devel.x86_64
yum install -y freetype-devel.x86_64
yum install -y t1lib-devel.x86_64
yum install -y libXpm-devel.x86_64
yum install -y gd-devel.x86_64
yum install -y gmp-devel.x86_64
yum install -y libc-client-devel.x86_64
yum install -y libicu-devel.x86_64
yum install -y openldap-devel.x86_64
yum install -y libmcrypt-devel.x86_64
yum install -y mysql-devel.x86_64
yum install -y readline-devel.x86_64
yum install -y net-snmp-devel.x86_64
yum install -y libtidy-devel.x86_64
yum install -y libxslt-devel.x86_64
yum install -y libmcrypt-devel.x86_64
yum install -y libevent.x86_64
yum install -y libevent-devel.x86_64
yum install -y aspell-devel.x86_64
yum install -y enchant-devel.x86_64
yum install -y oniguruma-devel.x86_64
yum install -y unixODBC-devel.x86_64
yum install -y sqlite-devel.x86_64
yum install -y krb5-devel.x86_64

MySQLサーバー・インストール

使わないシステムでも、インストールしておけば結構便利になることが多いため、インストールしておきます。使わない時には、サービスから外しサービスを停止します。

yum install -y mysql-server.x86_64
サービス登録
chkconfig mysqld on
サービスから削除

使用しない場合は、サービスから削除しておきます

chkconfig mysqld off
確認
chkconfig --list mysqld

MySQL設定

cp /etc/my.cnf /etc/my.cnf.org

symbolic-links=0[mysqld_safe] の間に以下を追加します。

vi /etc/my.cnf
character_set_server=utf8
default-storage-engine=InnoDB
innodb_file_per_table
[mysql]
default-character-set=utf8
[mysqldump]
default-character-set=utf8

サービス起動(root)

service mysqld start

コマンド度実行と設定手順(初期設定)

この設定はセキュリティのため、必ず行います。

mysql_secure_installation

rootパスワード → そのままEnter
rootパスワード設定 → Y Enter
rootパスワード入力(2回) → ******* Enter
anonymousユーザ削除 → Y Enter
リモートのrootログイン禁止 → Y Enter
testデータベース削除 → Y Enter
設定反映 → Y Enter

ログイン確認

mysql -u root -p

パスワード入力 Enter

mysql>\s

上記設定したパスワードでログインができるか確認後終了

mysql> exit

サービスを止めます。

service mysqld stop

普段使わない時にはサービスから外します。

chkconfig mysqld off

Redisクライアントとサーバのインストール

世界的な流れとしては、以前よく使われたMemcachedよりは、Redisの方が主流になっています。そのため、Redisサーバーも一緒に構築します。

cd /opt/src

ダウンロードとインストール

wget -q http://redis.googlecode.com/files/redis-2.6.14.tar.gz
tar xzf redis-2.6.14.tar.gz
cd redis-2.6.14
make -j10
make install

Redis設定

rm -rf /etc/redis /var/lib/redis
mkdir /etc/redis /var/lib/redis
\cp src/redis-server src/redis-cli /usr/bin
\cp redis.conf /etc/redis
sed -e "s/^daemonize no$/daemonize yes/" -e "s/^# bind 127.0.0.1$/bind 127.0.0.1/" -e "s/^dir \.\//dir \/var\/lib\/redis\//" -e "s/^loglevel verbose$/loglevel notice/" -e "s/^logfile stdout$/logfile \/var\/log\/redis.log/" redis.conf > /etc/redis/redis.conf

Redisのサービススクリプト作成と設定

cat > "/etc/init.d/redis-server" <<'EOF'
#!/bin/sh
#
# redis-server        Startup script for the Redis Server
# 
# chkconfig:   - 85 15 
# description:  Redis is a persistent key-value database
# processname: redis-server
# config:      /etc/redis/redis.conf
# config:      /etc/sysconfig/redis
# pidfile:     /var/run/redis.pid

# Source function library.
. /etc/rc.d/init.d/functions

# Source networking configuration.
. /etc/sysconfig/network

# Check that networking is up.
[ "$NETWORKING" = "no" ] && exit 0

redis="/usr/bin/redis-server"
prog=$(basename $redis)

REDIS_CONF_FILE="/etc/redis/redis.conf"

[ -f /etc/sysconfig/redis ] && . /etc/sysconfig/redis

lockfile=/var/lock/subsys/redis

start() {
    [ -x $redis ] || exit 5
    [ -f $REDIS_CONF_FILE ] || exit 6
    echo -n $"Starting $prog: "
    daemon $redis $REDIS_CONF_FILE
    retval=$?
    echo
    [ $retval -eq 0 ] && touch $lockfile
    return $retval
}

stop() {
    echo -n $"Stopping $prog: "
    killproc $prog -QUIT
    retval=$?
    echo
    [ $retval -eq 0 ] && rm -f $lockfile
    return $retval
}

restart() {
    stop
    start
}

reload() {
    echo -n $"Reloading $prog: "
    killproc $redis -HUP
    RETVAL=$?
    echo
}

force_reload() {
    restart
}

rh_status() {
    status $prog
}

rh_status_q() {
    rh_status >/dev/null 2>&1
}

case "$1" in
    start)
        rh_status_q && exit 0
        $1
        ;;
    stop)
        rh_status_q || exit 0
        $1
        ;;
    restart|configtest)
        $1
        ;;
    reload)
        rh_status_q || exit 7
        $1
        ;;
    force-reload)
        force_reload
        ;;
    status)
        rh_status
        ;;
    condrestart|try-restart)
        rh_status_q || exit 0
        ;;
    *)
        echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload}"
        exit 2
esac
EOF
実行権限変更
chmod 755 /etc/init.d/redis-server
サービス登録
chkconfig --add redis-server
chkconfig --level 345 redis-server on

または

chkconfig redis-server on

ランレベルについて

0:シャットダウン(システムの停止)
1:シングルユーザーモード(rootのみ)
2:ネットワークなしのマルチユーザーモード
3:通常のマルチユーザーモード(テキストログイン)
4:未使用
5:グラフィカルログイン・マルチユーザーモード
6:システムの再起動

redisサービス起動

service redis-server start
cd /opt/src

PostgreSQLのインストール

PostgreSQL-9.3.4は、yumのデフォルト・レポジトリにはないため、コンパイル・インストールします。PostgreSQLはroot権限で実行できないため、以下のユーザーを追加しておきます。make時はオプション「-j10」オプションを追加し、時間節約のため、並列でコンパイルします。

重要:PostgreSQLのバックエンドやファンクションの多くがC++言語で書かれているため、安定運用のためにはstdc++ラブラリーをリンクして原因不明のトラブルを回避できます。今までPostgreSQLは一度もダウンした経験がありません。とても信頼できるデータベースです。

GISサーポートビルドなどの詳細は以下のURLを参照する。
http://nextdeveloper.hatenablog.com/entry/2014/05/20/164605

ユーザ確認と追加

yum install -y finger
id postgres
finger postgres

既に追加されている場合はスキップします。

useradd postgres

ダウンロードと基本DBのインストール(PHP用のライブラリー構築)

普段使わない場合は、設定やサービスを起動しない。
本格的に使う場合は、以下を参照して設定する。
http://nextdeveloper.hatenablog.com/entry/2014/05/20/164605

cd /opt/src
wget -q http://ftp.postgresql.org/pub/source/v9.3.4/postgresql-9.3.4.tar.gz
tar zxvf postgresql-9.3.4.tar.gz
cd postgresql-9.3.4
LDFLAGS=-lstdc++ ./configure --prefix=/usr --libdir='${prefix}/lib64'
make -j10 world
make install-world
cd ..

コンパイル前の確認

一度コンフィグレーションを行って、makeを実行した際には、必ずmake clean; ./buildconf --forceを実行してから、./configure->makeの手順でコンパイルを行います。それでも、コンフィグレーションでコンパイル・オプションなどが認識されない場合は、ソースを削除してから最初からやり直してください。

PHPコンパイル構築1(シェアド・ビルド/FastCGI用/Apacheモジュール)

オプションの設定で、-dirオプションは、/usr/local/mysql のようにインストールされたディレクトリ(prefixディレクトリ)を指定します。。--with-xxxオプションがエラーになった場合は、ライブラリーのディレクトリも一緒に設定します。ここではは、PHPバイナリは、シェアド・コンパイル・バイナリを基本とします。インストールされるモジュールは、/etc/php.d/xxxx.iniというファイル名でモジュールファイル(.so)を個別に設定するようにします。ここでは、PHPのApacheモジュールのバイナリも生成します。必要ない場合は、下のコンパイルオプションから--with-apxs2 \を削除します。

PHP実行時、モジュールの中でもセッションが最初に実行されため、「session.so」がロードされていなければこのモジュールに依存しているExtenshonで「Undefined symbol」エラーが発生します。そのため、sessionモジュールは、PHP本体に組み込んでスタティックでコンパイルすることで、この問題を回避します。

コンフィグレーションを実行するまでに、phpredis/igbinary/apcu./configureで下のように認識されているかを確認します。

./buildconf --force
./configure --help | grep "redis\|igbinary\|apcu"
  --enable-apcu           Enable APCu support
  --disable-apcu-rwlocks  Disable rwlocks in APCu
  --enable-apcu-debug     Enable APCu debugging
  --enable-apcu-clear-signal  Enable SIGUSR1 clearing handler
  --disable-apcu-mmap     Disable mmap, falls back on shm
  --enable-apcu-spinlocks        Use spinlocks before flocks
  --enable-igbinary          Enable igbinary support
  --enable-redis           Enable redis support
  --disable-redis-session      Disable session support
  --enable-redis-igbinary      Enable igbinary serializer support

--enable-cgiは、FastCGIオプションでコンパイルされます。指定しなくてもデフォルトで設定されます。CGI/FastCGIの両インターフェースをサポートしてます。

./configure \
    --prefix=/usr \
    --exec-prefix=/usr \
    --bindir=/usr/bin \
    --sbindir=/usr/sbin \
    --sysconfdir=/etc \
    --datadir=/usr/share \
    --includedir=/usr/include \
    --libdir=/usr/lib64 \
    --libexecdir=/usr/libexec \
    --localstatedir=/var \
    --sharedstatedir=/usr/com \
    --mandir=/usr/share/man \
    --infodir=/usr/share/info \
    --with-apxs2 \
    --with-config-file-path=/etc \
    --with-config-file-scan-dir=/etc/php.d \
    --with-libdir=lib64 \
    --with-layout=GNU \
    --with-fpm-user=www-data \
    --with-fpm-group=www-data \
    --enable-apcu=shared \
    --enable-bcmath=shared \
    --enable-calendar=shared \
    --enable-cgi \
    --enable-cli \
    --enable-ctype=shared \
    --enable-dba=shared \
    --enable-dom=shared \
    --enable-exif=shared \
    --enable-fileinfo=shared \
    --enable-filter=shared \
    --enable-fpm \
    --enable-ftp=shared \
    --enable-gd-jis-conv \
    --enable-gd-native-ttf \
    --enable-igbinary=shared \
    --enable-inline-optimization \
    --enable-intl=shared \
    --enable-json=shared \
    --enable-mbstring=shared \
    --enable-opcache=shared \
    --enable-pdo=shared \
    --enable-phar=shared \
    --enable-pcntl=shared \
    --enable-posix=shared \
    --enable-re2c-cgoto \
    --enable-redis=shared \
    --enable-redis-session \
    --enable-redis-igbinary \
    --enable-session=static \
    --enable-shmop=shared \
    --enable-sigchild=shared \
    --enable-simplexml=shared \
    --enable-soap=shared \
    --enable-sockets=shared \
    --enable-sysvsem=shared \
    --enable-sysvshm=shared \
    --enable-sysvmsg=shared \
    --enable-tokenizer=shared \
    --enable-xml=shared \
    --enable-xmlreader=shared \
    --enable-xmlwriter=shared \
    --enable-zend-signals \
    --enable-zip=shared \
    --enable-wddx=shared \
    --disable-rpath \
    --disable-ipv6 \
    --disable-debug \
    --with-freetype-dir=/usr \
    --with-icu-dir=/usr \
    --with-jpeg-dir=/usr \
    --with-libxml-dir=/usr \
    --with-png-dir=/usr \
    --with-openssl-dir=shared,/usr \
    --with-xpm-dir=/usr \
    --with-zlib-dir=shared,/usr \
    --with-bz2=shared \
    --with-curl=shared,/usr \
    --with-db4=shared \
    --with-enchant=shared \
    --with-gd=shared \
    --without-gdbm \
    --with-gettext=shared \
    --with-gmp=shared \
    --with-iconv=shared \
    --with-imap=shared \
    --with-imap-ssl \
    --with-kerberos \
    --with-ldap=shared \
    --with-ldap-sasl \
    --with-mcrypt=shared \
    --with-mhash=shared \
    --with-mm=/usr \
    --with-mysql=shared,/usr \
    --with-mysqli=shared,/usr/bin/mysql_config \
    --with-pdo-mysql=shared,/usr/bin/mysql_config \
    --with-openssl=shared \
    --with-pear \
    --with-pic=shared \
    --with-pgsql=shared,/usr \
    --with-pdo-pgsql=shared,/usr \
    --with-pdo-sqlite=shared,/usr \
    --with-pdo-odbc=shared,unixODBC,/usr \
    --with-pcre-regex \
    --with-pspell=shared \
    --with-readline=shared \
    --with-snmp=shared \
    --with-t1lib=shared \
    --with-tidy=shared,/usr \
    --with-unixODBC=shared,/usr \
    --with-xmlrpc=shared \
    --with-xsl=shared,/usr \
    --with-zlib=shared

コンパイル

make -j10

php-fpmユーザー追加

useradd www-data

インストール

make install &&
install -v -m644 php.ini-production /etc/php.ini &&
install -v -m644 sapi/fpm/php-fpm.conf /etc/php-fpm.conf &&
install -v -m755 sapi/fpm/init.d.php-fpm /etc/init.d/php-fpm

php.ini設定変更

sed -i 's/expose_php = On/expose_php = Off/g;' /etc/php.ini
sed -i 's/\;date.timezone =/date\.timezone = Asia\/Tokyo/g;' /etc/php.ini

シェアドPHPのインストールログ

make install
Installing PHP SAPI module:       apache2handler
/usr/lib64/httpd/build/instdso.sh SH_LIBTOOL='/usr/lib64/apr-1/build/libtool' libphp5.la /usr/lib64/httpd/modules
/usr/lib64/apr-1/build/libtool --mode=install cp libphp5.la /usr/lib64/httpd/modules/
libtool: install: cp .libs/libphp5.so /usr/lib64/httpd/modules/libphp5.so
libtool: install: cp .libs/libphp5.lai /usr/lib64/httpd/modules/libphp5.la
libtool: install: warning: remember to run `libtool --finish /opt/src/php-5.5.16/libs'
chmod 755 /usr/lib64/httpd/modules/libphp5.so
[activating module `php5' in /etc/httpd/conf/httpd.conf]
Installing shared extensions:     /usr/lib64/20121212/
Installing PHP CLI binary:        /usr/bin/
Installing PHP CLI man page:      /usr/share/man/man1/
Installing PHP FPM binary:        /usr/sbin/
Installing PHP FPM config:        /etc/
Installing PHP FPM man page:      /usr/share/man/man8/
Installing PHP FPM status page:      /usr/share/fpm/
Installing PHP CGI binary:        /usr/bin/
Installing PHP CGI man page:      /usr/share/man/man1/
Installing build environment:     /usr/lib64/build/
Installing header files:          /usr/include/php/
Installing helper programs:       /usr/bin/
  program: phpize
  program: php-config
Installing man pages:             /usr/share/man/man1/
  page: phpize.1
  page: php-config.1
Installing PEAR environment:      /usr/share/pear/
[PEAR] Archive_Tar    - already installed: 1.3.11
[PEAR] Console_Getopt - already installed: 1.3.1
[PEAR] PEAR           - already installed: 1.9.4
Wrote PEAR system config file at: /etc/pear.conf
You may want to add: /usr/share/pear to your php.ini include_path
[PEAR] Structures_Graph- already installed: 1.0.4
[PEAR] XML_Util       - already installed: 1.2.1
/opt/src/php-5.5.16/build/shtool install -c ext/phar/phar.phar /usr/bin
ln -s -f /usr/bin/phar.phar /usr/bin/phar
Installing PDO headers:          /usr/include/php/ext/pdo/

シェアドPHPのExtension設定

シェルスクリプトで書いてないのは個別に確認しやすくするためです。
内容を確認した上で、環境に合わせて修正してください。

mkdir /etc/php.d
cat > "/etc/php.d/apcu.ini" <<EOF
extension=apcu.so
apc.enabled=1
apc.shm_size=128M
apc.enable_cli=1
apc.write_lock=1
apc.slam_defense=0
apc.gc_ttl=3600
apc.ttl=7200
apc.entries_hint=4096
apc.slam_defense=1
apc.mmap_file_mask=/tmp/apc.XXXXXX
apc.serializer=igbinary
EOF
echo -e extension=bcmath.so >/etc/php.d/bcmath.ini
echo -e extension=bz2.so >/etc/php.d/bz2.ini
echo -e extension=calendar.so >/etc/php.d/calendar.ini]
echo -e extension=ctype.so >/etc/php.d/ctype.ini
echo -e extension=curl.so >/etc/php.d/curl.ini
echo -e extension=dba.so >/etc/php.d/dba.ini
echo -e extension=dom.so >/etc/php.d/dom.ini
echo -e extension=enchant.so >/etc/php.d/enchant.ini
echo -e extension=exif.so >/etc/php.d/exif.ini
echo -e extension=fileinfo.so >/etc/php.d/fileinfo.ini
echo -e extension=ftp.so >/etc/php.d/ftp.ini
echo -e extension=gd.so >/etc/php.d/gd.ini
echo -e extension=gettext.so >/etc/php.d/gettext.ini
echo -e extension=gmp.so >/etc/php.d/gmp.ini
echo -e extension=iconv.so >/etc/php.d/iconv.ini
echo -e extension=igbinary.so >/etc/php.d/igbinary.ini
echo -e extension=imap.so >/etc/php.d/imap.ini
echo -e extension=intl.so >/etc/php.d/intl.ini
echo -e extension=json.so >/etc/php.d/json.ini
echo -e extension=ldap.so >/etc/php.d/ldap.ini
cat > "/etc/php.d/mbstring.ini" <<EOF
extension=mbstring.so
mbstring.language = Japanese
mbstring.internal_encoding = UTF-8
mbstring.http_input = UTF-8
mbstring.http_output = pass
mbstring.detect_order = UTF-8,SJIS,EUC-JP,JIS,ASCII
EOF
echo -e extension=mcrypt.so >/etc/php.d/mcrypt.ini
echo -e extension=mysql.so >/etc/php.d/mysql.ini
echo -e extension=mysqli.so >/etc/php.d/mysqli.ini
echo -e extension=odbc.so >/etc/php.d/odbc.ini

OPCacheプロダクション設定

メモリをある程度搭載しているマシーンでは、「opcache.memory_consumption」の数字を増やします。

mkdir /var/lib/php
cat > "/etc/php.d/opcache.ini" <<EOF
zend_extension=opcache.so
[opcache]
opcache.enable=1
opcache.enable_cli=1
opcache.memory_consumption=128
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=4000
opcache.max_file_size=5M
opcache.blacklist_filename=/var/lib/php/opcache*.blacklist
opcache.revalidate_freq=0
opcache.revalidate_path=0
opcache.save_comments=0
opcache.load_comments=0
opcache.consistency_checks=1
opcache.fast_shutdown=1
EOF
echo -e extension=openssl.so >/etc/php.d/openssl.ini
echo -e extension=pcntl.so >/etc/php.d/pcntl.ini
echo -e extension=pdo.so >/etc/php.d/pdo.ini
echo -e extension=pdo_mysql.so >/etc/php.d/pdo_mysql.ini
echo -e extension=pdo_odbc.so >/etc/php.d/pdo_odbc.ini
echo -e extension=pdo_pgsql.so >/etc/php.d/pdo_pgsql.ini
echo -e extension=pdo_sqlite.so >/etc/php.d/pdo_sqlite.ini
echo -e extension=pgsql.so >/etc/php.d/pgsql.ini
echo -e extension=phar.so >/etc/php.d/phar.ini
echo -e extension=posix.so >/etc/php.d/posix.ini
echo -e extension=pspell.so >/etc/php.d/pspell.ini
echo -e extension=readline.so >/etc/php.d/readline.ini
echo -e "extension=redis.so\nredis.serializer=igbinary" >/etc/php.d/redis.ini
echo -e extension=shmop.so >/etc/php.d/shmop.ini
echo -e extension=simplexml.so >/etc/php.d/simplexml.ini
echo -e extension=snmp.so >/etc/php.d/snmp.ini
echo -e extension=soap.so >/etc/php.d/soap.ini
echo -e extension=sockets.so >/etc/php.d/sockets.ini
echo -e extension=sysvmsg.so >/etc/php.d/sysvmsg.ini
echo -e extension=sysvmsg.so >/etc/php.d/sysvmsg.ini
echo -e extension=sysvshm.so >/etc/php.d/sysvshm.ini
echo -e extension=tidy.so >/etc/php.d/tidy.ini
echo -e extension=tokenizer.so >/etc/php.d/tokenizer.ini
echo -e extension=wddx.so >/etc/php.d/wddx.ini
echo -e extension=xml.so >/etc/php.d/xml.ini
echo -e extension=xmlreader.so >/etc/php.d/xmlreader.ini
echo -e extension=xmlrpc.so >/etc/php.d/xmlrpc.ini
echo -e extension=xmlwriter.so >/etc/php.d/xmlwriter.ini
echo -e extension=xsl.so >/etc/php.d/xsl.ini
echo -e extension=zip.so >/etc/php.d/zip.ini
echo -e extension=zlib.so >/etc/php.d/zlib.ini

Peclコマンドでのモジュール追加インストール例

以下は必要ない場合はスキップします。

pecl install -f oauth-beta

PHPモジュールのコンパイル・インストール

以下は必要ない場合はスキップします。
geosライブラリは、コンパイル時に注意が必要です。GIS系のライブラリーは、バージョンによって依存性がことなり、同じライブライーが既にインストールされている場合は、ライブラリーのディレクトリを変更して、ぶつからないようにしなければなりません。コンパイルする時は、一番安定している、3.3.9バージョンを選びます。

geosエクステンションをインストールするとgeoPHPという便利なクラスが利用できます。このライブラリーをインストールすることで、PHPからGISの様々なデータフォーマットが扱えるようになります。地図表示をより高機能にする際にはとても便利です。

geoPHPモジュール

https://github.com/phayes/geoPHP/

Goesエクステンションのインストール

wget http://download.osgeo.org/geos/geos-3.3.9.tar.bz2
tar -xvjf geos-3.3.9.tar.bz2
cd geos-3.3.9
./autogen.sh
./configure --enable-php
make clean
make -j20
make install

インストールされたエクステンションのリンク先がソースディレクトリになっているため、修正する必要があります。以下のように既存リンクを削除し、ldconfigでインストールされた先がロードされるようにします。

mv src/.libs/libgeos-3.3.9.so src/.libs/libgeos-3.3.9.so_orig
mv capi/.libs/libgeos_c.so.1 capi/.libs/libgeos_c.so.1_orig

sudo echo -e /usr/local/lib >/etc/ld.so.conf.d/geos-x86_64.conf
sudo echo -e extension=geos.so >/etc/php.d/geos.ini
/sbin/ldconfig

#正しくライブラリーがリンクされているか確認します。
[root@dev geos-3.3.9]# ldd /usr/lib64/20121212/geos.so
        linux-vdso.so.1 =>  (0x00007fff549ff000)
        libgeos_c.so.1 => /usr/local/lib/libgeos_c.so.1 (0x00007f2609235000)
        libc.so.6 => /lib64/libc.so.6 (0x00007f2608e8f000)
        libgeos-3.3.9.so => /usr/local/lib/libgeos-3.3.9.so (0x00007f2608afb000)
        libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x00007f26087f5000)
        libm.so.6 => /lib64/libm.so.6 (0x00007f2608570000)
        libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f260835a000)
        /lib64/ld-linux-x86-64.so.2 (0x0000003424400000)

※注意※

既存OSには、yumでインストールされている「geos-devel」バッケージが、3.3.2であるため、ぶつからないように注意します。コンパイル・インストールしたライブラリーのディレクトリが、lddコマンドで/usr/local/lib/になっているかを確認します。

以上、ここまでが、PHPをシェアド・ビルド方法になります。上記でのコンパイルはほとんどのエクステンションが追加されたPHPパッケージになります。エクステンションで必要ない場合は、コメントにしてロードしないようにして構築します。

PHPコンパイル構築2(スタティック・ビルド/Apache2のPHPモジュール用)

mod_phpようにビルドする際にはスタティックでコンパイルした方が、やや早いため、スタティック・ビルド方法も以下に追加します。スターティックのphp-fpmのバイナリも生成されます。オプションで設定で、-dirオプションは、/usr/local/mysqlのようにインストールされたディレクトリ(prefixディレクトリ)を指定します。。--with-xxxオプションがエラーになった場合は、ライブラリーのディレクトリも一緒に設定します。モジュール(extension)を追加する場合は、ダイナミックライブラリー(.so)で追加し、「.ini」ファイルで設定します。--with-apxs2のオプションも追加し、ApacheのPHPモジュール(libphp5.so)バイナリを生成しています。Opcacheは、スタティックでコンパイルしてもダイナミックライブラリーとしてインストールされますので、注意します。シェアドでビルドした場合若しくは必要ない場合は、スキップします。

cd /opt/src/php-5.5.16

phpredis/igbinary/apcu が configure で下のように認識されているかを確認します。

./buildconf --force
./configure --help | grep "redis\|igbinary\|apcu"
  --enable-apcu           Enable APCu support
  --disable-apcu-rwlocks  Disable rwlocks in APCu
  --enable-apcu-debug     Enable APCu debugging
  --enable-apcu-clear-signal  Enable SIGUSR1 clearing handler
  --disable-apcu-mmap     Disable mmap, falls back on shm
  --enable-apcu-spinlocks        Use spinlocks before flocks
  --enable-igbinary          Enable igbinary support
  --enable-redis           Enable redis support
  --disable-redis-session      Disable session support
  --enable-redis-igbinary      Enable igbinary serializer support


./configure \
    --prefix=/usr \
    --exec-prefix=/usr \
    --bindir=/usr/bin \
    --sbindir=/usr/sbin \
    --sysconfdir=/etc \
    --datadir=/usr/share \
    --includedir=/usr/include \
    --libdir=/usr/lib64 \
    --libexecdir=/usr/libexec \
    --localstatedir=/var \
    --sharedstatedir=/usr/com \
    --mandir=/usr/share/man \
    --infodir=/usr/share/info \
    --with-apxs2 \
    --with-config-file-path=/etc \
    --with-config-file-scan-dir=/etc/php.d \
    --with-libdir=lib64 \
    --with-layout=GNU \
    --with-fpm-user=www-data \
    --with-fpm-group=www-data \
    --enable-fpm \
    --enable-inline-optimization \
    --enable-apcu \
    --enable-bcmath \
    --enable-calendar \
    --enable-cgi \
    --enable-cli \
    --enable-ctype \
    --enable-dba \
    --enable-dom \
    --enable-exif \
    --enable-fileinfo \
    --enable-filter \
    --enable-ftp \
    --enable-gd-jis-conv \
    --enable-gd-native-ttf \
    --enable-intl \
    --enable-igbinary \
    --enable-json \
    --enable-mbstring \
    --enable-opcache \
    --enable-pdo \
    --enable-phar \
    --enable-pcntl \
    --enable-posix \
    --enable-re2c-cgoto \
    --enable-redis=static \
    --enable-redis-session \
    --enable-redis-igbinary \
    --enable-session \
    --enable-shmop \
    --enable-sigchild \
    --enable-simplexml \
    --enable-soap \
    --enable-sockets \
    --enable-sysvsem \
    --enable-sysvshm \
    --enable-sysvmsg \
    --enable-tokenizer \
    --enable-xml \
    --enable-xmlreader \
    --enable-xmlwriter \
    --enable-zip \
    --enable-wddx \
    --enable-zend-signals \
    --disable-rpath \
    --disable-debug \
    --with-freetype-dir=/usr \
    --with-icu-dir=/usr \
    --with-jpeg-dir=/usr \
    --with-libxml-dir=/usr \
    --with-png-dir=/usr \
    --with-openssl-dir=/usr \
    --with-xpm-dir=/usr \
    --with-zlib-dir=/usr \
    --with-bz2 \
    --with-curl=/usr \
    --with-db4 \
    --with-enchant \
    --with-gd \
    --without-gdbm \
    --with-gettext \
    --with-gmp \
    --with-iconv \
    --with-imap \
    --with-imap-ssl \
    --with-kerberos \
    --with-ldap \
    --with-ldap-sasl \
    --with-mcrypt \
    --with-mhash \
    --with-mm=/usr \
    --with-mysql=/usr \
    --with-mysqli=/usr/bin/mysql_config \
    --with-pdo-mysql=/usr/bin/mysql_config \
    --with-onig \
    --with-openssl \
    --with-pear \
    --with-pic \
    --with-pgsql=/usr \
    --with-pdo-pgsql=/usr \
    --with-pdo-sqlite=/usr \
    --with-pdo-odbc=unixODBC,/usr \
    --with-pcre-regex \
    --with-pspell \
    --with-readline \
    --with-snmp \
    --with-t1lib \
    --with-tidy \
    --with-unixODBC=/usr \
    --with-xmlrpc \
    --with-xsl=/usr \
    --with-zlib

スタティックPHPのコンパイル・インストール

コンパイル
make -j10
php-fpmユーザー追加
useradd www-data
インストール
make install &&
install -v -m644 php.ini-production /etc/php.ini &&
install -v -m644 sapi/fpm/php-fpm.conf /etc/php-fpm.conf &&
install -v -m755 sapi/fpm/init.d.php-fpm /etc/init.d/php-fpm
php.ini設定変更
sed -i 's/expose_php = On/expose_php = Off/g;' /etc/php.ini
sed -i 's/\;date.timezone =/date\.timezone = Asia\/Tokyo/g;' /etc/php.ini

スタティックPHP・インストール・ログ

make install all
Installing PHP SAPI module:       apache2handler
/usr/lib64/httpd/build/instdso.sh SH_LIBTOOL='/usr/lib64/apr-1/build/libtool' libphp5.la /usr/lib64/httpd/modules
/usr/lib64/apr-1/build/libtool --mode=install cp libphp5.la /usr/lib64/httpd/modules/
libtool: install: cp .libs/libphp5.so /usr/lib64/httpd/modules/libphp5.so
libtool: install: cp .libs/libphp5.lai /usr/lib64/httpd/modules/libphp5.la
libtool: install: warning: remember to run `libtool --finish /opt/src/php-5.5.16/libs'
chmod 755 /usr/lib64/httpd/modules/libphp5.so
[activating module `php5' in /etc/httpd/conf/httpd.conf]
Installing shared extensions:     /usr/lib64/20121212/
Installing PHP CLI binary:        /usr/bin/
Installing PHP CLI man page:      /usr/share/man/man1/
Installing PHP FPM binary:        /usr/sbin/
Installing PHP FPM config:        /etc/
Installing PHP FPM man page:      /usr/share/man/man8/
Installing PHP FPM status page:      /usr/share/fpm/
Installing PHP CGI binary:        /usr/bin/
Installing PHP CGI man page:      /usr/share/man/man1/
Installing build environment:     /usr/lib64/build/
Installing header files:          /usr/include/php/
Installing helper programs:       /usr/bin/
  program: phpize
  program: php-config
Installing man pages:             /usr/share/man/man1/
  page: phpize.1
  page: php-config.1
Installing PEAR environment:      /usr/share/pear/
[PEAR] Archive_Tar    - already installed: 1.3.11
[PEAR] Console_Getopt - already installed: 1.3.1
[PEAR] PEAR           - already installed: 1.9.4
Wrote PEAR system config file at: /etc/pear.conf
You may want to add: /usr/share/pear to your php.ini include_path
[PEAR] Structures_Graph- already installed: 1.0.4
[PEAR] XML_Util       - already installed: 1.2.1
/opt/src/php-5.5.16/build/shtool install -c ext/phar/phar.phar /usr/bin
ln -s -f /usr/bin/phar.phar /usr/bin/phar
Installing PDO headers:          /usr/include/php/ext/pdo/

スタティックPHP設定(Extension設定)

スタティックビルドでもopcacheはデフォルトでシェアドでコンパイルされるため、別途設定する必要があります。
extensions.iniファイルに追加されるモジュールをまとめて設定するようにします

mkdir /var/lib/php
cat > "/etc/php.d/extensions.ini" <<'EOF'
;Opcache
zend_extension=opcache.so
[opcache]
[opcache]
opcache.enable=1
opcache.enable_cli=1
opcache.memory_consumption=128
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=4000
opcache.max_file_size=5M
opcache.blacklist_filename=/var/lib/php/opcache*.blacklist
opcache.revalidate_freq=0
opcache.revalidate_path=0
opcache.save_comments=0
opcache.load_comments=0
opcache.consistency_checks=1
opcache.fast_shutdown=1

;apcu
apc.enabled=1
apc.shm_size=128M
apc.enable_cli=1
apc.write_lock=1
apc.slam_defense=0
apc.gc_ttl=3600
apc.ttl=7200
apc.entries_hint=4096
apc.slam_defense=1
apc.mmap_file_mask=/tmp/apc.XXXXXX
apc.serializer=igbinary

;mbstring
mbstring.language = Japanese
mbstring.internal_encoding = UTF-8
mbstring.http_input = UTF-8
mbstring.http_output = pass
mbstring.detect_order = UTF-8,SJIS,EUC-JP,JIS,ASCII

EOF

今回は以上になります。 次回は、動作確認、ApacheとNginxのパフォーマンス検証等、本記事のまとめについてお話します。 長文を読んで頂き、ありがとうございました。