System Compleat.

'Techs'에 해당되는 글 113건

  1. Nonpaged/Paged pool trace, 2nd 1
  2. 시스템 관리자의 실패, 그리고 서비스.
  3. NginX on Ubuntu-9.0.4-server
  4. Sunfreeware, NexentaOS
  5. Nonpaged Pool

Nonpaged/Paged pool trace, 2nd

Techs
( younjin.jeong@gmail.com , 정윤진 )

지난번에 Windows Non Paged Pool 관련 에러를 추적하다가, 끝을 싱겁게 낸 적이 있다.
삽질 하였으나, 추적 실패 ;;  

Non-Paged Pool 관련 에러 추적에 대한 내용은 지난글을 참조 하도록 한다.
 
하지만 최근 불꽃 서핑질을 통하여, simple-talk 의 Ben Lye 씨의 포스팅을 통해 명확한 내용을 알게 되었고, 이를 대충 우리 말로 옮긴 것이 다음의 내용이다.

물론 영어를 더 잘 하시는 분들은, 직접 가셔서 보셔도 된다.  @_@;; 여기.


결과부터 추려 흐름대로 진행 해 보면, 다음과 같다.

----

일반적으로 IIS를 구동하고 있는 웹 서버의 경우, 또는 다른 application server 인 경우와 마찬가지로 non paged pool 에러가 발생하게 되면  시스템은 ICMP Echo ( ping ) 등의 요청에 응답하지만, 실제 페이지를 요청해 보면 페이지 에러, IIS 로그를  살펴 보면 Connection Refused 의 에러가 잔뜩 찍히게 된다.

Non paged pool 에러가 발생했을 경우  시스템 이벤트 로그를 보면, 거의 대부분 event id 2019 ,
"The server was unable to allocate from the system nonpaged pool because the pool was empty"
라는 메세지를 보게 된다.

사용자 삽입 이미지


Non Paged Pool 의 명확한 정의는, 대략 추리면 다음과 같다.
 - 커널에서  Page fault 가 허용되지 않는 상황에서 시스템 드라이버 등의 데이터 저장이 가능해야 하는 메모리 공간 , 즉 커널에서 사용되어 절대로 Paging out 되는 일 없는 영역을 말한다.

이 영역은, Windows 버전 별로 다음과 같은 공간 제약을 가진다.
 - Windows Server 2003 32bit 에서 2기가 이상의 메모리를 가진 시스템은 256MB의 제한.
 - Windows Server 2008 32bit 시스템은 2G 또는 전체 메모리의 75% 의 제한.
 
 - Windows Server 2003 64bit 시스템은 128G 또는 전체 메모리의 45%의 제한.
 - Windows Server 2008 64bit 시스템은 128G 또는 전체 메모리의 75%의 제한.

Pool size 관련 내용은 Mark Russinovich 와 David Solomon씨의 "Windows Internals, 5th Edition"같은 저서 또는 Mark Russinovich 씨의 블로그 를 보면 잘 나와 있다고 한다.


시스템에 다음의 툴을 설치한다.

Debugging Tools for Windows
Process Explorer

Process Explorer 를 실행하고, Options -> Symbol Configuration 을 클릭 후
Dbghelp.dll  파일을 Debugging Tool 이 설치된 디렉토리의 해당 파일로 잡아주고,
Microsoft Symbol Server  를 Symbols path 로 적용한다.

사용자 삽입 이미지


Process Explorer 에서 Ctrl + I 단축키를 누르면 Nonpaged Pool 영역의 확인이 가능하다.

사용자 삽입 이미지


문제가 되는 시스템의 메모리 사용을 주기적으로 모니터링 해 보면, nonpaged pool 영역은
시스템을 재부팅 하기 전까지는 절대 줄어들지 않는 모습을 확인 할 수 있다.  따라서, 이는 커널에서 사용하고 있는 드라이버의 메모리 leak 이며, 가능한 빨리 어떤 드라이버가 문제인지 색출해 내는데 촛점을 맞춰야 한다.  이러한 작업에는 poolmon.exe 와 같은 Memory Pool Monitor 툴이 필요 하며,  이 툴은  Windows Support Tools 에 포함되어 있는 poolmon.exe 를 사용하거나 ( 2003 CD에 포함되어 있음 ) Microsoft Download Center 에서 다운로드가 가능하다.


사용자 삽입 이미지


Poolmon 은 Pool Storage 에 대한 사용량 ( paged & nonpaged ) 과 Pool tag로 분류된 정보를 보여준다.  Pool Tag는 보통 4-Character 로 구성된 문자열이며, 커널 API가 Pool 에 디바이스 드라이버 데이터와 같은 내용을 할당할때 사용 된다.


poolmon.exe 를 실행시키면, 도스시절에 보던 푸르딩딩한 바탕의 하양 글씨에 각종 정보가 나타나 있는데, 여기서 'p' 를 누르면  paged 와 nonpaged pool 을 전환하며 필터링 한다.
'b' 키는 byte 순위에 따른 정렬을, 'd'키는  pool 의 할당 또는 미할당 을 기준으로 필터링 하여 정보를 보여준다.

Nonpaged - Sorted by bytes 설정으로 정렬하면 아래와 같은 내용을 볼 수 있다.

사용자 삽입 이미지

그림을 확인 해 보면, 제일 첫번째 줄에 "ShAp" 가 56 바이트씩 2,187,628 회의 allocation 이 발생했으며 Free가 0 이고 , 이로 인해 122,507,168 바이트의 Non-paged Pool 사용이 발견된다.  이는,  Windows 2003 Server 32bit 기준으로 60%가 넘는 Non paged Pool 영역의 사용이며, 따라서 ShAp Tag를 가지는 드라이버가 leak 의 주범으로 의심 할 수 있다.

kernel API 를 찾았으니, 이제 이 Tag 가 대체 어떤 드라이버인지를 알아 내야 한다.  여기에는 몇가지 방법이 있는데,  처음에 설치한 Debugging Tools for Windows 를 사용해 커널 컴포넌트
나 드라이버를  Debugging tools 디렉토리안에 triage\pooltag.txt  에 Tag 들이 나열 되어 있으므로 찾으면 된다.

만약 tag가 pooltag.txt 파일 안에 없다면, Sysinternal 에서 제공하는 Strings , strings.exe 도구 ( Unix 또는 리눅스 기준으로는, 바이너리 또는 파일 안에 있는 해독 가능한 string 형태의 데이터를 찾아서 표시해 준다. 역자주 ) 를 사용해야 한다.

Tag는 Driver File 안에 명시되어 있으며,  대부분의 윈도우 드라이버들은 %SystemRoot%\System32\drivers 디렉토리에 위치하기 때문에 우리는 strings.exe 를 사용하여 쉽게 드라이버를 찾아 낼 수 있다.

사용자 삽입 이미지

strings * | findstr ShAp  커맨드를 통해, klif.sys 라는 드라이버를 찾아 냈다.


파일을 찾아내게 되면, 우리는 드라이버 제공자를 쉽게 추적 할 수 있으며, 이를 바탕으로 해당 드라이버 제조사에 기술지원의 요청이 가능하다. 

위와 같은 테크닉으로, Event ID 2020으로 발생하는 paged pool 영역에 대한 오류 ( "The server was unable to allocate from the system paged pool because the pool was empty." 도 쉽게 추적 해 낼 수 있다.  차이는 paged 냐 nonpaged 냐의 차이 일 뿐.

정리하면,
 - Paged / Nonpaged 영역 관련 오류인지 시스템 이벤트로그에서 메세지를 확인한다.
 - poolmon.exe 를 사용하여 Driver Tag 를 찾아낸다.
 - pooltag.txt 파일 또는 strings.exe 툴을 사용해 드라이버를 밝혀낸다.
 - 드라이버 제공자에게 연락한다.

위와 같은 방법을 따른다면, 이러한 문제는 더이상 어렵게 느껴지지 않을것이다.

-------
결과부터 말하지만, 결국 검색과 윈도우 pool 영역에 대한 이해의 한계였던 거다.
Ben Lye 씨의 포스팅을 보면서 훅 깨달은 바는, 역시 어느 플랫폼이든 공존하는 툴이 있고 추적의 방법은 이해가 수반된다면 거의 대부분 동일하다는 것이다.

윈도우 커널 관련 서적 보다가 퍼져버려 포기할 뻔 했던 내용에 대해 깔끔하고 명확한 정리를 포스팅 해 주신 Ben Lye 씨에게 심심한 감사를 표한다.


( younjin.jeong@gmail.com , 정윤진 )


시스템 관리자의 실패, 그리고 서비스.

Techs
( 정윤진, bluebird_dba@naver.com )


웹 서비스를 하는 많은 시스템에서, 사업의 성공과 함께 고객이 증가함에 따라 발생하는 많은 문제들이 있다.  보다 많은 고객에게 무정지 서비스를 하기위한 각 서비스 구성 요소의 이중화 부터, 서버의 추가에 따른 네트워크 장치의 추가, 대역폭의 확장 등 비용 들어가는 요소가 한두가지가 아니게 된다.

물론 이런 비용의 문제가 있다면 자연히 저렴하고 성능좋은 오픈소스 솔루션으로 눈을 돌리게 마련인데, 이 오픈소스 솔루션이라는게 그 좋은 성능만큼 손도 많이가고, 기본적으로 설치되는 패키지 들이 감당 해 낼 수 없는 어떤 한계 상황에 이르게 되면 소소한 튜닝 하나에 서비스의 명암이 엇갈리기도 한다.

여기 블로그에 내가 직접 설치해 보고, 또  그 성능을 온몸으로 확인했던 여러가지 툴 및 어플리케이션들이 '당연하게'  '잘' 동작 한다는 믿음에는 변함이 없지만, 이들과 맞물리는 요소에 따라 실패하게 될 수도 있다는 사실을 최근 뼈저리게 깨닫게 되었다.

사용자 삽입 이미지

BOTTLENECK a image from finsolinc.com





문제의 발단은 고객 서비스 규모의 증가에 따라 상거래 사이트의 특징상 수많은 이미지를 서비스하게 되는데, 이 감당하기 힘든 이미지의 규모 때문에 nginx 를 사용한 이미지 분리를 시도 하였는데, 결과는 참패였다.  참패의 원인은 몇가지가 있는데, 그중에서도 가장 주요한 부분이 바로 아파치의 mod_expire 였다.

HTTP 의 헤더를 조작하는 것이 많은 비용이 들어가는 일이라는 것은 평소에도 잘 알고있었지만, 이 헤더의 조작이 NFS 의 getattr() 호출의 빈번함과 함께 아파치의 Sending Reply 를 지연시켜 결국 사용 가능한 모든 소켓을 불태워 버림에 따라 nginx 는 nginx 대로, 아파치는 아파치 대로 부하상황에 사이트가 정상동작 하지 않게 되어버렸다.  스레드 기반에서의 ( mpm이 워커였다. 물론 prefork 도 동일한 설정에 상황은 마찬가지. ) locking 및 pending 의 무서움을 절실히 깨달았달까.

결국 문제는 찾아 내게 되었지만, 그 주범이 mod_expire 라는 사실에 허무하기 그지 없다. 고객의 사용 패턴에 따라 mod_expire 는 득이 될 수도, 실이 될 수도 있다.


아무리 간단한 서비스 구성에도 많은 요소들이 존재한다.  부하가 없을때에는 당연히 동작해 주는 그것들.  하지만 극한 상황이 되면 아주 작은 파라메터 하나, config 하나, sql 문장 하나가 서버를 멈추게 하고, DB를 멈추게 하는 무서운 적이 될 수 있음을 항상 기억해야 한다.

구성에 관한한 어지간해서는 실패한 경험이 별로 없는데, 이번건은 나에게 매우 큰 정신적 충격이었고,  역시 항상 장애에 대해 트레이닝 하지 않으면 당황하게 되는걸 보니 아직 많이 부족하다 싶다.  그렇게 당연한 인과 관계를 찾아내지 못했던게 참 ... 씁쓸하다고만 하기에는 부족한.


결국, 아파치의 체중조절에 들어갔다.  꼭 필요한 모듈만 올려서 경량화, ServerLimit 조절 같은 기본 구성부터  이미지 서버의 이벤트 폴링,  aio 및 sendfile 의 적용 등.

이제, 쓴맛을 볼만큼 봤으니 단맛을 찾아 내야 겠다.
2만 세션을 커버했다면, 이제 빡시게 준비해서 5만 세션 이상은 버티게 해야지.

대역폭을 병목구간으로 만들어 버리는, 그런 구조를 향하여.



( 정윤진,  bluebird_dba@naver.com )

P.S.

1.
nfs 의 마운트 옵션은 기억해 둘 만 하다.  getattr 비율이 40 또는 60% 이상이라면 서버의 로컬 캐시 타임을 늘리는 방법을 강구해 보도록 하자.

nfsstat -c
nfsstat -m


2.
apache2 구동중인 시스템에서 비교적 성능이 출중한 서버인경우에 위와 같은 상황에서
iowait 나 vmstat 에서 특이할 만한 값은 떨어지지 않는다.
server-status 를 적극 사용 하도록 하고, 리눅스라면 ps -eo wchan 을 참고 하도록 하자.

3.
nginx 는 꼬진 서버가 아니다.
다만 nginx 를 꼭 써야한다면, 기존의 웹서버 설정을 매우 디테일하게 살펴야 할 것이다.

NginX on Ubuntu-9.0.4-server

Techs
( 정윤진, bluebird_dba@naver.com )


오늘은, nginx 의 우분투 설치에 대해 한번 전체 과정을 쭈욱 적어 보려 한다.
우분투에서의 설치 과정은 대체로 다음과 같다.

1. OS 설치.
2. 필요 package 설치
3. nginx source download
4. Additional Module download
5. configure / make / make install
6. Setup
7. Run!!

물론,  2 ~ 5번을 건너 뛰고  apt-get install nginx 해도 된다.  ㅋ
어쨌든 우분투 인스톨이 끝나로 root 계정 세팅을 완료 하였다면 필요한 패키지 인스톨을 시작한다.

Package Install

apt-get update
apt-get dist-upgrade
apt-get install build-essential libpthread-stubs0 libpthread-stubs0-dev libgd2-xpm libgd2-xpm-dev libgeoip-dev libgeoip1 sysvinit openssl libssl-dev libpcre3-dev  libgcrypt11-dev


nginx download

NginX 는, 아직 메이저 버전 넘버가 1 이 채 못되었다.  그렇다고 unstable 한 것은 아니지만, 다음의 버전 넘버링을 참고 하도록 한다.

0.6  -> Legacy 버전  ( 통상 apt-get 으로 install 되는 버전. 3rd party 모듈이 잘 설치되며, 안정적으로 동작한다 )

0.7  -> Stable 버전.

0.8  -> Develop 버전  ( 3rd party 모듈은 포기하는게 좋다.  다만, 기존 3rd party 로 제공되던 모듈이 nginx 에 포함되어  --with 옵션으로 설치 되는 모듈이 많아졌다. )

wget http://sysoev.ru/nginx/nginx-0.6.38.tar.gz
바빠서 그런건지, sysoev.ru 사이트가 종종 먹통일 때가 있다.

google 에서 해당 버전의 파일명을 검색하면 서비스 하는 사이트가 많으니 신뢰할 만한 페이지에서 받아서 사용하도록 한다.

openssl 소스 다운로드
nginx 의 compile 시에 openssl 의 소스코드를 요구한다.

wget http://www.openssl.org/source/openssl-0.9.8k.tar.gz
사이즈에 비해 제법 느리니 커피한잔 마셔 준다. ㅋ



additional module download

http://wiki.nginx.org 의 Module 페이지에 가면 기본적으로 nginx 에서 제공하는 모듈 이외에 3rd party 모듈들의 링크를 제공한다.  필요한게 있다면 추가 하도록 한다.

GeoIP Extension
wget http://wiki.nginx.org/images/9/99/Nginx-geoip-0.1.tar.gz

NCache
wget http://ncache.googlecode.com/files/ncache-2.3_release.tar.gz

다른건 잘 안되서 추적하기도 귀찮고 해서 올리지 않았다.
통상 Upload Module 도 많이 사용 하는듯.

다운로드 받은 모듈은 configure 시에 옵션으로 써 주기 편한 디렉토리에 압축을 풀어 놓도록 한다.  난  $SRCDIR/nginx-0.6.38/modules  에 압축을 풀었다.


Configure && make && make install

일반적인 xNix 어플리케이션의 compile 과 비슷하다.

./configure --add-module=./modules/ncache-2.3 --add-module=./modules/nginx-geoip-0.1/  --with-google_perftools_module --with-poll_module --with-http_ssl_module  --with-http_realip_module  --with-http_gzip_static_module  --with-http_stub_status_module --prefix=/opt/nginx --with-openssl=/usr/src/binaries/openssl-0.9.8k

더 필요한게 있다면 붙여도 된다.

위의 apt-get install 만으로는 빠져있는 것들이 있을 것이다.  configure 과정에서 뭔가 누락된게 있다고 징징대면  apt-cache search 다음에 apt-get 으로 인스톨 해 주면 된다.

configure 가 끝나면 make , make install

configure 는 이상없이 끝났는데,  make 과정에서 error 를 토해내면서 중지하면,  error 부분을 조치해 주고 다시 make 를 시도한다.  통상 openssl 소스를 추가적으로 --with 옵션에 넣어준 경우,  make clean 시에 rm -f 로 디렉토리를 지우려는 멍청한 짓을 가끔 해서 make 파일을 수정하는 세련된 짓은 하지 않고, 그냥 rm -fR ../openssl-0.9.8k 해서 지웠다.
당연히, 지운다음에 다시 압축을 풀어줘야지.


nginx.conf &&  RUN!!!!

 정상적으로 설치가 완료 되었다면,  --prefix 로 지정한 디렉토리에 nginx 가 이쁘게 컴파일되어 설치된 모습을 볼 수 있다.  실행 바이너리는 ./sbin 에 , conf 는 ./conf 디렉토리 안에 있다.

nginx.conf 에서는, 다음의 몇가지가 기본적인 설정이다.  뭐 wiki 참조하시면 엄청 잘 나와있으므로, 모자란 부분은 거기서 추가 하시도록 한다.

몇몇 주요한 conf 는,

worker_process
sendfile

upstream  httpservice {
    ip_hash;
    server x.x.x.x:80;
}

location / {
      set $memcached_key $uri;
      memcached_pass     x.x.x.x:11211;
      ....
      ..
      Default nginx.conf 참조
}

rewrite 및 기타 virtual host 설정등도 함께 제공하므로, wiki.nginx.org 에서 참조 하도록 한다.

nginx 를 구동하기 위해서는, 적절한 계정이 있어야 한다.
groupadd -g 81 apache
useradd -g 81 apache

난 apache 로 돌렸다.  ( 사실 이건 예전에 AJ 가 쓰던거지만. )


어쨌든, 다 설정 되었으면 구동한다.

./sbin/nginx  ( & 안해도 된다  알아서 한다 )

지정한 process 만큼 떠 있는 모습이 확인 가능하다.



음.. 뭐 이런 매뉴얼 스러운 글은 원래 잘 쓰지 않는 편이지만,  나도 돌머리라 자주 잃어버려서 정리 겸 해서 쓴다.  뭐 사실 잃어버려도 다시 삽질 하면 되지만, 점점 삽질 하는 시간이 웬지 아까워 진다고 할까나...


그냥 wiki.nginx.org 를 번역하는게 나을지도..  그러고 보니 한글 페이지를 봤던것 같은 기억도;;;  varnish 가 더 희소성이 높으려나.. ㅋㅋㅋ


( 정윤진, bluebird_dba@naver.com )



Sunfreeware, NexentaOS

Techs
( 정윤진, bluebird_dba@naver.com )

친구네 시스템이 SunOS 5.9 로 되어있어서 간혹 장애가 나면 지원겸 해서 보아주는 경우가 있는데, 아무리 솔라리스라고 해도 리눅스의 유용한 툴들이 가끔 그리워 지게 마련이다.
더군다나 솔라리스에 오픈 소스의 솔루션을 설치할라 치면, automake 나 gcc 같은 툴들이 몸서리 쳐지게 필요해 지는데, 이때 유용한 것이 제목과 같은 Sunfreeware 다.

sunfreeware 에는 리눅스 세상에서 유용했던 또는 필수적인 여러가지 오픈소스들을 지원하는데, 다운로드 및 설치가 간단해서 많은 이들이 사용하고 있는것으로 안다.

가장 대표적인 예가 아파치, php 와 같은 범 unix 솔루션들을 그냥 바이너리/패키지 형태로 받아 쓰기에는 문제가 있는 경우가 많아서, 해당 시스템에서 직접 컴파일 해서 사용하거나 또는 일반 리눅스 머신에서 크로스 컴파일하여 타겟 시스템에 올리거나, 어쨌든 컴파일 해서 각종 튜닝을 시도해야 하는 것이 맞기 때문에 sunfreeware 에서 제공하는 여러 패키지를 반드시 설치해야 한다.


패키지를 구하는 방법은 간단해서, sunfreeware.com 에 접근하여 원하는 패키지를 다운로드 받으면 된다.

ftp ftp.sunfreeware.com 에 anonymous 로 접근
pub/freeware
원하는 패키지 다운로드!

압축 대강 해제해 주고
pkg-add -d [$PKGFILE]

좌르륵 설치 된다.


이와 같은 상용유닉스에서는 일반 리눅스에서는 별로 신경쓰지 않았던 여러 어플리케이션 별 튜닝 차이점에 대해 잘 살펴 보아야 한다.
잘 알려진 apache2.x 버전의 솔라리스 구동에는 많은 옵션들이 있으며, 이 솔라리스라 하더라도 SPARC 인지 아니면 다른 프로세서인지에 따라 시스템적 튜닝 요소들이 존재한다.

말이 좋아 튜닝이지, 사용자가 많아지는 환경이 되면 스왑을 잔뜩 잡수셔서 뻗거나, pthread 관련 문제로 인해 아파치가 다이 하시는등 그거 꽤 번잡스럽지만 신경써 주지 않으면 서비스 자체가 불가능 한 경우도 많으니 이기종 플랫폼에서 유의하는 것은 뭐 당연하달까.

자세한 정보는 여기서.
http://www.sunfreeware.com/


한가지 더,  세상이 좋아져서 opensolaris.org 라는게 생겼다.
opensolaris 자체를 사용해 보는 것도 좋지만, NexentaOS 라는거를 시스템 하면 꼭 한번쯤은 써보는게 좋지 않나 하는 생각이다.

왜?

이 NexentaOS 는 솔라리스 커널 기반에 Debian ( 또는 Ubuntu ) 식의 APT 를 사용한 패키지 관리 툴이 포함된 멋진놈이라는 거다.
리눅스 진영에서 솔라리스에 항상 군침 흘리는것이 바로 이  ZFS 인데, 세상에 현존하는 파일시스템 가운데 군계일학 같은 이놈을 우분투와 같이 아트한 패키징 시스템과 함께 리눅스처럼 편하게 사용 할 수 있다는것은 축복인거다.  게다가 지원하는 패키지도 13000개 이상이라는 홈페이지의 소개만큼이나 여러 툴을 쉽게 사용할 수 있다.

뭐, sunfreeware 만 쓰기엔 좀 거시기 해서 NexentaOS 도 곁다리로 소개하긴 하지만,
적어도 뭔가 공유 스토리지가 필요한 시스템 군을 구성하는데 있어서 성능적 측면에서는
이 NexentaOS 를 백단의 NFS 메인으로 두고 프론트 군 구성에 적절한 웹서버들을 포진하는 것은 대단히 매력적인 방법이 아닌가 싶다.


오늘은 원래 nginx.conf 에 대해서 대강 설명을 해볼까 했는데, 피곤하기도 하고 해서 그건 다음번 포스팅에 하기로 하고,  Nexenta에 대해서도 시간을 내어 한번 퍼포먼스 테스트를 해 봤으면 좋겠다. 


nexentaos 는 다음의 링크들에서 구하실 수 있겠다.

http://www.nexenta.org/os
http://www.opensolaris.org/os/downloads/


( 정윤진, bluebird_dba@naver.com )

Nonpaged Pool

Techs
( 정윤진, bluebird_dba@naver.com )

---------
시작하기 전에, 본 내용은 2010/03/18일에 포스팅한 내용을 보는것이 Nonpaged 및 Paged Pool 영역에 대한 추적에 용이함을 미리 말씀 드린다.

해당 내용은 여기 를 참조 하시면 되며, 아래의 내용은 경험담 정도로 보아주시면 좋겠다.
---------


일전에 윈도우 서버에서 nonpaged pool 영역에 문제가 생기면서 추적을 하다 하다가 포기한 적이 있다.  그 당시의 장애는 프로그램의 코드 문제로 나중에 밝혀 졌지만  이러한 유형의 장애 추적이 윈도우에서는 매우 어렵다 라고 느꼈던 개인적으로는 큰 사건중의 하나였다.

나의 경우에는 장애 상황에 장애 해결을 위한 실마리를 찾지 못하면 빠르게 원복하는게 항상 답이라고 생각한다.  이 원복의 의미에는, 최근에 변경한 ( 업데이트한 ) 서비스의 구성요소 일 수도 있고 일부 정말 모르겠는 경우 메모리의 문제가 발생하면 재부팅을 하거나 하는 것.

다만, 장애 상황에서 단 하나의 연관 가능성 있는 실마리라도 발견하면 추적하게 되는데, 적당한 시간만 있다면 이러한 잠깐의 추적이 완전한 문제 해결로의 지름길이 되곤한다.
따라서 장애 발생 시간에 ( 서비스에 문제가 되고 있는 시간에 ) 빨리 원복을 할지 이 장애의 원인을 추적할 지는 숱한 번민의 대상이 되고,  당황하거나 이런 부분을 조금이라도 소흘히 하게 되면 서비스 재개는 늦어지고, 장애 원인은 찾지 못해 매번 동일한 장애를 맞이하게 되는 슬픈 현실에 빠지게 될 수도 있다.

서론이 길었지만,  뭐 어쨌든 이번 이야기는 IIS를 동작시키는 윈도우 서버에서의 Non paged pool 의 부족  상황에 대해 어떠한 드라이버가 문제가 되는지를 추적하는 방법에 대해서다. 


윈도우 2003에서는 ( 다른 버전의 윈도 서버에서도 비슷한 방법을 제공하리라 생각한다 ) Windows Support Tools 에서  poolmon.exe 라는 툴을 제공한다.
일단 이 툴을 시스템에 미리 설치 해 두고, 정상 동작 상황에서도 한번 쯤 사용법을 익히는 것도 좋은 공부가 될 것으로 생각한다. ( 윈도 커널에 대한 )
조금 더 개발쪽으로 치우친 시스템 엔지니어라면, windbg.exe 같은 툴을 병행해서 사용하면 더 좋을 듯 싶다.


일단, IIS 구동중인 서버에서 Non-paged pool 영역의 메모리 부족사태가 발생하면 다음과 같은 IIS Error 로그가 발생하게 된다.

2009-xx-xx 02:06:22 - - - - - - - - - 1_Connections_Refused -
2009-xx-xx 02:06:32 - - - - - - - - - 1_Connections_Refused -
2009-xx-xx 02:07:37 - - - - - - - - - 1_Connections_Refused -
2009-xx-xx 02:11:02 - - - - - - - - - 2_Connections_Refused -

당연히 정상적인 서비스가 되고 있지 않은 상황이다.

윈도우 서버의 non-paged pool 은 다들 잘 아시다 시피 커널의 메모리 영역이며, 통상 윈도우에서는 최대 256M 의 메모리를 이 영역에 할당한다.  문제는, IIS 의 http.sys 가 이 영역에서 동작하기 때문에 시스템의 다른 드라이버 또는 커널 메모리 영역에서 동작하는 '그 무언가'가 메모리를 많이 잡수시면 정상적인 IIS 의 동작을 방해한다는데 있다.

유닉스 시스템을 기반으로 유추해 보건데, 이는 IIS 에서 응답 처리를 하기 위해 새로운 thread 의 할당 및 클라이언트 응답에 대한 정상적인 프로세스를 진행하는데 있어 할당 되어야할  커널 메모리 영역이 부족하기 때문에 '난 지금 처리 불가' 라는 메세지를 토해 내는 것 쯤으로 이해한다.

문제는, '그래서 어떤 드라이버인데?'  를 알아야 이 문제가 풀릴 테지만, 이게 쉽지 않다.

poolmon.exe 를 사용하면,  paged pool 과 non-paged pool 에 대한 정보를 알 수 있다.
이 정보에 나타나는 드라이버의 이름은 아래의 스크린샷에서 처럼 당최 뭔 드라이버인지 그 이름을 유추해 내기 힘든 ( 또는 명명규칙을 내가 모르니까 ) 구조로 되어있어, poolmon 자체에서 일종의 translate 를 제공하기도 한다.  ( poolmon.exe -C 하면 .txt 를 뱉어낸다.  )

사용자 삽입 이미지

poolmon.exe



그런데, 이 정보에도 나타나지 않거나 또는 이 정보로도 어떤 드라이버인지 알아낼 수 있는 여지가 많지 않다는게 참 큰일이다.  분명히 시스템에서는 이러한 이름으로 할당된 정보가 어디엔가에서는 참조되고 있을터인데, 각 영역의 Addressing 번지 수 라도 알면 어떻게 좀 해보겠는데  이 non-paged pool table(?) 비슷한 정보를 찾아 내는데 나는 결국 실패했다.

IIS 에서 구동하는 프로세스 자체가 문제인가? 라는 증거만 나와도 그 다음은 참 쉬웠을 텐데.

iisdiag.msi 를 사용하여 IIS 프로세스에 대한 덤프를 떠서 MS 에서 제공하는 Analyze 툴을 써도 신뢰할 만한 정보는 딱 부러지게 나오는게 없었던 기억이다.

결국, 윈도 시스템에 대한 이해 부족이 문제여서 'Windows 커널의 구조와 원리' 에 대한 책을 구입해서 파 보고 있는 중이다.


non-paged pool 영역이 꽉 차면, IIS 재시작은 답이 아니다.  서버 재부팅으로 아예 비워야 한다.  .NET 의 GC 동작도 의심해 보고 perfmon 으로 GC의 Level 별 카운트 증가에 대해 파 보기도 했지만, 결국 원하는 답은 나오지 않아  주기적으로 서버를 재부팅 해야 했던 아픈 기억이 있다.  이런 경우, 커널 덤프를 MS에 보내면 뭔가 답을 알려 주려나?


어쨌든, 좀 지난 일이긴 하지만 이러한 문제는 언제든 재발 될 수 있고, 또 어떤 서비스를 구성하건간에 사전에 신경쓰지는 않아도 발생했을때 한가지 더의 실마리를 알아내기 위해 평소에 이것 저것 많이 봐야 하는 직업임에는 분명한 듯.


결국은 또 신세타령 -ㅁ-;;


( 정윤진, bluebird_dba@naver.com )