2016. 4. 5. 13:13

PHP 운영구성 관련 정리 #1

PHP의 운영 구성

권장 PHP 구성

①PHP 언어 만 사용하는 환경

Nginx (Worker) + php-fpm
Apache-Worker + mod_fastcgi + php-fpm

②PHP / Ruby / Perl / Python 등 다국어 프로덕션

Nginx (Worker) + spawn-fcgi + php-cgi
Apache-Worker + spawn-fcgi + mod_fastcgi + php-cgi


여러 대의 운용 구성 예

  • varnish : SSL을 지원하지 않으므로 프런트 엔드에 pound (ssl wrapper)를 배치합니다.
  • 프런트 엔드에 nginx 보다 haproxy를 자주 사용합니다.
  • varnish와 백엔드 사이에 haproxy을 배치하는 구성도 있습니다.
  • HTTP의 POST, 세션, 쿠키 등을 올바르게 설정하고 구축해야합니다.
  • N : 다수
  • 1. pound <--> varnish <--> N * (apache + mod_php) 
    2. nginx <--> N * (apache + mod_php)
    3. pound <--> varnish <--> N * (apache + mod_fastcgi + php-cgi)
    4. nginx <--> N * (apache + mod_fastcgi + php-cgi)
    5. pound <--> varnish <--> N * (apache + mod_fastcgi+php-fpm)
    6. nginx <--> N * (apache + mod_fastcgi+php-fpm)
    7. pound <--> varnish <--> N * (nginx + php-fpm)
    9. nginx <--> N * (nginx + php-fpm)


부하 분산 시스템 구성의 정리

①pound-> varnish-> haproxy-> backend
②nginx-> backend
③haproxy-> backend


★ 정리 ★

고성능의 PHP 운영 환경 구축의 핵심은 컴파일 튜닝 커널 파라미터 튜닝, 캐싱,로드 밸런싱, PHP 운용의 기본 구성 내부 processing의 고속화, 내부 network의 고속화 등을 종합적으로 적절히 구성해야 됩니다.. 빠른 데이터 액세스 및 계산 능력이 필요한 경우는 그리드 컴퓨팅 (Globus Toolkit : 표준 미들웨어) 구축이라는 의미도 있지만, 자원을 낭비하지 않도록 개발 현장에서의 데이터베이스와 프로그래밍 최적화 화도 중요한 요소입니다.

결론은 PHP를 이용하는데있어서 가장 추천 할 수있는 기본 구성은 다음의 두 가지입니다.

Nginx 구성

 Nginx-Worker + php-fpm

Apache 구성

 Apache-Worker + mod_fastcgi + php-fpm

FastCGI 운용 관련 설정에 대해

 FastCGI는 요청을 기다리는 프로세스 수를 동적 (dynamic) 또는 정적 (static)으로 설정할 수 있습니다. 본인은 정적(static)설정을 선호합니다. php-fpm이 프로세스를 관리하는 데몬의 역할을하고 있습니다. "mod_fastcgi + php-cgi"라는 구성의 경우도 FastCGI 프로세스 수 설정은 동적 또는 정적으로 설정하지만, 정기적으로 유지 보수를 할 필요가있었습니다. 이러한 관리 기능을 php-fpm에서는 SAPI가 지원 중단없이 안전하게 FastCGI 프로세스의 자동 관리 할 수​​있게되었습니다.


Tuned에서의 튜닝

다음 도구를 설치하고 명령을 실행하면 자동으로 조정 해 준다고합니다. 내용을 모르는 경우 다음 명령을 실행하지 않고 그대로 넘어가십시오.

설치

yum install -y tuned

옵션 확인

tuned-adm list
Available profiles :
- default
- enterprise-storage
- desktop-powersave
- laptop-ac-powersave
- laptop-battery-powersave
- sap
- spindown-disk
- virtual-guest
- server-powersave
- throughput-performance
- virtual-host
- latency-performance

튜닝 실행 (latency-performance)

tuned-adm profile latency-performance


GRUB 구문 추가 설정에 의한 튜닝

다음 내용은 커널과 OS의 지식이있는 분에 한합니다. OS가 부팅되지 않을 위험이 있으므로 참고 정도로 해 주시면 감사하겠습니다. 100 만분의 1 초 단위를 경쟁 금융 기관의 빠른 거래 시스템 (Low latency Trading System)에 효과를 발휘하는 설정을 참고로 한 것입니다. 지금은 실시간 커널 등의 응용도 있으므로 Unix / Linux에서 새로운 기술에 대해 관심있는 분들은 Ubuntu의 lowlatency 커널을 참고로 해 주시면이라고 생각합니다. GRUB 구문의 끝에 다음 행을 추가하여 설정합니다. 다음 작업은 자신의 책임과 판단으로해야합니다. 불안이있는 것 같다면,이 설정은 생략합니다.

nosoftlockup nohz = off highres = off intel_idle.max_cstate = 0 processor.max_cstate = 0 cgroup_disable = memory nmi_watchdog = 0 divider = 4 nosoftlockup mce = ignore_ce


GRUB 구문의 예

주의 : 다음 "kernel"부분을 그대로 복사하여 바꾸면 OS가 시작되지 않습니다. 반드시 위의 행을 마지막에 추가하도록하십시오.

view /etc/
title CentOS (2.6.32-431.17.1.el6.x86_64)
        root (hd0,0)
        kernel /vmlinuz-2.6.32-431.17.1.el6.x86_64 ro root = UUID = 035d9a21-778d-40cf-9ecb-d244d7b95781 rd_NO_LUKS rd_NO_MD SYSFONT = latarcyrheb-sun16 KEYBOARDTYPE = pc KEYTABLE = jp106 LANG = ja_JP.UTF-8 rd_NO_LVM rd_NO_DM quiet nomodeset clocksource = kvm-clock console = tty0 console = ttyS0,115200n8r crashkernel = auto nosoftlockup nohz = off highres = off intel_idle.max_cstate = 0 processor.max_cstate = 0 cgroup_disable = memory nmi_watchdog = 0 divider = 4 nosoftlockup mce = ignore_ce
        initrd /initramfs-2.6.32-431.17.1.el6.x86_64.img

각 GRUB 설정 항목에 대한 설명은지면 상 생략합니다. 항목별로 검색하여 확인하시면 좋겠습니다합니다.


ulimit 설정 변경

서버 부하 테스트를 할 때 ulimit 설정 관련 오류를 확인할 수없는 경우가 많기 때문에 ulimit에 대한 기본값을 변경합니다.  명령으로 설정할 수 있지만 다시 시작하면 기본값으로 돌아갑니다. "/etc/security/limits.conf" 에 설정해 두거나 다음과 같이 추가합니다.

제한 확인

ulimit -n -u -s

권장 설정 반영

ulimit -n 65536 -u 16384 -s 32768

시작시 권장 사항 반영

echo "ulimit -n 65536 -u 16384 -s 32768">> /etc/sysconfig/init

커널 파라미터 튜닝

다음 내용은 자신의 책임과 판단으로해야합니다. 설정은 "Low latency Trading System"의 설정을 참고로하고 있습니다. 반드시 설정 내용을 확인하고 자신의 시스템에 맞게 각 항목의 내용을 이해 한 다음 변경하십시오. 다음 설정 반영 인한 중단 및 문제 등에 대해 책임을지지 않습니다. 다음 설정은 IPV6를 비활성화하고 IPV4 만 사용하는 환경 설정입니다.

세마포어 계산과 메모리 Latency 문제 관련 설정 적용

다음 cat 명령으로 작성된 쉘을 실행하고 출력되는 내용을 커널 매개 변수 세마포어로 설정합니다. 방화벽 설정에서 리버 프록시 서버로 사용하거나 큰 사이트의 경우, 메모리에 맞게 "netfilter"의 CONNTRACK_MAX 튜닝을 할 필요가 있습니다.

CONNTRACK_MAX 튜닝

참조 http://wiki.khnet.info/index.php/Conntrack_tuning

OS_BIT = 64
RAMSIZE =`grep MemTotal / proc / meminfo | sed -e 's / ^ [^ 0-9] * //'| cut -d ''-f1`
HASHSIZE =`echo "scale = 0; ($ RAMSIZE * 1024) / 131072 / ($ OS_BIT / 32)"| bc -l`
CONNTRACK_MAX =`echo "scale = 0; $ HASHSIZE * 8"| bc -l`

튜닝 값 계산과 일부 설정 반영

계산 된 값을 커널 파라미터 설정 내용을 확인하고 수정합니다.

cd / opt
cat> "kernel_optimize.sh"<< 'EOF'
#! / bin / sh
SHARED_BUFFER_RATIO = 0.25
OPTIMAL_SHMMNI = 8192
OS_BIT = 64
echo "kernel.shmmni = $ OPTIMAL_SHMMNI"
MAX_MEM =`grep MemTotal / proc / meminfo | sed -e 's / ^ [^ 0-9] * //'| cut -d ''-f1`
OS_PAGE_SIZE =`getconf PAGE_SIZE`
OPTIMAL_SHMMAX =`echo "scale = 0; (8192 + 208) * (($ MAX_MEM * 1024) / $ OS_PAGE_SIZE) * $ SHARED_BUFFER_RATIO"| bc -l | cut -d ''-f1`0
echo kernel.shmmax = $ OPTIMAL_SHMMAX
OPTIMAL_SHMALL =`echo "scale = 0; ($ OPTIMAL_SHMMAX / $ OS_PAGE_SIZE) * ($ OPTIMAL_SHMMNI / 16)"| bc -l | cut -d ''-f1`
echo kernel.shmall = $ OPTIMAL_SHMALL
if [$ MAX_MEM -gt 8192]; then #latency issues configuration
    echo 2> / proc / sys / vm / dirty_ratio
    echo 1> / proc / sys / vm / dirty_background_ratio
else
    echo 10> / proc / sys / vm / dirty_ratio
    echo 5> / proc / sys / vm / dirty_background_ratio
fi
#netfilter 설정
HASHSIZE =`echo "scale = 0; ($ MAX_MEM * 1024) / 131072 / ($ OS_BIT / 32)"| bc -l`
CONNTRACK_MAX =`echo "scale = 0; $ HASHSIZE * 8"| bc -l`
echo "net.netfilter.nf_conntrack_max = $ CONNTRACK_MAX"
echo "options nf_conntrack hashsize = $ HASHSIZE"> /etc/modprobe.d/nf_conntrack.conf
EOF


# 기존 커널 매개 변수 파일의 백업
cp /etc/sysctl.conf /etc/sysctl.conf_backup

# 위 설정을 반영
sh kernel_optimize.sh

# 커널 매개 변수 설정
# 아래의 내용은 각 항목의 내용을 확인 위에서 실행하여 계산 된 수치로 변경하고 cat 명령을 실행하십시오. 수정은 ★ 표시가있는 부분이 될 수 있습니다.

cat> "/etc/sysctl.conf"<< 'EOF'
### 커널 매개 변수 설정
# SysRq 설정
kernel.sysrq = 0

# 스케줄러 설정
kernel.sched_nr_migrate = 12

# 코어 덤프 파일 이름 설정
kernel.core_uses_pid = 1

###### 튜닝 설정 ######
# 커널 메시지 큐 최대 크기
kernel.msgmnb = 65536

# 커널 메시지 최대 크기
kernel.msgmax = 65536

# 세마포어 튜닝 계산
# SHARED_BUFFER_RATIO = 0.25
# OPTIMAL_SHMMNI = 8192
#echo "kernel.shmmni = $ OPTIMAL_SHMMNI"
# MAX_MEM =`grep MemTotal / proc / meminfo | sed -e 's / ^ [^ 0-9] * //'| cut -d ''-f1`
# OS_PAGE_SIZE =`getconf PAGE_SIZE`
# OPTIMAL_SHMMAX =`echo "scale = 0; (8192 + 208) * (($ MAX_MEM * 1024) / $ OS_PAGE_SIZE) * $ SHARED_BUFFER_RATIO"| bc -l | cut -d ''-f1`0
#echo kernel.shmmax = $ OPTIMAL_SHMMAX
# OPTIMAL_SHMALL =`echo "scale = 0; ($ OPTIMAL_SHMMAX / $ OS_PAGE_SIZE) * (OPTIMAL_SHMMNI / 16)"| bc -l | cut -d ''-f1`
#echo kernel.shmall = $ OPTIMAL_SHMALL

# 기본 설정 내용
# kernel.shmmni = 4092
# kernel.shmmax = 68719476736
# kernel.shmall = 4294967296

# 커널 헤더 소스의 내용
#define SHMMAX 0x2000000 / * max shared seg size (bytes) * /
#define SHMMIN 1 / * min shared seg size (bytes) * /
#define SHMMNI 4096 / * max num of segs system wide * /
#define SHMALL (SHMMAX / getpagesize () * (SHMMNI / 16))
#define SHMSEG SHMMNI / * max shared segs per process * /

## SHMMAX SHMMNI 68719476736 4096
## SHMALL = ----------- * ---------- = ------------- * ------ = 4294967296
## PAGE_SIZE 16 4096 16

# 다음 4G 메모리 설정의 예
# 세마포어 튜닝 계산의 내용을 아래에서 설정합니다.

# 1 프로세스 당 공유 메모리의 최소 크기 (byte)
kernel.shmmni = 8192

# 시스템 전체의 공유 메모리 페이지 최대
# ★ 아래는 세마포어 튜닝 계산의 내용에 맞게 수정합니다.
kernel.shmmax = 20593713000

# 공유​​ 메모리 세그먼트의 바이트 수 제한
# ★ 아래는 세마포어 튜닝 계산의 내용에 맞게 수정합니다.
kernel.shmall = 2574213632

# 매개 변수 순서의 내용
#semmsl semmns semopm semmni
# 세마포어 ID 별 세마포 시스템 전체의 세마포 한 번에 실시 할 수있는 세마포어 작업의 수 세마포어 ID의 최대 값
#OracleDB (semopm)는 100 이상 설정 필수
# 다음 설정은 메모리 데이터베이스 ALTIBASE 튜닝 참고.
kernel.sem = 2000 32000 512 5029

# 파일 오픈 IO 관련
# Oracle / MySQL 튜닝 참조
fs.aio-max-nr = 1048576
fs.file-max = 6815744

# 메모리 튜닝
vm.swappiness = 20
vm.overcommit_ratio = 99
vm.overcommit_memory = 2

# IPV6 비활성화
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1

# 패킷 전송 해제
net.ipv4.conf.all.forwarding = 0
net.ipv4.conf.default.forwarding = 0

# listen 큐 제한 설정
net.core.somaxconn = 262144

# ICMP 에러 메시지를 무시
net.ipv4.icmp_ignore_bogus_error_responses = 1

# 위장 부정 패킷 : 리디렉션 기록
net.ipv4.conf.all.log_martians = 1
net.ipv4.conf.default.log_martians = 1

# 스푸핑 소스 IP 스푸핑 방지
net.ipv4.conf.all.rp_filter = 1

# L3 환경의 점보 프레임으로 통신하는 경우
# net.ipv4.tcp_mtu_probing = 1 

# 네트워크 자원 관련 설정
net.ipv4.tcp_fin_timeout = 15
net.ipv4.tcp_sack = 1
net.ipv4.tcp_fack = 1
net.ipv4.tcp_keepalive_time = 60
net.ipv4.tcp_keepalive_intvl = 3
net.ipv4.tcp_keepalive_probes = 3

# RFC1337을 준수 (Protect Against TCP Time-Wait)
net.ipv4.tcp_rfc1337 = 1

# 소켓의 고속 재활용 (DOS 공격 방지)
net.ipv4.tcp_max_tw_buckets = 1440000 
net.ipv4.tcp_tw_recycle = 1 
net.ipv4.tcp_tw_reuse = 1 

# TCP SYN Flood 공격 대책
net.ipv4.tcp_syncookies = 1

# RFC1323
# TCP 창 크기 조정 활성화 (64KByte 이상의 버퍼)
net.ipv4.tcp_timestamps = 0 
net.ipv4.tcp_window_scaling = 1

# 브로드 캐스트 주소로 ping에 응답 할 수없는
# ※ Smurf 공격 대책
net.ipv4.icmp_echo_ignore_broadcasts = 1

# ICMP Redirect 패킷을 거부
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0

# Source Routed 패킷은 거부
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0

# Kdump 사용 설정
net.ipv4.conf.all.force_igmp_version = 2
net.ipv4.conf.default.force_igmp_version = 2
kernel.unknown_nmi_panic = 1
kernel.panic_on_unrecovered_nmi = 1
kernel.panic_on_io_nmi = 1

# ARP 응답없이 설정
net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.default.arp_ignore = 1

# 스푸핑 (소스 IP 스푸핑 방지)
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1

# 클라이언트가 증가했을 때의 문제 해결 방법
net.ipv4.neigh.default.gc_thresh1 = 1024
net.ipv4.neigh.default.gc_thresh2 = 2048
net.ipv4.neigh.default.gc_thresh3 = 4096

# NIC 튜닝 설정
# 네트워크 버퍼 16M 충분
# 4MB까지 커널에서 자동 조정
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.core.rmem_default = 16777216
net.core.wmem_default = 16777216
net.core.optmem_max = 16777216
net.core.netdev_max_backlog = 250000
net.ipv4.tcp_mem = 4096 87380 16777216
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 87380 16777216
net.ipv4.tcp_max_orphans = 16777216
net.ipv4.tcp_max_syn_backlog = 65535
net.ipv4.tcp_low_latency = 1
net.ipv4.tcp_no_metrics_save = 1
net.ipv4.tcp_congestion_control = htcp
net.ipv4.neigh.default.unres_qlen = 100
net.ipv4.neigh.lo.unres_qlen = 100
net.ipv4.neigh.eth0.unres_qlen = 100
net.ipv4.neigh.eth1.unres_qlen = 100
net.ipv4.route.flush = 1

# 고부하의 서버 / NAT / 프록시 서버에 대한 오류 방지 설정
# iptables를 다시 시작해야, iptables가 동작하지 않는 환경에서는 설정할 필요는 없습니다.

# net.netfilter.nf_conntrack_max 계산
# OS_BIT = 64
# RAMSIZE =`grep MemTotal / proc / meminfo | sed -e 's / ^ [^ 0-9] * //'| cut -d ''-f1`
# HASHSIZE =`echo "scale = 0; ($ RAMSIZE * 1024) / 131072 / ($ OS_BIT / 32)"| bc -l`
#CONNTRACK_MAX =`echo "scale = 0; $ HASHSIZE * 8"| bc -l`
#echo net.netfilter.nf_conntrack_max = $ CONNTRACK_MAX

# 4G 메모리 설정 예
# ★ 아래는 메모리에 맞게 수정합니다.
#iptables가 시작하지 않는 경우 반영시 오류가 발생합니다.
net.netfilter.nf_conntrack_max = 122576
net.netfilter.nf_conntrack_generic_timeout = 10
net.netfilter.nf_conntrack_tcp_timeout_established = 2160
net.netfilter.nf_conntrack_tcp_timeout_close = 8
net.netfilter.nf_conntrack_tcp_timeout_close_wait = 10
net.netfilter.nf_conntrack_tcp_timeout_time_wait = 10
net.netfilter.nf_conntrack_tcp_timeout_fin_wait = 10
net.netfilter.nf_conntrack_tcp_timeout_syn_sent = 10
net.netfilter.nf_conntrack_tcp_timeout_syn_recv = 10
net.netfilter.nf_conntrack_tcp_timeout_max_retrans = 30
net.netfilter.nf_conntrack_tcp_timeout_unacknowledged = 30
net.netfilter.nf_conntrack_tcp_loose = 1
net.netfilter.nf_conntrack_tcp_be_liberal = 0
net.netfilter.nf_conntrack_tcp_max_retrans = 3
net.netfilter.nf_conntrack_acct = 1
net.netfilter.nf_conntrack_checksum = 1
net.netfilter.nf_conntrack_log_invalid = 0
net.netfilter.nf_conntrack_expect_max = 256
EOF