최영석 zealot33@gmail.com | NHN Business Platform 글로벌 플랫폼 개발 랩의 과장이다. 대학, 대학원에서 수학, 응용수학을 전공하고 TmaxSoft, FistGlobal을 거쳐 현재는 NHN Business Platform에 입사해 사내에 NGINX를 확산하는 업무를 맡고 있다.
월드 와이드 웹 부흥 역사에서 중심적인 역할을 했던 아파치 웹서버가 점점 NGINX에 그 자리를 내주기 시작해 현재는 대규모 트래픽을 처리하는 웹서비스의 경우 NGINX를 사용하는 비율이 점점 높아지고 있는 추세다.
<그림 1> Top 사이트 웹서버 사용현황
NGINX는 러시아인 igor Sysoev가 2002년에 만들기 시작해 2004년에 처음 릴리즈한 웹(HTTP) 서버, reverse proxy, IMAP/POP3 서버다. NGINX는 C10K problem(하나의 웹서버에 10,000개의 클라이언트 접속을 동시에 다룰 수 있는 기술적 문제)을 해결하기 위해 기존의 아파치 방식처럼 하나의 스레드에서 하나의 클라이언트 요청을 처리하는 것이 아니라 Event-driven(Asynchronous) 구조를 사용한다. NGINX 이외에도 Lighttpd, Tornado, Magnum, Aleph 등 최근에 개발된 많은 웹서버들과 서버 사이드 자바스크립트인 Node.js가 Event-driven 구조를 사용하고 있다.
2000년대 초반 인터넷 붐과 함께 더 많은 요청을 처리할 수 있는 웹서버에 시선이 쏠렸고 이때 등장한 것이 C10K problem이다. 더 많은 요청의 처리를 위해선 기존보다 나은 Network I/O 기술과 스레드 관리 기술 등이 개발될 필요가 있었다. 이 시기에 리눅스에서도 epoll, NPTL 등 기존에 비해 훨씬 발전된 기술이 적용됐다. The C10K problem(http://www.kegel.com /c10k.html)에서 관련 기술에 대한 정보를 제공하고 있으니 참고하자.
Event-driven Architecture(EDA a.k.a Asynchronous)
EDA 방식은 기존의 아파치 웹서버가 사용하는 방식(하나의 스레드에서 하나의 클라이언트를 처리하는 방식)보다 훨씬 적은 스레드개수로 훨씬 많은 클라이언트를 처리할 수 있다. 아파치 웹서버처럼 하나의 스레드에서 하나의 클라이언트를 처리한다면 ‘accept’와 persistence layer에서 정보를 읽거나 쓴 후 가공해 클라이언트에 전달할 때까지 I/O 문제로 스레드가 대기해야 할 때가 잦은 데다 클라이언트 개수만큼 스레드가 생성돼야 한다. 하지만 EDA 방식에서는 각 상태(state)를 정하고 여기서 event(가령 accept가 이루어져야 할 때 또는 응답 결과를 다 생성했을 때 등)가 발생할 때마다 이 event를 처리하게 해 더 적은 스레드로(또는 스레드 없이) CPU가 놀지 않고 일하게 할 수 있다.
NGINX는 아파치 웹서버가 제공하는 거의 모든 기능들을 제공한다.
● NGINX 제공 기능
- handling of static files
- reverse proxy
- load balancing
- SSL support
- FastCGI
- Virtual Host
- FLV Streaming
- MP4 Streaming
- Web page access authentication
- gzip
- URL Rewriting
- Custom Logging
- SSI
- WebDAV
NGINX의 사용 현황
W3Techs.com가 발표한 통계자료에 따르면 2012년 4월 13일을 기준으로 NGINX의 웹서버 시장 점유율은 10.9%다.
<그림 2> 전체 웹서버 사용현황
<그림 2>를 보면 NGINX가 전체 웹서버 중 3위를 차지하고 있다. 또한 사용량이 증가하는 추세로 보여 곧 마이크로소프트 IIS를 따라 잡으리라 예상된다. 트래픽이 많은 1,000개의 웹사이트(<그림 1>참조)에서도 아파치 웹서버를 곧 따라 잡을 수 있을 것으로 보인다.
<그림 3> 웹서버 사용량 증감추이
<표 1> 대표적인 NGINX 사용 사이트
alexa.com은 트래픽을 기준으로 하는 전 세계 사이트들의 순위를 발표하고 있다. <표 1>은 2012년 4월 13일 기준으로 alexa. com이 발표한 Top 500 사이트들 중 NGINX를 사용하고 있는 대표적인 사이트들이다.
<그림 4>는 NGINX가 웹서버 시장에서 어떤 위치를 차지하고 있는가를 나타낸다. 사용 시기가 상대적으로 오래되지 않아 총 점유율에서는 세 번째일 뿐이지만 상대적으로 트래픽이 높은 사이트들에서 사용되고 있음을 확인할 수 있다.
<그림 4> NGINX의 시장지위
NGINX의 특징 이해
Non blocking event driven 방식
NGINX는 기본적으로 Non blocking 네트워크 통신 방식으로 동작한다. socket 인터페이스들은 바로 결과를 리턴하는 것이 있고 경우에 따라 Blocking 되는 것도 있다. socket(), setsockopt() 등은 blocking 없이 결과를 리턴한다. connect(), send(), recv(), close() 등은 경우에 따라 Bocking 될 수도 있다. NGINX는 지체되지 않을 것을 확인한 다음에만 위의 함수들을 호출한다. send(), recv()의 경우에는 epoll을 사용해 blocking 여부를 확인한다. send(), revc()를 호출하는 코드들은 Event-driven 형태로 구성된다. 하나의 event는 socket과 socket의 상태 및 실행할 함수로 구성되고 웹서버는 웹브라우저가 보낸 요청을 네트워크를 통해 전달받아 처리하기 때문에 NGINX의 내부가 거의 전부 Event-drive의 형태로 동작하게 된다. NGINX는 미리 설정된 개수의 worker 프로세스로 운영되고 각각의 프로세스는 싱글 스레드로 동작한다. 아파치 웹서버와는 다르게 설정된 개수의 스레드만을 사용하기 때문에 아파치에 비해 CPU, 메모리등 자원 사용률이 현격하게 낮은 편이다.
장점은 우수한 성능
앞에서 언급했듯이 NGINX는 아파치에 비해 낮은 자원 사용률을 가진다. 일반적으로 NGINX는 아파치에 비해 높은 성능을 가지고 있다고 알려져 있지만 성능은 workload의 특성과 양에 따라 천차만별이므로 딱 잘라 결론 내리기는 어렵다. 하나의 favicon,ico 파일을 서비스하기 위해 호출되는 시스템 함수의 개수를 strace를 이용해 측정한 <표 2>를 보면 아파치는 31개의 시스템 함수를 호출하고 NGINX는 16개의 시스템 함수를 호출했다.
<표 2> Apaceh와 NGINX 시스템 콜 비교
<그림 5> 아파치 2.4 VS NGINX(9KB)
<그림 6> 아파치 2.4 VS NGINX(54KB)
최근 아파치 웹서버 진영에서 6년 만에 메이저 릴리즈된 아파치 2.4 버전도 Asynchronous를 지원하고 NGINX만큼 성능이 좋다는 이야기가 있었다. 하지만 테스트한 결과는 달랐다(<그림 5>, <그림 6> 참조).
모듈 작성의 어려움
NGINX는 모듈 작성이 어렵기로 유명하다. 아파치 웹서버에는 Apache Portable Runtime(APR)이라는 인터페이스가 존재하는데 대부분의 개발자는 APR 문서를 읽고 필요한 함수를 사용해 모듈을 작성한다. 하지만 NGINX에는 아직 그런 자세하고 친절한 문서가 없다. NGINX 모듈 개발자는 실제 코드를 읽고 학습해 나가는 방법밖에 없는데다 원 개발자인 Igor Sysoev가 주석 또한 거의 남겨놓지 않았다. 하지만 NGINX 사용률이 점차 증가함에 따라 써드파티 모듈을 만드는 개발자들이 증가했고 그 중에 몇몇은 자신들의 경험을 바탕으로 자신의 블로그 등에 NGINX 내부와 configuration 등에 대한 여러 글들을 올리고 있어 도움을 받을 수 있다. 다음 회에서는 NGINX를 공부하는 데 도움을 받을 수 있는 커뮤니티와 개발자 블로그 등에 대해 알아보자.
출처 : http://www.imaso.co.kr/?doc=bbs/gnuboard.php&bo_table=article&wr_id=40048