[웹서버] 고성능 웹 사이트 설계 기법
성능과 고가용성은 많은 수의 요청을 받는 웹 사이트에서는 매우 중요하다. 이 글은
인기있는 사이트에서 성능과 가용성을 높일 수 있는 몇가지 기법 – 여분의 하드웨어,
로드 밸런싱, 웹 서버 가속, 동적 데이타의 효율적인 관리 – 들을 소개한다. 우리가
이들 중 몇 가지를 1998년 나가노 동계 올림픽 공식 홈페이지 – 지금까지 가장 유명한
사이트 중의 하나인- 에서 어떻께 사용했는지 설명할 것이다. 실제로 기네스북은 이
사이트가 두 개의 기록을 세웠다고 인정했다.
* 사상 최고의 가장 인기있는 인터넷 이벤트 – 공식적으로 감사된 수치는 올림픽
게임 16일동안 6억 3천4백만 요청.
* 1분동안 가장 많은 히트를 기록한 인터넷 사이트 – 공식적으로 감사된 수치는 여자
자유종목 피겨스케이팅 경기중의 1분동안 110,414히트를 기록.
사이트의 규모, 많은 요청, 데이타의 용량 등이 성능과 고가용성을 중요한 설계
문제로 만들었다. 이 사이트의 구조는 1996년 하계 올림픽 경기 웹 사이트를 설계하고
구현한 경험에서 출발하였다. 이 글에서는 먼저 인기있는 웹 사이트에서 성능과
가용성을 높이기 위해 사용될 수 있는 일반적인 기법들을 설명한다. 다음으로 이들
중의 몇 가지 기법이 나가노의 공식 웹 사이트에서 어떻게 구현되었는지 설명한다.
1. 여러 웹 서버로의 라우팅
엄청나게 많은 트래픽 부하를 처리하기 위해서 웹 사이트는 서로 다른 여러
컴퓨터에서 동작하는 여러 서버를 사용한다. 서버들은 공유 화일 시스템을 사용하여
정보를 공유할 수 있다. 예를 들어 앤드류 화일 시스템 (AFS), 분산 화일 시스템
(DFS) 등이 있다. 또는 공유 데이타 베이스를 사용한다; 그렇지 않고, 데이타는
서버들에 복제될 수도 있다.
(1) RR-DNS
라운드 로빈 도메인 네임 서버(RR-DNS) 방법; NCSA가 서버에 사용하는 이 방법은, 여러
서버에 요청을 분산시키는 방법의 하나이다. RR-DNS는 하나의 도메인 이름이 여러 IP
주소에 대응되도록 한다. 그리고 각 IP 주소는 서로 다른 웹 서버에 대응한다.
사용자가 보낸 (서버의) 도메인 이름을 명시한 요청은 라운드-로빈 형태로 대응된다.
(차례로 돌아가면서 대응), 그러나 RR-DNS에서 몇 가지 문제가 발생한다.
1) 서버측 캐싱 ; 네임 서버에서의 이름-to-IP주소 캐싱은 부하 불균형을 발생시킬 수
있다. 일반적으로, 이름-to-IP주소의 대응의 처리 결과를 클라이언트와 RR-DNS 사이의
여러 네임 서버들이 캐싱한다. 다른 IP주소를 갖는 서버에 대응시키려면, RR-DNS는
time-to-live(TTL, 생존시간)를 도메인 이름에 주어서, 지정된 TTL이 지난 다음의
요청은 로컬 네임 서버에서 처리할 수 없게 한다. 그러면 그들은 다시 공식 RR-DNS에
요청되어 다른 HTTP 서버의 IP 주소에 대응된다. TTL 기한 내에 발생한 네임 요청은
같은 HTTPD 서버에 대응된다.
작은 TTL 값은 도메인 네임 처리를 위해 네트워크 트래픽을 심각하게 증가시키기
때문에, 네임 서버들은 종종 RR-DNS가 제공한 매우 작은 TTL을 무시하고, 대신 그들의 최소
TTL을 부여한다. 따라서 중간의 네임 서버들로 하여금 네임-to-IP주소 대응의 처리
결과를 캐싱하는 것을 막을 방법이 없다 – 심지어 작은 TTL값을 사용하더라도. 같은
ISP를 사용하는 많은 클라이언트들은 같은 네임 서버를 공유하는 경우가 많고, 따라서
하나의 특정 웹 서버로 몰리게 된다. (역주:즉 데이콤을 사용하는 사용자들이 모두
하나의 서버로만 몰리게 된다)
2) 클라이언트측 캐싱; 이름-to-IP주소 대응의 처리 결과의 클라이언트측 캐싱도 부하
불균형을 발생시킬 수 있다. HTTP 서버의 부하는 제어될 수 없으며, 클라이언트의
액세스 패턴에 따라서 달라진다. 더군다나, 각 웹 페이지들은 일반적으로 텍스트와
이미지를 포함한 여러 오브젝트들로 구성되어 있기 때문에, 클라이언트는 한꺼번에
여러개의 요청을 동시에 보낸다. 한꺼번에 보낸 여러 요청은 하나의 서버 노드로
보내지고, 불균형을 증가시킨다. 이런 효과들이 심각한 불균형을 야기하고,
클러스터로 하여금 최대 부하를 처리하기 위해서는 훨씬 낮은 평균부하에서
동작하도록 한다.
RR-DNS의 또다른 문제는 라운드 로빈 기법이 좋은 로드 밸런싱을 제공하기 위해서는
너무 단순하다는 것이다. 우리는 각 서버의 부하와 같은 요소들을 반드시 고려해야
한다. 예를 들어, 한 서버 노드에서 여러 데이타베이스 접근을 통해 생성되는 동적
데이타의 요청은 특정 웹 서버를 과부하되게 만들 수 있다.
3) 노드 고장; 마지막으로 클라이언트와 이름-to-IP주소 대응의 처리가 된 네임 서버
캐싱은 웹 서버 노드의 고장에 대처하는 것을 어렵게 만든다. 클라이언트와
네임 서버는 고장을 알지 못하기 때문에, 그들은 계속 고장난 웹 서버로 요청을
보낸다. 비슷하게, 온라인 관리를 위해서도 클러스터의 특정 웹 서버 노드를 정지시킬
필요가 있다. 역시, 개별 노드의 IP 주소를 클라이언트와 네임 서버에 제공하는 것이
이 상황을 어렵게 만든다. 백업 서버를 설정하고, 웹서버 노드의 고장을 인식하면
해당 IP 주소를 넘겨받도록 할 수도 있는데, 이런 방법도 관리하기 어렵다. 또한
능동 백업 노드(평소에도 일을 하는)의 경우 일차 노드의 고장이 발생하면 두 배의
부하가 걸리게 된다.
(2) TCP 라우팅
그림1은 (IP 수준의 표준 라우팅이 아니라) TCP 수준에서의 라우팅에 기반한 로드
밸런싱 기법을 나타낸다. 클러스터의 한 노드는 TCP 라우터라고 불리는데,
클라이언트의 요구를 라운드 로빈 또는 다른 방법을 사용해서 클러스터 내의 웹 서버
노드로 전송한다. 라우터의 도메인 이름과 IP 주소는 외부에 공개되어 있고,
클러스터의 다른 노드들은 클라이언트에서는 보이지 않는다. (만약 둘 이상의 TCP
라우터 노드가 있는 경우, RR-DNS가 하나의 도메인 이름을 여러 TCP 라우터로
대응시킨다) 클라이언트는 요청을 TCP 라우터 노드로 보내고, 이 TCP 라우터 노드는 특정 TCP
연결에 속한 모든 패킷을 서버 노드들 중의 하나로 보낸다. TCP 라우터는 어느 노드로
라우팅 할 것인지 결정하기 위해 부하에 기반한 다른 알고리즘을 사용할 수도 있고,
부하에 기반한 알고리즘보다 성능이 떨어지는 라운드-로빈 방법을 사용할 수도 있다.
서버 노드는 TCP 라우터를 건너뛰고 클라이언트에 직접 응답한다. 요구 패킷은 응답
패킷에 비하면 작기 때문에, TCP 라우터에는 작은 부하만 걸린다.
TCP 라우터 스킴은 DNS 기반 솔루션보다 좋은 로드 밸런싱을 제공하고, 클라이언트나
네임 서버의 캐싱 문제를 피할 수 있다. 라우터는 개별 서버 노드의 부하를 고려한
더 좋은 로드 밸런싱 알고리즘을 사용할 수도 있다. TCP 라우터는 웹 서버 노드의
고장을 인식하여 사용자의 요청을 사용 가능한 웹 서버 노드로만 전송할 수 있다.
시스템 관리자는 TCP 라우터의 설정을 변경하여 웹 서버 노드를 추가, 삭제할 수
있고, 이를 통해 웹 서버 클러스터를 관리할 수 있다. 백업 TCP 라우터를 설정하여,
TCP 라우터 노드의 고장을 처리할 수 있고, 백업 라우터는 정상 동작시에는 웹 서버로
동작할 수 있다. 1차 TCP 라우터의 고장을 인식하면, 백업 라우터는 클라이언트의
요청을 자신을 제외한 남아있는 웹 서버 노드로 전송한다.
1) 상용 TCP 라우터; 많은 상용 TCP 라우터들이 있다. 예를 들어 IBM의 네트워크
디스패처(ND)는 여러 운영체제에서 동작한다. 유닉스, 썬 솔라리스, 윈도우 NT,
임베디드 OS 등이다.
임베디드 OS는 범용 OS의 TCP 통신 스택을 최적화하고 스케줄러와 인터럽트 처리
오버헤드를 제거하여 라우터 성능을 개선한다. ND는 단일 프로세서 기계에서
동작하는 임베디드 OS에서 초당 10,000 HTTP 요청을 처리할수 있으며, 이것은
대부분의 웹 사이트가 처리할 수 있는 것보다 높은 요청 속도이다.
다른 상용의 TCP 라우터는 Radware의 Web Server Director
(http://www.radware.co.il), Resonate의 Central Dispatch
(http://www.resonamte.com/products/central_dispatch/data_sheets.html) 등이다.
Cisco Systems의 LocalDirector
(http://www.cisco.com/warp/public/cc/cisco/mkt/scale/locald/)는 TCP 라우터
접근방법과 다른데, 서버에서 돌아오는 패킷도 LocalDirector를 거쳐서 클라이언트로
돌아가기 때문이다. 여러 로드 밸런싱 접근방법들의 비교에 대해서는 Cardellini,
Colajanni, and Yu의 논문을 참조.
2) TCP 라우팅과 RR-DNS의 결합 ; 단일 TCP 라우터가 병목이 되지 않은 상태에서
요청을 라우팅하기에 충분하지 않으면, TCP 라우터와 DNS 스킴을 여러가지 방법으로
결합할 수 있다. 예를 들어, RR-DNS 기법을 하나의 IP 주소를 여러 라우터 노드로
대응시키기 위해 사용될 수 있다. 이 하이브리드 기법은 RR-DNS에 의해 발생하는
로드 불균형을 해결할 수 있는데, 응답하는 라우터가 RR-DNS에 의해서 대응된 무더기의
요청을 여러 서버들로 분산시킬 수 있기 때문이다. 또한 확장성도 좋은데, 큰 TTL
값으로 인해 RR-DNS를 실행하는 노드는 병목이 되지 않고, 여러 라우터 노드를
한꺼번에 지원할 수 있기 때문이다.
3) 특별한 요구사항; TCP 라우팅의 한가지 문제는 단일 클라이언트에서의 요청을 여러
웹 서버 노드들에 분산시킨다는 문제이다. 이것이 좋은 로드 밸런싱을 제공하지만,
몇가지 응용의 경우 요청들이 하나의 서버로 라우팅될 필요가 있다. 이런 응용을
지원하기 위해, ND는 특정 서버를 우선적으로 선택하는 라우팅을 제공한다. 예를 들어
Secure Sockets Layer(SSL)로 암호화된 요청의 경우 유효하다. 이 SSL은 클라이언트와 서버 사이에
통과되는 정보를 암호화하기 위한 세션 키를 생성하는데 세션 키는 생성 비용이 크다.
따라서 매번의 SSL 요청마다 키를 다시 생성하지 않도록, 100초 정도의 수명을
갖는다. 클라이언트와 서버가 세션 키를 정한 다음, 특정 클라이언트와 서버 사이의
요청은 그 수명동안 같은 세션 키를 사용한다.
그러나, 여러 웹 서버로 구성된 시스템의 경우, 한 서버는 다른 서버가 생성한 세션
키를 알 수 없다. 라운드 로빈과 같은 간단한 로드 밸런싱 알고리즘이 사용될 경우
같은 클라이언트의 여러 SSL 요청은 한 세션 키의 수명동안 여러 서버로 전송될
것이다. ND는 같은 클라이언트에서 전송된 여러 SSL 요청을 100초 동안은 한 개의
서버로 전송함으로써 이 문제를 해결한다.
2. 웹 서버 가속기
하나의 요청을 처리하면서, 웹 서버는 소프트웨어의 계층사이에서 여러번 데이타를
복사한다. 예를 들어 화일 시스템에서 응용으로, 응용에서 OS 커널로, 전송 과정에서
복사하며, 또한 디바이스 드라이버 수준에서 복사할 수도 있다. OS 스케줄러, 인터럽트
처리 등의 다른 오버헤드들도 비효율을 증가시킨다. 웹 사이트 성능을 개선하기 위한
기법으로, 사이트의 데이타를 캐싱하여 자주 요청되는 페이지를 웹 서버에서보다 훨씬
적은 오버헤드로 처리할 수 있다. 이런 캐시를 HTTP 가속기나 웹 서버 가속기라고
부른다.
(1) 우리의 가속기
우리는 웹 서버 가속기를 개발했는데, 임베디드 OS에서 동작하고 단일 CPU 200-MHz
PowerPC에서 초당 5,000페이지를 캐시에서 처리한다. 이 성능은 전형적인 고성능 웹
서버를 유사한 하드웨어, 일반 OS에서 실행한 것보다 10배 이상 빠른 것이다.
Harvest와 Squid(http://squid.nlanr.net/Squid/) 캐시도 HTTP 데몬(HTTPD) 가속기를
포함하지만, 우리의 것이 이들보다 좋은 성능을 보인다. Novell도 BorderManager의
일부로 HTTPD 가속기를 팔고 있다.
우리 시스템의 뛰어난 성능은 대부분 임베디드 OS 덕분이다. 특히 버퍼 복사를
최소한으로 하였다. 제한된 기능 때문에, OS는 범용 소프트웨어 응용, 즉
데이타베이스나 OLTP 에는 적합하지 않다. 그러나, 최적화된 통신 지원은 웹 서버
가속과 같은 특별한 네트워크 응용에는 잘 적용될 수 있다.
우리의 가속기와 다른 것의 주된 차이는 우리의 API는 응용 개발자가 명시적으로,
캐시된 데이타를 추가, 삭제, 수정할 수 있도록 한다. 따라서 히트율을 최대화하고,
현재의 캐시를 유지한다. 우리는 정적 웹 페이지 뿐만 아니라 동적 웹 페이지도
캐싱하는데, 해당 페이지의 캐시가 무의미하면 응용이 명시적으로 이것을 무효화할 수
있기 때문이다. 동적 웹 페이지의 캐싱은 동적인 내용의 비중이 큰 웹 사이트의 성능
향상에 중요하다. 우리는 동적 페이지의 캐싱을 허용하는 다른 가속기는 없는 것으로
알고 있다.
그림 2가 보여 주듯이, 가속기는 여러 웹 서버 노드의 앞에 위치한다. TCP 라우터는
가속기와 같은 노드에서 동작한다.(독립된 노드에서 동작할 수도 있다) 요청된
페이지가 캐시에 있으면, 가속기는 페이지를 클라이언트에 돌려준다. 그렇지 않으면
TCP 라우터가 웹 서버 노드를 선택하고, 요청을 그 노드로 전송한다. 지속성 TCP
연결이 캐시와 웹 서버 노드 사이에 유지될 수 있으며, 이로써 캐시 미스를 서버
노드에서 처리하는 부하를 감소시킬 수 있다. 우리의 가속기는 많은 요청을 캐시에서
처리함으로써(윔블던 사이트의 경우 93%) 한 사이트에서 필요한 웹 서버의 수를
감소시킬 수 있었다.
가속기가 각 요청을 검사하여 그 요청을 캐시에서 처리할 수 있는지 판단하기
때문에, 가속기는 클라이언트와의 연결을 반드시 종료해야 한다. 캐시 미스의 경우,
가속기는 클라이언트가 요청한 정보를 서버에 요청하여 받아서 클라이언트에
돌려준다. 미스의 경우, 캐싱은 그림1의 TCP 라우터에 비해 약간의 부하를
증가시키는데, 가속기가 클라이언트에 대해 프락시로 동작하기 때문이다. 그러나
지속성 TCP 연결을 캐시와 서버 사이에 사용함으로써, 이 부하를 크게 줄일 수 있다.
사실 서버의 부하는 서버가 클라이언트의 요청을 직접 처리하는 것보다 작다.
캐시는 두 모드 중의 하나로 동작한다; 투명 또는 동적 모드이다. 투명 모드에서는
데이타는 캐시 미스가 발생한 다음 자동적으로 캐시된다. 웹 마스터는 캐시 정책
파라미터를 설정하여 어떤 URL이 자동으로 캐시될지 결정할 수 있다. 예를 들어 각
파라미터들은 스태틱 이미지 화일, 스태틱 비이미지 화일, 동적 화일 등을
캐시할 것인지, 그리고 그들의 기본 수명은 얼마인지를 나타낼 수 있다. 서버의
응답에 포함된 HTTP 헤더는 캐시 정책 파라미터에 따라 결정된 특정 URL의 기본
동작보다 우선한다. 동적 모드에서 캐시 내용은 웹 서버 가속기나 원격 노드에서
실행되는 응용에 의해 명시적으로 관리된다. API의 함수들은 프로그램이 URL 내용의
수명을 캐시, 무효화, 질문, 설정할 수 있도록 한다. 동적 모드가 응용 프로그래머의
작업을 복잡하게 하지만, 이것은 성능 최적화를 위해 필요하다. 동적 모드는 특히
인기있는 오브젝트를 캐시에 프리패치하거나, 캐시된 시점에 수명을 알 수 없는
오브젝트를 무효화하는데 유용하다.
(2) 성능
오브젝트를 디스크에 캐싱하는 것은 가속기의 성능을 많이 떨어뜨리기 때문에, 모든
캐시된 데이타는 메모리에 저장된다. 따라서 캐시 크기는 메모리 크기에 의해
제한된다. 우리의 가속기는 캐시 치환을 위해 가장 오래된 것을 버리는(LRU, least
recently used) 알고리즘을 사용한다. 그림 3은 요청된 오브젝트의 크기에 따라
하나의 가속기가 처리할 수 있는 성능을 보여준다. 우리의 테스트 시스템은 2,048
바이트 이상의 요청된 오브젝트에 대해서는 가속기가 최대의 성능을 내도록 하는데
충분한 네트워크 대역폭을 제공하지 못한다. 그래프는 우리가 실제로 측정한 값과,
네트워크 성능이 병목이 아닌 경우 예상되는 수치들을 같이 보여준다. 우리의
가속기의 성능의 자세한 분석과, 그림 3의 예상을 얻은 방법은 Levy et al.에서 얻을
수 있다.
우리의 가속기는 초당 5,000 캐시 히트, 2,000 캐시 미스를 8Kbyte 페이지의 경우
얻을 수 있다. 이 때 가속기와 후위 서버간에 지속성 연결은 사용되지 않았다. 캐시
미스의 경우 가속기는 정보를 후위 서버에 요청하고 이를 받은 다음 클라이언트에
돌려준다. 서버에 정보를 요청하는 것은 캐시에서 오브젝트를 가져오는 것에 비해
매우 많은 명령을 사용한다. 따라서 캐시 미스 성능은 가속기와 후위 서버 사이에
지속 연결을 사용함으로써 향상될 수 있다.
3. 효율적인 동적 데이타 서빙
고성능 단일 프로세서 웹 서버는 전형적으로 초당 수백개의 정적 화일을 처리한다.
그러나 동적 페이지는 10배 이상 느린 속도로 느리게 처리된다. 프로그램이 하나의
동적 페이지를 생성하기 위해 CPU 시간을 1초 이상 사용하는 경우도 드물지 않다.
동적 페이지의 비율이 높은 웹 사이트의 경우, 주로 생성에 필요한 CPU 시간이 병목인
경우가 많다.
동적 페이지는 자주 변경되는 데이타를 제공하는 사이트에는 필수적이다. 예를 들어
1998년 US 오픈 테니스 토너먼트의 공식 웹 사이트는 평균 초당 4개의 변경된 페이지를
경기 기간동안 보여주었다. 동적으로 페이지를 생성하는 서버 프로그램은 가장
최근 버전의 데이타를 보여줄 수 있지만, 만약 데이타가 화일에 저장되어 있고 화일
시스템에서 서비스되면, 그들을 최신의 것으로 유지하는 것은 쉽지 않다. 특히 여러
화일들이 자주 변경되는 경우는 더욱 그러하다.
(1) DUP를 사용한 캐시 관리
동적인 데이타에 대해 성능을 높이는 가장 중요한 기법중의 하나는 그들이 처음 생성될 때 바로
캐싱하는 것이다. 존재하는 동적 페이지에 대한 이후의 요청은 같은 페이지를
생성하기 위해 프로그램을 반복하여 실행하는 것이 아니라, 캐시에서 읽어서
돌려준다. 이 기법에서 중요한 문제는 어느 페이지를 캐싱할 것인지, 언제 이들이
불필요해지는지 결정하는 것이다. 다시, API 함수의 호출에 의한 명시적인 캐시
관리가 성능을 최적화하고 일관성을 보장하는데 필수적이다.
우리는 데이타 변경 전파(Data Update Propagation, DUP)라는 알고리즘을 새로
만들었다. 어느 캐시된 페이지가 새로운 정보에 의해 불필요하게 되었는지 정확하게
파악하기 위해. DUP는 캐시된 웹 페이지가 하부의 데이타의 변화에 따라 영향받는지
결정한다. 예를 들어 만약 몇 개의 캐시된 페이지가 하나의 데이타베이스에 속한
테이블에서 생성된다면, 캐시는 데이타베이스와 동기화하여 페이지가 잘못된
데이타를 가지고 있지 않도록 해야 한다. 더 나아가 캐시된 페이지는 데이타베이스의
특정 부분과 최대한 정확히 대응되어야 한다. 그렇지 않으면 데이타베이스 변경
이후, 값이 변경되지 않아서 불필요한 오브젝트들도 캐시에서 무효화되든지,
수정된다. 이런 불필요한 캐시 변경은 미스 비율을 증가시키고, 성능을 저하시킨다.
DUP는 오브젝트 – 캐시될 수 있는 아이템이라고 정의 – 와 하부 데이타 – 주기적으로
변경되고 오브젝트의 값을 변경시키는 – 사이의 관계를 관리한다. 트리거 모니터라고
불리는 프로그램이 오브젝트와 하부 데이타 간의 데이타 의존 정보를 관리하고, 언제
데이타가 변경되는지를 결정한다. 시스템이 변경을 인식하는 경우 저장된 의존 정보를
질의하여 어느 캐시된 오브젝트가 영향받으며, 무효화하거나 수정해야 하는지
결정한다.
의존성은 방향성 그래프로 표시되는데, 이것을 오브젝트 의존성 그래프(object
dependence graph, ODG)라고 부른다. 버텍스는 오브젝트나 하부 데이타를 나타내고,
버텍스 v에서 버텍스 u로의 엣지는 v에 대한 변경은 u에도 영향을 준다는 것을
나타낸다. 트리거 모니터는 그림 4의 ODG를 응용에서의 정보에 의해서 생성한다.
만약 go2 노드가 변경되면, 트리거 모니터는 이것을 탐지한다. 시스템은 그래프 탐색
알고리즘을 사용하여 go2의 변화에 의해서 어떤 오브젝트가 영향을 받는지 결정한다.
이 경우는 go5, go6, go7이다. 시스템은 다음에는 불필요하다고 결정한 오브젝트를
무효화하든지, 또는 수정한다.
각 엣지에 중요도를 다르게 주어, 무효화된 하부의 데이타가 오브젝트에 얼마나
영향을 주는지 결정하는데 도움을 줄 수 있다. 그림 4에서, go1에서 go5로의 데이타
의존성은 go2에서 go5로의 의존성에 비해서 더욱 중요한데, 앞의 것이 뒤의 것에
비해 5배의 중요도를 갖기 때문이다. 따라서 go1의 변경이 go2의 변경에 비해 go5에
미치는 영향이 더 크다. 우리는 DUP 알고리즘을 이전 연구에서 자세히 설명하였다.
(2) 동적 데이타를 생성하는 인터페이스
동적 페이지를 생성하는 서버 프로그램을 호출하는 인터페이스는 성능에 중요한
영향을 준다. Common Gateway Interface(CGI)는 각 요청을 처리하기 위해서 새로운
프로세스를 생성하고, 심각한 부하를 준다. 가장 많이 사용되는 인터페이스였던
CGI는 더 좋은 성능의 메카니즘으로 교체되고 있다. 예를 들어 오픈 마켓의 FastCGI
(http://www.fastcgi.com)는 계속 동작하는 프로세스를 생성하여 웹 서버가 요청을
전달하도록 한다. 이 기법은 프로세스 생성 부하를 피할 수 있으나, 웹 서버와
FastCGI 프로세서간의 통신 부하는 여전히 요구된다. FastCGI는 또한 하나의 서버가
처리할 수 있는 동시 접속의 수를 하나의 컴퓨터가 처리할 수 있는 프로세스의 수로
제한한다.
서버 프로그램이 호출될 때마다 새로운 프로세스를 생성하거나, 미리 생성된
프로세스와 통신하는 방법 대신에, 아파치, IBM Go 서버, 넷스케이프와
마이크로소프트의 웹 서버들은 웹 서버 프로세스 자신의 일부로 서버 확장을 호출하는
인터페이스를 제공한다. 서버 태스크는 웹 서버 안에서 독립된 쓰레드에서 실행되고,
동적으로 로드되거나 정적으로 서버에 포함된다. IBM의 Go 웹 서버 API(GWAPI),
넷스케이프의 서버 응용 프로그래밍 인터페이스(NSAPI), 마이크로소프트의 인터넷
서버 API(ISAPI), 아파치의 저수준 ‘모듈’ 등이 모두 이런 접근방법의 예이다. 또
주의깊은 쓰레드 관리를 통해 존재하는 서비스 쓰레드 수에 비해 많은 연결을 처리할
수 있고, 전체 자원 소비를 감소시키고, 용량을 증가시킨다. 불행히도, GWAPI, NSAPI,
ISAPI, 아팥치 모듈 등이 제공하는 인터페이스는 실제 사용하기는 좀 까다롭고,
이식성, 쓰레드 안전성, 메모리 관리 등이 개발 과정을 복잡하게 한다.
더 최근의 접근 방법, IBM의 자바 서버 페이지(JSP), 마이크로소프트의 액티브 서버
페이지(ASP), 자바 서블릿, 아파치의 mod_perl 등은 이런 인터페이스를 감추고 웹
개발자의 작업을 자바, 비주얼 베이직, Perl을 사용하여 쉽게 가능하도록 한다. 이들
서비스는 쓰레드 안전성의 여러가지 문제도 감추어주고, 내장된 가비지 컬렉션을
제공하여 프로그래머의 메모리 관리 문제를 해결해 준다. 원래의 인터페이스를 직접
사용하여 작성된 익스텐션에 비해서 속도는 느릴 수 있으나, 프로그램 생성의 편리성,
유지보수, 이식성과 응용의 신뢰성 증가 등이 약간의 성능 차이에 비하면 훨씬 크다.
4. 1998 올림픽 게임 사이트
1998 동계 올림픽 웹 사이트의 구조는 1996년 하계 올림픽 웹 사이트에서의 경험에서
발전한 것이다. 1996년에 우리가 수집한 서버 로그로부터 1998년 웹 사이트 설계의
중요한 통찰을 얻을 수 있었다. 우리는 대부분의 사용자가 기본적인 정보, 메달 순위,
최근의 결과, 현재 뉴스 등을 찾기 위해 너무나 많은 시간을 소비한다는 것을 알게
되었다. 클라이언트는 최소한 세 번 이상의 웹 서버 요청을 통해서야 결과 페이지에
도달할 수 있었다. 사이트의 뉴스, 사진, 스포츠 섹션 등에 대해서도 비슷한 브라우징
패턴을 보였다. 더 나아가, 한 클라이언트가 한 마지막 페이지에 도착하고 나면,
거기엔 다른 섹션에 있는 적절한 정보로 이동하는 직접 링크가 아무 것도 없었다. 이
계층적 탐색 순서 때문에, 중간에 탐색되는 페이지들은 가장 자주 접근되는 것들에
포함되었다.
1998 사이트의 주요 목표 중의 하나는 히트 수 감소였는데, 1996년의 웹 사이트
디자인과, 1998 사이트에서 제공되는 추가된 컨텐츠를 고려하여 예측하면 하루 2억
히트 이상을 기록하기 때문이었다. 따라서 우리는 페이지를 재설계하여 클라이언트가
관계된 정보들을 더 적은 수의 웹 페이지를 보면서 얻을 수 있도록 하였다. 1998
올림픽 게임 웹 사이트의 자세한 설명은 이전의 연구에서 얻을 수 있다.
가장 중요한 변화는 매일 새로운 홈페이지를 생성하고, 이전의 홈 페이지를
클라이언트들이 볼 수 있도록 하는 최상위의 탐색 레벨을 추가한 것이었다. 우리
예상으로는 개선된 페이지 설계로부터 3배 이상의 히트 수 감소를 얻을 수 있었다. 웹
서버 로그 분석에 의하면 25%의 사용자는 개선된 홈페이지에서는 그날의 홈페이지
하나만 보면 원하는 정보를 찾을 수 있었다.
(1) 사이트 구조
웹 사이트는 전세계에 흩어져 있는 4개의 IBM Scalable Parallel (SP2) 시스템
복합체로 구성되었으며 총 143 프로세서, 78 GB의 메모리, 2.4 TB 이상의 디스크
공간을 사용하였다. 우리는 이 수준의 하드웨어를 사용하여 고성능과 가용성을 확실히
보장하도록 했는데, 이 사이트가 매우 인기있을 뿐만 아니라, 보여주는 데이타가 계속
변화하는 사이트였기 때문이다. 새로운 내용이 시스템에 들어올 때마다, 변화를
반영하여 변경된 웹 페이지를 전세계에 몇 초 안에 제공할 수 있었다. 클라이언트는
따라서 게임으로부터 가장 최근의 결과, 뉴스, 사진 다른 정보를 얻기 위해 웹
사이트에 의존할 수 있었다. 시스템은 최고로 사용자가 몰리는 기간에도 페이지들을
신속하게 제공했으며, 사이트는 게임 기간동안 100% 접속이 가능했다.
우리는 자료의 복제, 지리적으로 분산된 4곳으로부터 페이지를 서비스하는 여분의
하드웨어를 사용하여 고가용성을 이루었다. 하나의 서버가 고장나면, 요청은
자동으로 다른 서버들로 전송되었으며, 만약 하나의 복합체 전체가 고장나면, 요청은
다른 세 개로 전송되었다. 네트워크는 여분의 경로를 가지고 있어서 단일 지점의
고장으로 전체가 끊어지는 것을 막아 주었다. 또한 네트워크는 예상되는 대역폭의
최소 2~3배를 처리할 수 있도록 설계되어 일부 네트워크가 고장나더라도 높은 데이타
용량을 감당할 수 있도록 하였다.
동적 페이지는 FastCGI를 사용하여 생성되었고, 웹 사이트는 동적 페이지를 DUP
알고리즘을 사용하여 캐싱하였다. DUP는 97% 이상의 캐시 히트율을 달성하는데 중요한
요소였다. 1996년의 웹 사이트의 경우 초기 단계의 기법들을 사용하였으며, 동적
페이지들을 DUP를 사용하지 않고 캐싱하였다. 따라서 어떤 페이지들이 새로운 정보에
의해 변경되었는지 정확히 결정하기 어려웠다. 부적당한 페이지를 확실히 모두
제거하도록 하는 과정에서 (제거될 필요가 없는) 현재의 많은 페이지들이
제거되었으며, 이것이 시스템이 새로운 자료를 받은 다음 높은 미스율을 낳는 원인이
되었다. 1996년 웹 사이트의 캐시 히트율은 80% 정도였다. 100%에 가까운 히트율을
달성하는데 또다른 주요 요소는 프리패칭이었다.(역주:사용자의 요청이 있기 전에
미리 페이지를 생성하는 기법) 핫 페이지(역주:캐시에서 매우 자주 요청되는
페이지)가 자료의 변화로 낡은 것이 되는 경우, 캐시에서 무효화되는 것이 아니라
캐시 내에서 새로운 버전으로 수정되었다.(역주: 무효화되는 경우 다음 요청이 들어올
때 생성되고, 캐시에 들어온다) 따라서 이들 페이지에 대해서는 캐시 미스가 발생하지
않았다.
하부 데이타에 대한 수정은 페이지를 서비스하는 것과는 다른 프로세서에서 실행되기
때문에, 응답 시간은 수정이 가장 빈번한 시간에도 그다지 영향을 받지 않았다.
그러나, 1996년의 웹사이트에서는 웹 서버로 사용되는 프로세서가 하부 데이타를
수정하는 일에도 사용되었다. 이러한 설계와 높은 캐시 미스율로 수정이 빈번한
기간에 응답 시간을 늘리는 결과가 되었다.
(2) 시스템 구조
웹 페이지는 4 곳에서 서비스된다. 일리노이주의 샤움버그, 오하이오주의 콜럼버스,
매릴랜드주의 베쎄스다, 일본의 도꾜이다. http://www.nagano.olympic.org로의
사용자 요청은 지역의 ISP에서 IBM 글로벌 서비스 네트워크로 전달되고, IGS
라우터는 요청을 사용자의 지역에 가장 가까운 곳으로 전달한다.
페이지들은 각 사이트의 IBM SP2 시스템에서 생성되고, 서비스된다. 각 SP2는 여러
프레임으로 구성되고 각 프레임은 10개의 RISC/6000 단일 프로세서, 한 개의
RISC/6000 8웨이 SMP로 구성된다. 각 단일 프로세서는 512MB의 메모리와 대략 18GB의
디스크 공간을 가진다. 각 SMP는 1 GB의 메모리, 대략 6 GB의 디스크 공간을 가진다.
전부 우리는 13개의 SP2 프레임을 사용했다. 샤움버그에 4개, 나머지에 각 3개씩. 각
지역에 관리, 지원, 화일 서비스, 네트워킹, 라우팅, 기타 여러 일을 위해 수많은
컴퓨터가 사용되었다.
우리는 1996년의 사이트 트래픽, 용량, 성능 데이타를 바탕으로 지나간 1년 반동안의
웹 트래픽의 대략적인 증가를 감안하고, 게임 기간동안의 100% 사이트 가용성을
고려하여, 하드웨어 요구사항을 계산했다. 돌아보면, 우리는 필요보다 너무 많은
하드웨어를 사용했다. 이러한 초과 예측은 부분적으로는 우리의 캐싱 알고리즘이
서버의 CPU 시간을 우리가 생각한 것보다 많이 줄여주었기 때문이다.
결과 데이타는 시간 계측 장비와 현장에서 컴퓨터에 입력된 자료에서 곧바로
수집되었다. 스코어 장비는 현장에서 토큰링 LAN으로 지역 DB2 데이타베이스에
연결되고, 데이타는 나가노의 마스터(메인프레임에 연결된) 데이타베이스에
전송되었다. 마스터 데이타베이스는 현장의 스코어 시스템과 인터넷에 서비스를
제공했다.
그림 5는 마스터 데이타베이스로부터 도꾜와 샤움버그로 데이타가 어떻게
복제되는가를 보여준다. 샤움버그에서 다시 데이타는 베쎄스다와 콜럼버스로
복제된다. 신뢰성과 복구 목적으로, 도꾜의 사이트는 샤움버그로도 복제할 수 있도록
했다.
(3) 로컬 로드 밸런싱과 고가용성
로드밸런서(LB)는 우리가 사용한 복합체의 네트워크 관리 기법을 구현하는데 필수적인
요소였다. 우리는 IBM ND를 선택했지만, 다른 로드 밸런서, Radware나 Resonate의
제품을 선택할 수도 있었다. LB는 인터넷에서 트래픽 요청을 받아들이고, 이들을
복합체로 전송하며, 다시 처리를 위해 사용가능한 웹 서버로 전송한다. 그림 6에서
보듯이 미국내의 각 복합체마다 4개의 LB 서버가 라우터와 전반부 웹서버 사이에
자리잡고 있다. 4개의 LB 서버의 각각은 12개의 1차 소스 주소 중의 세 개씩을 가지고
있으며, 두 개식의 2차 소스 주소를 가지고 있다. 각 LB의 2차 소스 주소는 더 높은
라우팅 cost가 할당되어 있다.
각 LB 서버는 gated 라우팅 데몬을 실행한다. 이것은 IP 주소를 라우터에 이르는
경로로 알리도록 설정되어 있다. 우리는 각 LB에 이것이 어떤 IP 주소에 대해서 1차
혹은 2차 서버인지에 따라서 서로 다른 cost를 할당하였다. 라우터는 이들 경로를
네트워크에 재전송할 것이다. 각 복합체에서 알려준 경로 정보에 따라서, 라우터는
들어온 요청을 가장 작은 cost의 LB로 전송하도록 결정한다. 이것은 일반적으로 가장
가까운 복합체에서 들어온 요청에 할당된 주소에 대한 1차 소스인 LB이다.
요청은 주소에 대한 2차 LB로는 단지 1차 LB가 어떤 이유로든 다운되었을 때만
전송된다. 2차 LB도 다운되었을 때는, 트래픽은 다른 복합체의 1차 LB로 전송된다.
이러한 설계는 LB 서버의 관리자에게 복합체간의 로드 밸런싱의 제어를 허용한다. 더
나아가, 라우터는 설계를 위해 변경될 필요가 없는데, LB 서버로부터 동적 라우팅
프로토콜을 통해 경로를 학습하기 때문이다.
각 LB 서버는 각 사이트의 SP2 프레임에 흩어져 있는 전반부 웹 서버 풀에 연결된다.
트래픽은 각 웹 서버 노드에서 실행되는 어드바이저라고 불리는 프로그램이 제공하는
부하 정보에 따라서 웹 서버 사이에 분산된다. 웹 노드가 다운되면, 어드바이저가
즉시 분산 리스트에서 제거한다.
이러한 접근 방법은 사이트에서 어떤 단일 고장 지점을 허용하지 않음으로써
고가용성을 보장한다. 웹 서버 고장의 경우, LB는 자동적으로 웹 서버 풀의 다른
서버들로 요청을 전송할 것이고, SP2 프레임이 다운되는 경우, LB는 다른 프레임으로
전송할 것이다. 라우터는 LB 서버가 다운되는 경우 백업 서버로 전송할 것이고, 전체
복합체가 고장인 경우, 트래픽은 자동으로 백업 사이트로 연결된다. 이런 방법으로
우리가 우아한 성능저하라고 부르는 방식으로, 복합체 내의 여러 고장 지점이 즉시
처리되고, 트래픽이 부드럽게 아직 동작하고 있는 시스템 요소로 재분산된다.
1998년 올림픽 이후, 우리의 기술은 1998년, 1999년 윔블던 테니스 대회를 포함한
다른 접속 빈도가 높은 사이트에 채용되었다. 이들 사이트는 모두 1998년 올림픽 게임
사이트보다 더 높은 요청률을 보였는데, 주로 웹 사용의 계속적인 증가때문이었다.
1999년 윔블던 사이트는 1998년 올림픽에서 사용되지 못했던 웹 서버 가속 기술이
사용되었다. 이 사이트는 14일동안 9억 4천 2백만 히트를 받았고, 이것은 7천1백만
페이지 뷰, 8백7십만 방문에 해당한다. 최고 히트율은 분당 43만, 일일 1억
2천5백만에 달했다. 비교해 보면, 1998년의 올림픽 게임 웹 사이트는 16일동안 6억
3천4백만 히트를 받았고, 최고 히트율은 분당 11만, 일일 5천7백만에 달했다.
우리는 2000년 올림픽 게임 웹 사이트를 위한 동적 웹 컨텐트 위한 고도의 시스템을
개발하고 있으며, 웹 서버 가속을 더 많이 사용할 것이다. 이 (웹) 출판 시스템에
대한 설명은 InfoCom 2000에서 예정되어 있다.
Acknowledgements, References, 저자 약력 생략.
독자들은 저자들을 {aruni, challngr, dias, pauldant}@us.ibm.com으로 연락할 수
있다.