1. NginX를 이용한 static 컨텐츠 서비스
- 로드밸런싱 : 유저의 요청을 웹 애플리케이션 서버(WAS)로 분산 할 수 있다.
- 유저 요청에 대한 선 처리 : 유저의 요청이 WAS에 도달하기 전에 다양한 처리를 할 수 있다. 웹 애플리케이션 방화벽(WAF)를 설치하거나, 유저의 요청을 다른 위치로 보내도록 제어 할 수 있다.
- 캐싱 : 웹 서비스는 이미지, CSS, 자바스크립트 같은 정적인 페이지를 가지고 있다. 이런 정적 컨텐츠들을 NginX에서 대신 처리하는 것으로 응답 속도를 높일 수 있으며, WAS에 대한 부담을 줄일 수 있다. 컨텐츠들을 메모리에 캐시할 경우 서비스 할 경우 고성능의 웹 서비스를 만들 수도 있다.
2. Web Contents 캐시에 대해서
2.1. 서버 캐시
컨텐츠 캐시
다. 요즘 웹 서버는 매우 바쁘다. 유저의 요청을 받아서 데이터베이스를 조회해서 즉석에서 HTML 페이지를 만들고 이미지와 CSS, 자바스크립트 등 다양한 오브젝트들을 함께 응답해야 한다. 웹 서버가 해야 하는 일이 늘어나면서 리버스 프락시
를 이용, 두 개 이상의 WAS(Web Application Server)
가 요청을 분산해서 처리하도록 구성을 한다.변하지 않는 컨텐츠
의 경우에는 그냥 프락시 서버에서 직접 응답을 하게 하면 더 빠른 서비스를 제공 할 수 있지 않을까 ? 요즘 왠만한 웹 서비스들은 동적으로 컨텐츠를 서비스 한다. 하지만 조금만 들여다 보면, 많은 컨텐츠가 정적(변하지 않음)이라는 것을 알 수 있다. 이미지, CSS, Javascript, 동영상, PDF 뿐만 아니라 HTML 문서의 상당수도 정적이다. 유저 정보를 표시하는 HTML 문서는 (데이터베이스 등을 조회해서) 동적으로 만들어져야 하겠으나, 메뉴얼, 사이트 소개, 메뉴 등은 변하지 않는 컨텐츠들이다. 이들 컨텐츠들을 프락시 서버에서 서비스 한다면 더 빠르고 효율적으로 서비스 할 수 있을 것이다. 아래 그림을 보자.- 네트워크 홉 이 줄어든다. WAS까지 요청을 보내지 않아도 된다. 1만큼의 네트워크 홉을 줄일 수 있다.
- 파일처리에 최적화 할 수 있다. 캐시 서버는 파일에 대한 "읽기/쓰기" 연산, 그 중에서도 읽기 연산을 주로 한다. 목적이 특정되므로 이에 맞게 최적화 할 수 있다. 당연하지만 NginX나 Apache 같은 전용 웹서버는 다양한 일을 하는 WAS(Django, RoR, Node)보다 빠르고 효율적으로 작동한다.
- 최적화가 쉽다. 정적 컨텐츠와 동적 컨텐츠를 분리 함으로써, 그에 맞는 최적화 방법을 사용 할 수 있다. 정적 컨텐츠를 Redis나 memcache, 램디스크 등으로 캐시할 수 있다.
3. NginX 캐시 매커니즘
- NginX 캐시 서버가 컨텐츠 요청을 받는다.
- 요청 URL을 Key로 컨텐츠가 캐시돼 있는지 확인한다.
- 처음 요청이므로 캐시 실패(
MISS
) 한다. - WAS서버로 요청을 보낸다.
- WAS서버로 부터 응답이 오면 캐시를 할지를 검사한다.
- 응답을 디스크에 저장한다.
- 다음 번에 같은 URI로 요청이 오면, 캐시 적중(
HIT
)한다. 요청은 WAS로 전달되지 않으며, 캐시서버가 대신 응답한다.
4. 테스트 구성
- Nginx는 WAS(Web application Server)나 다른 웹 서버(Nginx나 apache 같은)의 앞에 배치 할 수 있다. 로드밸런서로서의 역할 과 캐시 서버로의 역할을 동시에 수행 할 수 있다.!
- Nginx는 일반적인 HTTP 요청 뿐만 아니라
FastCGI
와uWSGI
요청의 결과를 캐시할 수 있다. 이 기능은 특히 CMS(Content Management System)의 결과물을 캐시하는데 유용하게 사용 할 수 있다. - 캐시서버를 둠으로써, 애플리케이션 서버의 부하를 분산 할 수 있다.
5. WAS 서버 구성
Expires
와 Date
가 같은 시간임을 알 수 있다. 요청시간과 동시에 컨텐츠가 만료됐다. 따라서 클라이언트는 요청 결과를 캐시하지 않는다. 또한 Cache-Control: no-cache
로 이 컨텐츠를 캐시하지 말라고 지시하고 있다.Expires
시간이 현재시간으로 부터 1년 후임을 알 수 있다. 이 규칙에 의해서 foundation.css는 최대 1년 동안 캐시가 된다.6. 캐시 서버 설정
192.168.56.31:80
에서 유저 요청을 기다린다. 만약 유저 요청이 도착하면, proxy_pass에 설정된192.168.56.30
으로 요청을 전달한다. curl을 이용해서 /css/foundation.css를 요청해 보자. 캐시서버가 컨텐츠를 캐시하지 않고 있기 때문에, 이 요청은 WAS까지 전달된다.6.1. proxy_cache_path
levels
는 캐시파일을 어떻게 저장할지를 결정한다. 만약 levels를 설정하지 않는다면, 캐시파일은 현재 디렉토리에 저장이 된다. level을 설정할 경우, 서브디렉토리에 md5 해시된 파일이름으로 컨텐츠를 저장한다. level=1:2는 첫번째 단계의 디렉토리는 한글자, 두번째 단계의 디렉토리는 두 글자로 명명하라는 의미다. 예를 들어 /tmp/nginx/a/bc
디렉토리에 캐시 파일이 저장된다.keys_zone
은 이 캐시를 가리키는 이름이다. my_zone
은 캐시와 메타파일을 저장하기 위해서 10M의 공간을 할당 했다.inactive
지시어를 사용 하면, 일정 시간동안 접근이 없는 캐시파일을 할 수 있다. 위 설정에서는 한시간(60 minutes)동안 사용하지 않는 캐시파일은 삭제하도록 설정했다.6.2. proxy_cache_key
Key
규칙을 설정한다. 기본 설정 값은 $scheme$proxy_host$uri$is_args$args
이다. "$host$request_uri $cookie_user"와 같이 사용 할 경우 유저 쿠키 별로 캐시를 구성할 수도 있다.6.3. proxy_cache
location
블럭내에서 사용한다. my_zone
캐시를 사용하도록 설정했다. add_header X-Proxy-Cache $upstream_cache_status
헤더를 추가했다. 이 헤더에는 HIT
, MISS
, MYPASS
와 같은 캐시 적중 상태정보가 설정된다.MISS
가 설정된 걸 확인 할 수 있다. 캐시를 하기 위해서는 WAS
로 부터 최소한 한 번 이상의 요청이 이루어져야 한다. 다시 한번 요청을 해보자.HIT
)한 것을 알 수 있다. 이 요청은 WAS
로 전달되지 않고, 캐시 서버가 대신 응답한다. 캐시서버 디렉토리에서 캐시파일을 확인 할 수 있다.Cache-Control
헤더 요청을 무시한다. 만약 클라이언트의 Cache-Control
요청을 허용하고 싶다면, 아래와 같이 설정을 바꿔야 한다.BYPASS
로 설정된 걸 알 수 있다. 이 요청은 WAS 서버로 직접 전달된다. tcpdump
로 Cache-Control을 설정했을 때와 그렇지 않았을 때를 테스트 해보자.6.4. 캐시 상태
MISS | 캐시를 찾을 수 없다. 요청은 WAS 까지 전달된다. WAS 응답이 끝나면 캐시가 만들어질 것이다. |
BYPASS | 캐시서버의 캐시를 무시하고, WAS까지 요청을 전달한다. 캐시서버는 아마도 캐시를 가지고 있을 것이다. |
EXPIRED | 캐시 만료시간이 초과했다. 캐시서버는 WAS로 요청을 전달해서 캐시를 업데이트 한다. |
STALE | 서버가 제대로 응답하지 않아서, 낡은(stale) 캐시를 서비스하고 있다. |
UPDATING | 정확한 목적을 모르겠다. 좀 더 살펴봐야 할 듯 |
REVALIDATED | 캐시가 여전히 유효하다. 클라이언트가 if-modified-since를 설정했을 때 리턴한다. |
HIT | 성공적으로 캐시를 서비스 했다. |
7. Joinc에 적용
Go
로 직접 개발한 CMS(자칭 gowiki)로 운영하고 있다. 모니위키를 기반으로 하고 있기 때문에, 위키문법의 문서를 HTML
로 변환하는데 상당한 자원이 들어간다. 성능을 올리기 위해서 gowiki 서버 앞에 nginx 캐시서버를 두기로 했다./w/FrontPage
를 요청하면, Gowiki로 요청이 전달된다. Gowiki는 FrontPage 문서를 HTML로 변환해서 응답한다. 이 응답은 NginX 서버가 캐시를 하므로, 다음번 요청 부터는 캐시에 있는 데이터를 응답한다./api
로 요청을 한다. 코드 실행기가 대표적인 경우인데, 이런 컨텐츠는 캐시하면 안 된다. 그리고 css, js, png, jpg 등도 캐시하기로 했다. NginX의 설정은 다음과 같다.7.1. 캐시 삭제
./nginx-cache-purge /w/man/12/nginx /tmp/nginx
수행하면 된다.7.2. 성능 테스트


7.3. 하나의 HTML 문서에 정적 컨텐츠와 동적 컨텐츠가 함께 있을 때
쿠기(cookie)
를 이용해서 이 문제를 해결 했다. 아래와 같이 proxy_cache_key에 cookie_login
을 설정했다.
댓글 없음:
댓글 쓰기