NGINX vs MPM-PREFORK vs MPM-EVENT
Ubuntu 14.04 에서 apache 2.4 MPM prefork 를 사용중이다.
prefork 방식은 안정적이고 다른 소프트웨어와 호환성이 좋다고 알려져 있다.
동시 접속에 대해서는 쓰레드 방식의 worker / event / nginx 가 좋다고 알려져 있다.
그리고 나는 이것들이 실제 지금 우리 서버에도 해당되는지 테스트를 해봤다.
더불어 현재 설치된 prefork 방식의 한계도 알아보려고 한다.
현재 서버는 AWS r1.large 이다.
Prefork setting
# vi /etc/apache2/mods-enabled/mpm_prefork.conf <IfModule mpm_prefork_module> StartServers 5 MinSpareServers 5 MaxSpareServers 10 MaxRequestWorkers 150 MaxConnectionsPerChild 0 </IfModule> | cs |
최초 서버 시작시 프로세스는 5개로 시작하고, 여분의 프로세스 범위는 5~10 이고 요청을 처리할 수 있는 최대 프로세스 수는 150 개로 설정되어 있다.
하나의 프로세스당 하나의 요청을 받으니까 150개의 요청을 한번에 받고나면 150개가 클라이언트에 응답을 돌려줄 때까지는 더 이상의 요청을 받을 수 없다.
응답을 빨리 한 프로세스는 또 다른 요청을 받을 수 있을 것이고... 그것은 페이지의 용량 등 여러가지 리소스에 따라 달라질 것이다.
프로세스 확인
웹서버를 시작하고 나서 apache2 프로세스를 검색하면
18625 ? Ss 0:01 /usr/sbin/apache2 -k start 18630 ? S 0:01 /usr/sbin/apache2 -k start 18642 ? S 0:01 /usr/sbin/apache2 -k start 18652 ? S 0:01 /usr/sbin/apache2 -k start 18673 ? S 0:00 /usr/sbin/apache2 -k start 18711 ? S 0:00 /usr/sbin/apache2 -k start | cs |
부모 프로세스인 Ss 를 제외하면 프로세스가 5개 맞다.
Prefork 과부하 테스트
Request page size : 52kb
Number of Threads : 최대 500
Ramp-Up Period : 1
Loop Count : 1
웹 서비스 성능 테스트 툴은 JMeter 를 사용하였다. (Apache Bench 도 결과적으로는 거의 흡사했다.)
테스트 PC 의 CPU 가 100% 가 되면 요청 Thread 가 동시에 전달될 수 없으므로, 요청 Thread(동시접속)는 500 정도까지 테스트 해보았다.
요청 페이지는 DB 연결도 필요하고 CDN 으로부터 적지 않은 이미지들도 불러오는 일반 쇼핑몰 메인 페이지 수준의 페이지이다.
Thread 1~10 은 응답속도가 0.4 초 나왔다. (전혀 문제 없음)
Thread 20 은 응답속도가 0.4~0.8 초 나왔다. 평균 0.6 (거의 문제 없음)
Thread 30 은 응답속도가 0.4~1.4 초 나왔다. 평균 1.0 (이정도는 문제 없음)
Thread 40 은 응답속도가 0.4~3.0 초 나왔다. 평균 1.6 (벌써 이러면 좀 걱정 됨)
Thread 50 은 응답속도가 0.4~3.0 초 나왔다. 평균 1.9 (최대 응답 속도는 이전과 동일)
Thread 60 은 응답속도가 0.6~3.9 초 나왔다. 평균 2.4 (벌어지기 시작함)
Thread 70 은 응답속도가 0.6~4.7 초 나왔다. 평균 2.8 (...)
Thread 80 은 응답속도가 0.6~5.8 초 나왔다. 평균 3.3
Thread 90 은 응답속도가 0.9~6.4 초 나왔다. 평균 3.9
Thread 100 은 응답속도가 0.8~7.4 초 나왔다. 평균 4.4
Thread 110 은 응답속도가 0.5~7.9 초 나왔다. 평균 4.6
Thread 120 은 응답속도가 0.5~8.9 초 나왔다. 평균 5.2
Thread 130 은 응답속도가 0.5~9.9 초 나왔다. 평균 5.8
Thread 140 은 응답속도가 0.6~10.4 초 나왔다. 평균 6.3
Thread 150 은 응답속도가 0.6~11.2 초 나왔다. 평균 6.9
--(MaxRequestWorkers 설정값이 150 이라서 그런건지 뭔지 여기까지는 에러가 없다.
Thread 160 은 응답속도가 0.6~12.2 초 나왔다. 평균 7.2
Thread 200 은 응답속도가 0.9~15.6 초 나왔다. 평균 9.3
Thread 250 은 응답속도가 0.9~19.6 초 나왔다. 평균 11.4
Thread 300 은 응답속도가 0.6~22.8 초 나왔다. 평균 13.6
Thread 350 은 응답속도가 0.8~26.2 초 나왔다. 평균 15.4 (error 5.14%)
Thread 400 은 응답속도가 0.6~29.0 초 나왔다. 평균 16.9 (error 8.50%)
Thread 500 은 응답속도가 5.4~24.2 초 나왔다. 평균 17.5 (error 35.8%)
각 테스트는 프로세스가 안정화 되고나서 테스트를 하였다.
MaxRequestWorkers 설정 값이 150 인 상태에서 52kb 짜리 테스트 페이지는 동시 요청을 300 개 정도까지는 에러 없이 응답하였다.
발생한 에러는 콘솔에 툴 에러로 나왔는데 어찌됐든 응답 받지 못했으니 대충 에러로 인식.
RAM 사용량은 thread 500 요청시 8GB 중 apahce 에서 최대 1GB 정도만을 사용했다. CPU 도 25% 정도까지만 올라갔다. (서버 리소스는 완전 널널하다는...)
사실 3초 이상 브라우저의 로딩 화면을 바라보고 있는 사람은 거의 없다.
최대 3초 까지 방문 유저가 참아 준다고 치면 현재 상태에서의 동접은 50 정도까지가 안정적인 것으로 보인다.
매우 실망스러운 수치이다.
성능 테스트를 직접 해본것은 처음이였지만 내가 알고 있던 성능 테스트 결과와는 사뭇 달랐다.
이때까지만 해도 일단 페이지 자체가 가볍지 않고, 튜닝도 전혀 하지 않은 기본 설정 상태라서 그럴것이라고 생각했다.
그렇다면 MaxRequestWorkers 값을 늘리면 응답 속도가 늘어날까? (150->256)
Thread 50 은 응답속도가 0.7~3.2 초 나왔다. 평균 2.0 (비슷)
Thread 80 은 응답속도가 0.8~6.0 초 나왔다. 평균 3.4 (비슷)
Thread 100 은 응답속도가 0.9~7.5 초 나왔다. 평균 4.3 (비슷)
Thread 120 은 응답속도가 0.9~8.9 초 나왔다. 평균 5.0 (비슷)
Thread 150 은 응답속도가 1.0~11.4 초 나왔다. 평균 6.6 (비슷)
Thread 200 은 응답속도가 0.8~15.0 초 나왔다. 평균 8.5 (비슷)
Thread 300 은 응답속도가 0.9~22.5 초 나왔다. 평균 13.3 (비슷)
Thread 350 은 응답속도가 0.9~26.1 초 나왔다. 평균 15.8 (error 11.11%)
프로세스를 150 에서 256 으로 올려도 속도면에서는 거의 차이가 없었고 에러도 동일한 구간에서 발생하기 시작했다.
그렇다면 현재 상황에서는 프로세스 수를 1024 정도로 올리더라도 응답속도나 에러는 동일할 것으로 판단되었다.
그래도 확실하게 테스트.
MaxRequestWorkers 구성은 ServerLimit 에서 지정한 값보다 클 수 없는데, serverLimit 의 기본값은 256 이다.
MaxRequestWorkers 를 256 보다 크게 설정하려면 ServerLimit 값을 256보다 크게 설정해야 한다.
ServerLimit 는 여분의 메모리에 할당되므로 이 값을 너무 크게 설정하면 시스템이나 apache 가 불안정해 질 수 있다고 한다.
ServerLimit 는 200000 까지 설정할 수 있으며, 이 보다 더 큰 값을 적용시키려면 MPM 소스 파일에 MAX_SERVER_LIMIT 값을 수정하고 apache 를 재컴파일해야 한다.
MaxRequestWorkers 256->1024
<IfModule mpm_prefork_module> ServerLimit 1024 StartServers 5 MinSpareServers 5 MaxSpareServers 10 MaxRequestWorkers 1024 MaxConnectionsPerChild 0 </IfModule> | cs |
Thread 50 은 응답속도가 0.5~3.4 초 나왔다. 평균 2.1 (비슷)
Thread 100 은 응답속도가 0.9~7.7 초 나왔다. 평균 4.4 (비슷)
Thread 200 은 응답속도가 0.9~15.7 초 나왔다. 평균 9.0 (비슷)
Thread 300 은 응답속도가 1.0~23.5 초 나왔다. 평균 13.6 (비슷)
Thread 350 은 응답속도가 0.9~25.3 초 나왔다. 평균 15.3 (error 6.00%)
달라진게 없다. 하하~ ...prefork...
포기할 수 없다. 마지막으로 1024->100000 까지 올려봤다.
Thread 350 은 응답속도가 1.7~26.6 초 나왔다. 평균 16.0 (error 1.43%)
확실히 알게 되었다. prefork 튜닝은 다 부질 없음을...ㅋ
어짜피 첫 페이지에 대한 동시접속만 알아보려는 것이므로 Timeout, KeepAlive 등의 테스트는 하지 않았다.
Multi threads
NGINX vs MPM-WORKER vs MPM-EVENT
프로세스 방식의 mpm-prefork, 멀티 스레드 방식의 nginx / mpm-worker / mpm-event.
prefork 의 실망감을 감추지 못한채 큰 기대감을 갖고 위 3가지에 대해 prefork 와 동일하게 테스트 해보았다.
prefork 와 동일한 환경에서의 결과는...
...
...
...
...
...
따로 적기도 짜증날 정도로 prefork / nginx / mpm-worker / mpm-event 의 결과는 비슷했다. 스레드 수를 늘려도 마찬가지.
순간 네트워크의 속도가 약간씩 영향을 주는 것을 감안할 때 무엇이 더 좋다고 딱히 말할 수 없을 정도로 큰 차이가 없었다.
또한 AWS 에서 가장 낮은 사양의 t2.micro 에서도 동일했다. 하하.
(phpinfo 정도의 가벼운 페이지는 모두 1000 개의 동시접속을 1,2 초 내에 처리했다.)
나의 결론은 이렇다.
1. Apache 를 쓰던 Nginx 를 쓰던 속도나 처리 상에 큰 속도 차이는 없다.
2. 웹서버의 사양도 속도에 큰 차이를 보이지 않는다. (서버 사양을 늘리느니 서버를 한 대 더 추가하는게 나을듯...)
3. 튜닝한다고 프로세스, 쓰레드 수를 늘려도 처리 속도는 차이가 없다.
난 결국 이미 깔려 있는, 그리고 이 중 가장 안정적이라는 prefork 를 유지하기로 마음 먹었다.
끝!
WRITTEN BY
- 손가락귀신
정신 못차리면, 벌 받는다.