nginx (1.9.5) 설치 및 성능테스트

[Nginx 설치 및 성능테스트]

1.설치환경

CPU : Intel(R) Core(TM)2 Quad CPU    Q6600  @ 2.40GH (가상화 환경)
Ram : 1G
Os : Sulinux 2014 R6 64bit
작성자 : 서비님 (http://dslee1.blogspot.kr/)

2. Nginx 소개

"더 적은 자원으로 더 빠르게 데이터를 서비스 할 수 있다."

nginx 는 차세대 웹서버로 불리고 있으며, 위 그래프에서도 알수 있듯이 꾸준한 상승세를 보이고 있다.  Nginx 는 러시아의 개발자이자 서버관리자인 이고르 시셰프(Igor Sysoev)에 의해 2002년부터 개발되기 시작했다고 하며,  2004년 첫 릴리즈 이래, 2012년 전세계적으로 약 12% 이상의 점유율을 기록하고 있다 한다. 현재 Apache에 있어 가장 위협이 되고 있는 존재로 급부상 중이다.

nginx 는 새로운 시대의 요청에 부응해서 만들어진 웹서버이다. 개발의 모든 목적이 높은 성능에 맞춰져 있다. 그리고 잘 사용하지 않는 기능은 과감하게 제외했다. 덕분에 폭발적인 증가세에 있는 인터넷 서비스를 지탱하는데 적합하다.

3. 설치

DB 를 제외한 기본적입 웹서비스를 할수있는 환경을 구성할 것이다. nginx + php 설치를 목적으로 한다.

3.1 기본페키지 삭제

기존에 yum 으로 설치된 패키지를 삭제하도록 한다. 이곳에서는 nginx + php 만 설치하기 때문에 시스템 자원을 효율적으로 사용하기위해서 불필요한 프로세스는 삭제하도록 한다.

yum -y remove httpd*
yum -y remove mysql*
yum -y remove php*

3.2 기본 라이브러리 설치

nginx 및 php 는 다양한 라이브러리를 이용하여 설치를 진행한다. 처음 os 를 설치하고 난 이후에 기존에 설치된 라이브러리들이 있을수있지만 업데이트 및 빠진 라이브러리들을 설치한다.

yum -y install zlib zlib-devel libxml2 curl libjpeg libjpeg-devel libpng libpng-devel freetype freetype-devel freetype-utils fontconfig fontconfig-devel gd gd-devel php-gd libmcrypt libmcrypt-devel gcc g cpp gcc-c compat-gcc-32-g77 flex glibc openssl openssl-devel gmp gmp-devel mhash mhash-devel php-soap libc-client* net-snmp* pcre-devel.x86_64

3.3 php 설치

이제 nginx 의 대표적인 웹언어인 php 를 설치하도록 하겠다. 설치 버전은 5.5.x 버전을 사용하면 된다.

3.3.1 다운로드

공식홈페이지에서 다운로드 하도록 한다.


파일명이 mirror 되어있기 때문에 변경해준다.

mv mirror php-5.5.7.tar.gz

3.3.2 라이브러리 링크

php configration 과정에서 아래와 같은 에러메시지가 확인이 될것이다. 아래와 같이 링크 해준다.
configure: error: libjpeg.(a|so) not found
ln -s /usr/lib64/libjpeg.so /usr/lib/
ln -s /usr/lib64/libpng.so /usr/lib/

3.3.3 mcrypt.h 설치

tar xvfz libmcrypt-2.5.7.tar.gz
cd libmcrypt-2.5.7
./configure && make && make install

3.3.4 환경 설정 및 설치
 tar xvfz php-5.5.7.tar.gz
 cd php-5.5.7
./configure --prefix=/usr/local/php-5.5.7 --with-config-file-path=/usr/local/lib --with-gd --with-freetype-dir --with-zlib --enable-sockets --enable-gd-native-ttf --with-png-dir --with-jpeg-dir --enable-sigchild --with-gettext --enable-mbstring --enable-inline-optimization --enable-bcmath --enable-shmop --enable-calendar --enable-ftp --with-gdbm --with-iconv --enable-mbregex --with-openssl --with-curl --enable-soap --disable-debug --with-mcrypt --with-kerberos --enable-zip --with-zlib-dir --enable-exif --enable-fpm --with-fpm-user=nobody --with-fpm-group=nobody && make && make install

php 디렉토리로 링크 걸어둔다. 이곳은 단순히 사용상의 편의를 위해서 하는것이다.

ln -s /usr/local/php-5.5.7  /usr/local/php

php.ini 환경설정 파일은 설치된 디렉토리에 복사한다.
cp php.ini-production /usr/local/lib/php.ini

php.ini 파일을 열어서 몇가지 설정을 변경해준다.

vi /usr/local/lib/php.ini
* short_open_tag
short_open_tag = On

* error_reporting
error_reporting = E_ALL & ~E_DEPRECATED & ~E_NOTICE & ~E_STRICT

* display_errors
display_errors = On

* date.timezone
date.timezone = "Asia/Seoul"

-- 여기서 부터 php-fpm 설정
일반적으로 nginx는 동적인 페이지 구현이 어렵다. 이부분을 해결하기 위해서 fast-cgi 기능을 사용하는 php-fpm 을 설치해야된다.

cd sapi/fpm
cp -a php-fpm.conf /usr/local/php/etc/php-fpm.conf

* php-fpm (start|stop) 등의 스크립트 지원이 없으므로 직접 작성

— 여기서 부터 php-fpm 실행 스크립트 /etc/rc.d/init.d/php-fpm

vi /etc/rc.d/init.d/php-fpm

#! /bin/sh
### BEGIN INIT INFO
# Provides: php-fpm
# Required-Start: $remote_fs $network
# Required-Stop: $remote_fs $network
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: starts php-fpm
# Description: starts the PHP FastCGI Process Manager daemon
### END INIT INFO
prefix=/usr/local/php
exec_prefix=${prefix}
php_fpm_BIN=${exec_prefix}/sbin/php-fpm
php_fpm_CONF=${prefix}/etc/php-fpm.conf
php_fpm_PID=${prefix}/var/run/php-fpm.pid
php_opts="--fpm-config $php_fpm_CONF --pid $php_fpm_PID"
wait_for_pid () {
try=0
while test $try -lt 35 ; do
case "$1" in
"created")
if [ -f "$2" ] ; then
try=""
break
fi
;;
"removed")
if [ ! -f "$2" ] ; then
try=""
break
fi
;;
esac
echo -n .
try=`expr $try 1`
sleep 1
done
}
case "$1" in
start)
echo -n "Starting php-fpm "
#$php_fpm_BIN --daemonize $php_opts
$php_fpm_BIN $php_opts
if [ "$?" != 0 ] ; then
echo " failed"
exit 1
fi
wait_for_pid created $php_fpm_PID
if [ -n "$try" ] ; then
echo " failed"
exit 1
else
echo " done"
fi
;;
stop)
echo -n "Gracefully shutting down php-fpm "
if [ ! -r $php_fpm_PID ] ; then
echo "warning, no pid file found - php-fpm is not running ?"
exit 1
fi
kill -QUIT `cat $php_fpm_PID`
wait_for_pid removed $php_fpm_PID
if [ -n "$try" ] ; then
echo " failed. Use force-quit"
exit 1
else
echo " done"
fi
;;
force-quit)
echo -n "Terminating php-fpm "
if [ ! -r $php_fpm_PID ] ; then
echo "warning, no pid file found - php-fpm is not running ?"
exit 1
fi
kill -TERM `cat $php_fpm_PID`
wait_for_pid removed $php_fpm_PID
if [ -n "$try" ] ; then
echo " failed"
exit 1
else
echo " done"
fi
;;
restart)
$0 stop
$0 start
;;
reload)
echo -n "Reload service php-fpm "
if [ ! -r $php_fpm_PID ] ; then
echo "warning, no pid file found - php-fpm is not running ?"
exit 1
fi
kill -USR2 `cat $php_fpm_PID`
echo " done"
;;
*)
echo "Usage: $0 {start|stop|force-quit|restart|reload}"
exit 1
;;
esac

저장 후
chmod 755 /etc/rc.d/init.d/php-fpm

3.4 Nginx 설치

3.4.1 다운로드
공식홈페이지에서 가장 최신버전을 받는것을 추천한다.

tar xvfz nginx-1.9.5.tar.gz
cd nginx-1.9.5
./configure --prefix=/usr/local/nginx-1.9.5 --user=nobody --group=nobody --with-http_ssl_module --with-http_dav_module --with-http_gzip_static_module --without-mail_pop3_module --without-mail_imap_module --without-mail_smtp_module && make && make install

관리를 편하기 하기위해서 링크를 걸어주도록 한다.

ln -s /usr/local/nginx-1.9.5 /usr/local/nginx

3.4.2 환경설정

vi /usr/local/nginx/conf/nginx.conf

-- 여기서 부터 nginx.conf 여기부터
#user nobody;
# worker_processes 1;  본인의 시스템 환경에 맞게 설정해주면 된다.
worker_processes "4";     
error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
pid logs/nginx.pid;
events {
worker_connections 10240;
}
http {
index index.html index.php;
include 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 logs/access.log main;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
gzip on;
gzip_disable "MSIE [1-6]\.(?!.*SV1)";
gzip_http_version 1.0;
gzip_comp_level 9;
gzip_proxied any;
gzip_types text/plain text/css application/x-javascript text/xml application/xml rss text/javascript;
server {
listen 80;
client_max_body_size 50M;
client_body_timeout 600;
client_header_timeout 600;
server_name 192.168.0.71
root html;
index index.html index.php;
location ~ \.(php|html)$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
# another virtual host using mix of IP-, name-, and port-based configuration
#
#server {
# listen 8000;
# listen somename:8080;
# server_name somename alias another.alias;
# location / {
# root html;
# index index.html index.htm;
# }
#}
# HTTPS server
#
#server {
# listen 443;
# server_name localhost;
# ssl on;
# ssl_certificate cert.pem;
# ssl_certificate_key cert.key;
# ssl_session_timeout 5m;
# ssl_protocols SSLv2 SSLv3 TLSv1;
# ssl_ciphers HIGH:!aNULL:!MD5;
# ssl_prefer_server_ciphers on;
# location / {
# root html;
# index index.html index.htm;
# }
#}
}

3.4.3 실행 스크립트

nginx는 자동으로 스크립트가 생성되어있지 않다. 이 때문에 공식홈페이지 문서에 있는 스크립트를 참조하면 된다.

* 여기서 부터 ngnix 실행 스크립트 vi /etc/rc.d/init.d/ngnix

vi /etc/rc.d/init.d/ngnix
#!/bin/sh
#
# nginx - this script starts and stops the nginx daemin
#
# chkconfig: - 85 15
# description: Nginx is an HTTP(S) server, HTTP(S) reverse \
# proxy and IMAP/POP3 proxy server
# processname: nginx
# config: /usr/local/nginx/conf/nginx.conf
# pidfile: /var/run/nginx.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
nginx="/usr/local/nginx/sbin/nginx"
prog=$(basename $nginx)
NGINX_CONF_FILE="/usr/local/nginx/conf/nginx.conf"
lockfile=/var/lock/subsys/nginx
start() {
[ -x $nginx ] || exit 5
[ -f $NGINX_CONF_FILE ] || exit 6
echo -n $"Starting $prog: "
daemon $nginx -c $NGINX_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() {
configtest || return $?
stop
start
}
reload() {
configtest || return $?
echo -n $"Reloading $prog: "
killproc $nginx -HUP
RETVAL=$?
echo
}
force_reload() {
restart
}
configtest() {
$nginx -t -c $NGINX_CONF_FILE
}
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|configtest}"
exit 2
esac
저장 후
chmod 777 /etc/rc.d/init.d/ngnix

4. 성능테스트

지금까지 nginx를 설치를 완료하였다. 여기에서는 설치된 nginx가 과연 어느정도의 성능을 보여주는지 테스트 해보도록 하겠다. 물론 리얼서버만큼의 만족도와 신뢰성을 얻기는 힘들겠지만, 대략적인 성능체감을 할수있을것 같다.

단독으로 테스트를 하기 보다는 현재 전세계적으로 많이 사용하는 apache 와 함께 비교를 해보도록 하겠다.

4.1 설치환경 비교
아래는 nginx 및 apache 설치환경 비교 내용이다.

[nginx]
버전 : 1.9.5 (현재가장 최신버전 2015.10.21)
MPM : event
cpu : Intel(R) Core(TM)2 Quad CPU    Q6600  @ 2.40GHz (가상화 pc)
ram : 1G
os : sulinux 2014 R6 (최신커널업데이트)

설치 직후 튜닝은 거의 진행되지 않음.

[apache]
버전 : 2.4.17 (현재가장 최신버전 2015.10.21)
MPM : worker 및 event
cpu : Intel(R) Core(TM)2 Quad CPU    Q6600  @ 2.40GHz (가상화 pc)
ram : 1G
os : sulinux 2014 R6 (최신커널업데이트)

<worker 튜닝>
<IfModule mpm_worker_module>
   StartServers          5
   MinSpareThreads       100
   MaxSpareThreads       500
   ThreadsPerChild         25
   MaxRequestWorkers      1024
   MaxConnectionsPerChild   0
</IfModule>

<event 튜닝>
<IfModule mpm_event_module>
          ThreadLimit          100
  StartServers         5
  MaxRequestWorkers    5500
  ServerLimit          200
  MinSpareThreads      100
  MaxSpareThreads      1000
  ThreadsPerChild      100
  MaxRequestsPerChild  0
</IfModule>

4.2 테스트 프로그램

vi test2.php

<?
 $str=array();
 for($i=1;$i<=100;$i++){
    $str2+=$i%3;
    $str[$i]=$str2;
  }
  echo "ok";
?>

4.3 성능 테스트
테스트용 성능툴은 apache 에 기본적으로 제공되는 ab 를 이용하도록 한다.

각각 2번씩 총 6번의 테스트를 진행하였다.

ab -n 10000 -c 100 http://192.168.0.71/test2.php
100개의 쓰레드를 이용하여 10.000 호출.

ab -n 100000 -c 100 http://192.168.0.71/test2.php
100개의 쓰레드를 이용하여 100.000 호출

4.4 결과

total 시간.

Nginx 1.9.5
Apache worker
Apache event
10.000 호출
12.313 seconds
16.037 seconds
13.386 seconds
100.00 호출
135.425 seconds
158.746 seconds
145.933 seconds
서버 부하(10.000일때)
load average: 0.59
load average: 19.77
load average: 1.48
서버 부하(100.000일때)
load average: 1.86
load average: 121.44
load average: 7.06

단순테스트 진행이었지만 생각보다 nginx의 성능이 apache 보다 우수하다는걸 알수 있었다.
확실히 쓰레드방식을 사용하는 apache의 worker 방식은 시스템 부하 및 처리시간이 가장 많이 나타나게 되었다. 반면에 이벤트 방식을 사용하는 apache 및 nginx 는 처리시간도 짧고, 시스템 부하 면에서 우수한 성능을 보여주는걸 확인하였다. 이 테스트를 평균 10번 정도 테스트 하였으며, 해당 평균을 계산한 것이다.

접속자가 많으며, cpu 를 많이 사용하는 시스템에서는  apache event 방식이나 또는 nginx 를 사용하면 높은 퍼포먼스를 보여주지 않을까 생각 된다.