2016. 4. 6. 09:51

PHP 운영구성 관련 정리 #3

mod_fastcgi 설치

소스 다운로드
cd /opt/src
wget http://www.fastcgi.com/dist/mod_fastcgi-current.tar.gz
압축 및 컴파일
tar zxvf mod_fastcgi-current.tar.gz
cd mod_fastcgi-2.4.6/
cp Makefile.AP2 Makefile
make top_dir=/usr/lib64/httpd
make install top_dir=/usr/lib64/httpd
설치 이진 확인
ldd /usr/lib64/httpd/modules/mod_fastcgi.so
        linux-vdso.so.1 =>  (0x00007ffffeeea000)
        libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f478e38c000)
        libc.so.6 => /lib64/libc.so.6 (0x00007f478dff8000)
        /lib64/ld-linux-x86-64.so.2 (0x0000003b69000000)

Apache2 / FastCGI 설정 (PHP-FPM)

성능 비교를 위해 확장자를 임시로 ".fphp"로 설정하고 있습니다. 실전 운용시에는 ".php"로 되돌립니다. Location 설정은 URL에 직접 액세스를 방지 내용입니다.Action 내부 리다이렉션 후 fcgi-bin URL을 사용할 수 있도록하기 위해 'env = REDIRECT_STATUS "을 설정합니다.

cat > "/etc/httpd/conf.d/php-fpm.conf" <<'EOF'
LoadModule fastcgi_module modules/mod_fastcgi.so
<FilesMatch "\.(fphp|html)$">
    SetHandler application/x-httpd-php
</FilesMatch>
Action application/x-httpd-php /fcgi-bin/php-fpm virtual
Alias /fcgi-bin/php-fpm /fcgi-bin-php-fpm
<Location /fcgi-bin/php-fpm>
    Order Deny,Allow
    Deny from All
    Allow from env=REDIRECT_STATUS
</Location>
FastCgiExternalServer /fcgi-bin-php-fpm -appConnTimeout 10 -idle-timeout 250 -socket /var/run/php-fpm.sock -pass-header Authorization
EOF

★ 중요 ★ 위 설정에서 "-appConnTimeout 10 -idle-timeout 250"은 반드시 설정해야합니다. idele-timeout은 기본적으로 30 초로되어 있지만, 경우에 따라서는 충분하지 않기 때문에 길게 설정해야합니다. "FastCGI : incomplete headers (0 bytes) received ...."오류가 토출 응답하지 않을 경우가 드물게 있습니다. 이 오류가 발생했을 때 "- idle-timeout"시간을 더 길게 설정하여 해결할 수 있습니다. 자세한 내용은 다음 사이트를 참조하십시오.

FastCGI 설치 설명서 :http://www.fastcgi.com/mod_fastcgi/docs/mod_fastcgi.html

PHP-FPM 서비스 확인 및 등록

서비스 동작 테스트
service php-fpm start
service php-fpm stop
서비스에 추가 테스트
chkconfig php-fpm on
서비스에서 제거 테스트
chkconfig php-fpm off
서비스 확인
chkconfig --list php-fpm
php-fpm 0 : off 1 : off 2 : off 3 : off 4 : off 5 : off 6 : off
서비스 등록
chkconfig php-fpm on

PHP-FPM 설정

글로벌과 수영장 설정으로 나눈다. 많은 옵션이 있지만, 아래와 같이 짧게 설정해도 문제는 없습니다. FastCGI 프로세스는 고정 (static)으로 설정을 권장합니다. 
Apache-1.3의 초기 버전에서 FastCGI를 사용해 보았습니다 만, 동적 (dynamic)에서의 설정은 다양한 문제가 발생 한 경험이 있습니다. FastCGI 프로세스는 기다리는 과정이기 때문에 메모리 누수를주의해야합니다. PHP-FPM에서 요청의 최대 수 (pm.max_requests)를 설정하고 있으면 자동으로 자식 프로세스를 재시작 해주는 기능이있어, 메모리 누수를 방지합니다. 메모리의 상황을 확인하면서 고정 (static)으로 시작上げる子프로세스 수를 결정합니다. 
설정시주의해야 할 것은, 기본적으로 생성 된 소켓 파일은 apache 또는 nginx 권한에 액세스 할 수 없기 때문에 listen.mode에서 권한을 0666으로해야합니다. 2G 메모리 머신에서 프로세스 수를 100으로해도 문제없이 동작 확인했습니다. 사이트에 따라 다르므로 HTOP를 설치하고 메모리 사용량을 보면서 조정합니다. 뿌뿌로세스 수 고정 (static)의 설정은 일단로드되면 고정 메모리를 확보합니다. 동적 (dynamic)의 설정은 메모리 사용량이 설정 범위 내에서 액세스 수에 따라 달라집니다.

php-fpm.conf 설정
mkdir /etc/fpm.d
rm -f /etc/php-fpm.conf
전역 설정
cat > "/etc/php-fpm.conf" <<EOF
[global]
pid = run/php-fpm.pid
error_log = log/php-fpm.log
log_level = notice
daemonize = yes
include=/etc/fpm.d/*.conf
EOF
풀 설정 (Apache 검증 권한)

Apache의 경우 아래의 설정으로 전환 확인합니다.

cat > "/etc/fpm.d/www.conf" <<'EOF'
[apache]
user = apache
group = apache
listen = /var/run/php-fpm.sock
listen.mode = 0666
pm = static
pm.max_children = 100
pm.max_requests = 1000
security.limit_extensions = .php .fphp .html .htm
EOF
풀 설정 (Nginx 검증 권한)

Nginx의 경우 아래의 설정으로 전환 확인합니다.

cat > "/etc/fpm.d/www.conf" <<'EOF'
[nginx]
user = nginx
group = nginx
listen = /var/run/php-fpm.sock
listen.mode = 0666
pm = static
pm.max_children = 100
pm.max_requests = 1000
security.limit_extensions = .php .fphp .html .htm
EOF
php 동작 테스트 파일 작성
cat > "/var/www/html/info_test.php" <<EOF
<?php
echo phpinfo();
?>
EOF

Nginx 컴파일 구축

nginx의 의존성에있는 라이브러리 설치
yum -y install GeoIP-devel.x86_64
yum -y install bxslt-devel.x86_64
yum -y install perl-ExtUtils-Embed.x86_64
yum -y install pcre-devel.x86_64
RPM-GPG-KEY 가져 오기
rpm --import http://mirror.centos.org/centos/6.5/os/x86_64/RPM-GPG-KEY-CentOS-6
Nginx의 최신 안정 버전 설치
rpm -i http://nginx.org/packages/centos/6/x86_64/RPMS/nginx-1.6.0-1.el6.ngx.x86_64.rpm
RPM 설치 디렉토리 확인
rpm -ql nginx
/etc/logrotate.d/nginx
/etc/nginx
/etc/nginx/conf.d
/etc/nginx/conf.d/default.conf
/etc/nginx/conf.d/example_ssl.conf
/etc/nginx/fastcgi_params
/etc/nginx/koi-utf
/etc/nginx/koi-win
/etc/nginx/mime.types
/etc/nginx/nginx.conf
/etc/nginx/scgi_params
/etc/nginx/uwsgi_params
/etc/nginx/win-utf
/etc/rc.d/init.d/nginx
/etc/sysconfig/nginx
/usr/sbin/nginx
/usr/share/nginx
/usr/share/nginx/html
/usr/share/nginx/html/50x.html
/usr/share/nginx/html/index.html
/var/cache/nginx
/var/log/nginx

RPM으로 설치 한 이유는 각종 설정 파일을 자동으로 배치하는 것입니다. 후 소스에서 다운로드하여 Google 개발 오픈 소스 "ngx_pagespeed"을 지원하도록 따로 컴파일한 실행파일을 바꿉니다. "/usr/sbin/nginx"

Nginx 및 소스 다운로드
cd /opt/src
wget -q http://nginx.org/download/nginx-1.6.0.tar.gz
tar zxvf nginx-1.6.0.tar.gz

wget -q https://github.com/pagespeed/ngx_pagespeed/archive/v1.8.31.4-beta.zip -O ngx_pagespeed-1.8.31.4-beta.zip
unzip ngx_pagespeed-1.8.31.4-beta.zip

cd ngx_pagespeed-1.8.31.4-beta/
wget -q https://dl.google.com/dl/page-speed/psol/1.8.31.4.tar.gz
tar -xzvf 1.8.31.4.tar.gz
컴파일 설정

컴파일 옵션 확인은 기존 RPM으로 설치되어있는 것과 동일한 구성하기 위해 "nginx -V"명령으로 확인 pgespeed 모듈을 마지막으로 추가해야합니다.

cd /opt/src/nginx-1.6.0
./configure --prefix=/etc/nginx \
    --sbin-path=/usr/sbin/nginx \
    --conf-path=/etc/nginx/nginx.conf \
    --error-log-path=/var/log/nginx/error.log \
    --http-log-path=/var/log/nginx/access.log \
    --pid-path=/var/run/nginx.pid \
    --lock-path=/var/run/nginx.lock \
    --http-client-body-temp-path=/var/cache/nginx/client_temp \
    --http-proxy-temp-path=/var/cache/nginx/proxy_temp \
    --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp \
    --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp \
    --http-scgi-temp-path=/var/cache/nginx/scgi_temp \
    --user=nginx --group=nginx \
    --with-http_ssl_module \
    --with-http_realip_module \
    --with-http_addition_module \
    --with-http_sub_module \
    --with-http_dav_module \
    --with-http_flv_module \
    --with-http_mp4_module \
    --with-http_gunzip_module \
    --with-http_gzip_static_module \
    --with-http_random_index_module \
    --with-http_secure_link_module \
    --with-http_stub_status_module \
    --with-http_auth_request_module \
    --with-http_xslt_module \
    --with-http_image_filter_module \
    --with-http_degradation_module \
    --with-mail \
    --with-mail_ssl_module \
    --with-file-aio \
    --with-ipv6 \
    --with-http_spdy_module \
    --with-cc-opt='-O2 -g -pipe -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic' \
    --with-ld-opt=' -Wl,-E' \
    --add-module=/opt/src/ngx_pagespeed-1.8.31.4-beta
컴파일
make -j10
기존 바이너리 교체
\cp objs/nginx /usr/sbin/nginx

Nginx 설정 (검증을위한 임시 설정)

Nginx 기본 설정

worker_processes CPU의 코어 수를 설정합니다.

기존 설정 백업
\cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf_backup
설정 파일 덮어 쓰기
cat > "/etc/nginx/nginx.conf"<< 'EOF'
user  nginx;
worker_processes  3;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    tcp_nopush      on;

    keepalive_requests 100;
    keepalive_timeout 10;

    gzip  on;
    gzip_static on;
    gzip_comp_level 2;
    gzip_buffers 64 8k;
    gzip_min_length 1100;
    gzip_types        text/plain 
                      text/xml 
                      text/css 
                      application/xml 
                      application/xhtml+xml 
                      application/rss+xml 
                      application/atom_xml 
                      application/javascript 
                      application/x-javascript 
                      application/x-httpd-php;
    gzip_disable      "MSIE [1-6]\.";
    gzip_disable      "Mozilla/4";
    gzip_vary  on;
    gzip_proxied      any;
    gzip_http_version 1.1;

    server_tokens off;

    include /etc/nginx/conf.d/*.conf;

}
EOF
Nginx 서버 설정

기존 Apache 벤치 마크 디렉토리를 그대로 설정하고 벤치마킹을 실시합니다.

\cp /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf_backup

cat > "/etc/nginx/conf.d/default.conf" <<'EOF'
server {
    listen       80;
    server_name  localhost;

    location / {
        root   /var/www/html/;
        index  index.php;
        try_files $uri $uri/ /index.php?$uri&$args;
    }

    location ~ \.php$ {
        root           /var/www/html/;
        fastcgi_pass   unix:/var/run/php-fpm.sock;
        fastcgi_index  index.php;
        include        fastcgi_params;
        fastcgi_param  REMOTE_ADDR $remote_addr;
        fastcgi_param  REMOTE_PORT $remote_port;
        fastcgi_param  SERVER_ADDR $server_addr;
        fastcgi_param  SERVER_PORT $server_port;
        fastcgi_param  SERVER_NAME $server_name;
        fastcgi_param  CONTENT_TYPE $content_type;
        fastcgi_param  CONTENT_LENGTH $content_length;
        fastcgi_param  QUERY_STRING $query_string;
        fastcgi_param  PATH_INFO  $fastcgi_path_info;
        fastcgi_param  REQUEST_METHOD $request_method;
        fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param  SCRIPT_NAME $fastcgi_script_name;
        fastcgi_param  REQUEST_URI $request_uri;
        fastcgi_param  DOCUMENT_URI $document_uri;
        fastcgi_param  DOCUMENT_ROOT $document_root;
        fastcgi_param  SERVER_PROTOCOL $server_protocol;
        fastcgi_param  GATEWAY_INTERFACE CGI/1.1;
        fastcgi_param  SERVER_SOFTWARE nginx/$nginx_version;
        fastcgi_param  HTTPS $https;
        fastcgi_buffer_size 128k;
        fastcgi_buffers 256 16k; #4096k total
        fastcgi_busy_buffers_size 256k;
        fastcgi_temp_file_write_size 256k;
        fastcgi_max_temp_file_size 0; #disable buffering to disk
        client_max_body_size 0; #Allow large uploads
    }
}
EOF

Apache와 Nginx의 성능 검증 결과

nginx(woker) + php-fpm ⇒ 685.07 [#/sec]
apache(worker) + php-fpm ⇒ 594.79 [#/sec]
apache(prefork) + php-fpm ⇒ 560.84 [#/sec]
apache(prefork) + mod_php ⇒ 509.72 [#/sec]

위 결과는 환경이나 이용 상황에 따라 다를 수 있지만 대체로 "nginx (woker) + php-fpm"의 구성이 가장 좋은 성능이 나옵니다.

서버의 대역폭 검증 (TCP 처리량)

이 검사는 서버 2 대가 필요합니다. 로컬 또는 광역 네트워크에서도 확인할 수 있습니다. 서버 측의 방화벽을 해제해야합니다. 기본 포트는 5201입니다. 다음 도구를 모두 설치하고 확인합니다. 만일 서버의 IP를 "192.168.1.3/192.168.1.4"로 설정합니다. 이 검증은 AWS 또는 VPS 환경에서 DB 연결을 할 때 네트워크에 병목 현상이 없는지를 확인하기 위해서입니다. 또한 역방향 프록시 서버를 설정하여 운용 할 때 개별 서버에서 성능이 나오지도 네트워크에 병목 현상이 있고, 성능이 오르지 않는 경우가 있으므로 반드시 확인하여보십시오.

ym install -y iperf3
192.168.1.3:server

포트를 변경하는 경우에는 "- p 8080"과 같이 추가합니다.

iperf3 -s
192.168.1.4:client

서버 측의 포트가 기본 포트와 다른 경우는 "-p 8080"과 같이 추가합니다.

iperf3 -c 192.168.1.3