이 장에서는 서비스의 핵심이 되는 TTL(Time To Live)과 Caching-Key 그리고 만료정책에 대해 설명한다.
저장된 콘텐츠는 TTL동안 유효하다.
HTTP 규격은 TTL을 설정할 수 있도록 Cache-Control을 명시하고 있다.
하지만 이는 절대적인 것은 아니다.
다양한 방식의 TTL 정책과 5장. Caching 무효화 를 통해 서비스 품질을 높일 수 있다.
HTTP에는 콘텐츠를 구분하는 다양한 규격이 존재한다.
그만큼 Caching-Key도 다양하게 존재할 수 있다.
콘텐츠 변경이 없을수록 원본부하를 줄일 수 있을뿐만 아니라 쉽게 확장할 수 있다.
서비스에 최적화된 만료정책을 수립하는 다양한 방식에 대해 설명한다.
앞으로 설명되는 설정을 모든 가상호스트의 기본 설정으로 적용하고 싶다면 <VHostDefault> 하위에 설정한다.
반대로 특정 가상호스트에만 적용하고 싶다면 <Vhost>태그 하위에 설정한다.
Caching-Key 란 콘텐츠를 구분하는 고유 값이다.
파일시스템에서 파일들과 구분되는 고유경로(예. /usr/conf.txt)를 가지는 것과 같은 개념이다.
흔히 Caching-Key 는 URL과 혼동되기 쉽다.
HTTP의 여러 기능에 따라 같은 URL이라고 하더라도 콘텐츠가 달라질 수 있다.
TTL이란 저장된 콘텐츠의 유효시간이다.
TTL을 길게 설정하면 원본서버의 부하는 줄어들지만 변경사항이 늦게 반영된다.
반대로 짧게 설정하면 너무 잦은 변경확인 요청으로 원본서버 부하가 높아진다.
운영의 묘미는 TTL을 적절히 설정하여 원본부하를 줄이는 것에 있다.
TTL은 한번 설정되면 만료되기 전까지 바뀌지 않는다.
새로운 TTL은 파일이 만료되었을 때 적용된다.
관리자는 Purge , Expire , ExpireAfter , HardPurge 등의 API를 사용해 TTL을 변경할 수 있다.
기본적으로 TTL은 원본서버의 응답에 따라 결정된다.
TTL이 만료되기 전까지 저장된 콘텐츠로 서비스 된다.
TTL이 만료되면 원본서버로 콘텐츠 변경여부( If-Modified-Since 또는 If-None-Match )를 확인한다.
원본서버가 304 Not Modified 응답을 준다면 TTL은 연장된다.
<Res2xx>(기본:1800초,Ratio:20,Max=86400)
원본서버가 200 OK로 응답했을 때 TTL을 설정한다.
콘텐츠를 처음 저장할 때 <Res2xx> 초 뒤에 콘텐츠가 만료(TTL)되도록 설정한다.
(TTL만료 후) 원본서버에서 변경되지 않았다면(304 Not Modified) Ratio 비율(0~100)만큼 TTL을 연장한다.
TTL은 최대 Max 까지 증가한다.
<NoCache>(기본:5초,Ratio:0,Max=5,MaxAge=0,Expire=OFF)<Res2xx> 와 동일하나 원본서버가 no-cache 로 응답하는 경우에만 적용된다.
Expire 속성이 ON 이라면 TTL과 상관없이 캐싱 즉시 TTL을 만료시킨다.
클라이언트 서비스 전 항상 원본 갱신여부를 체크한다.
<NoStore>(기본:5초,Ratio:0,Max=5,MaxAge=0,Bypass=OFF)<Res2xx> 와 동일하나 원본서버가 no-store 로 응답하는 경우에만 적용된다.
cache-control:no-store
Bypass 속성이 ON 이라면 클라이언트 요청을 원본서버로 바이패스 한다.
이때 콘텐츠는 캐싱되지 않으며, TTL은 클라이언트 요청을 바이패스할 시간으로만 기능한다.
<Res3xx>(기본:300초)
원본서버가 3xx로 응답했을 때 TTL을 설정한다.
Redirect용도로 사용되는 경우가 많다.
<Res4xx>(기본:30초)
원본서버가 4xx로 응답했을 때 TTL을 설정한다.
404 Not Found 인 경우가 많다.
<Res5xx>(기본:30초)
원본서버가 5xx로 응답했을 때 TTL을 설정한다.
원본서버 내부 장애상황인 경우가 많다.
<ConnectTimeout>(기본:3초)
원본서버로 접속하지 못하는 경우 TTL을 설정한다.
콘텐츠가 이미 저장되어 있다면 <ConnectTimeout> 초 만큼 TTL을 연장한다.
콘텐츠가 저장되어 있지 않다면 <ConnectTimeout> 초 만큼 장애상황으로 응답한다.
이는 장애상황을 서비스한다는 의미보다는 TTL시간동안 (아마도 장애상황일) 원본서버에 부담을 주지 않기 위함이다.
<ReceiveTimeout>(기본:3초)
접속은 됐으나 데이터를 수신하지 못하는 경우 TTL을 설정한다.
<ConnectTimeout> 과 의미적 동일하다.
<OriginBusy>(기본:3초)과부하 판단 조건을 만족하면 원본서버 요청없이 만료된 콘텐츠의 TTL을 설정된 시간만큼 연장한다.
이는 원본서버의 부하를 가중시키지 않기 위함이다.
Note
TTL 값을 0으로 설정하면 서비스 직후 곧바로 만료된다.
만약 모든 요청에 대해 원본서버의 응답을 주고 싶다면 바이패스할 것을 권장한다.
URL마다 별도로 TTL을 설정한다.
명확한 URL 또는 패턴 URL에 매칭되는 콘텐츠마다 고정된 TTL을 설정할 수 있다.
/svc/{가상호스트 이름}/ttl.txt 에 설정한다.
# /svc/www.example.com/ttl.txt# 구분자는 콤마(,)이며 시간 단위는 초이다.*.jsp,10/,5/index.html,5/script/*.js,300/image/ad.jpg,1800
모든 페이지(html, php, jsp 등)에 별도의 TTL을 설정하기 위하여 *.html을 추가하였더라도 첫 페이지(/)에는 설정되지 않는다.
원본서버가 첫 페이지를 어떤 페이지(예를 들어 index.php로 default.jsp 등)로 설정하였는지 HTTP 프로토콜로는 알 수 없다.
그러므로 모든 페이지에 별도의 TTL을 설정하려면 반드시 /를 추가해야 한다.
CDNv2.6.13 , Enterprisev19.07.0 부터 원본 응답코드에 따라 TTL을 지정할 수 있다.
$URL[/image/ad.jpg], 1800
$URL[*.jpg] & $ORGSTATUS[200], 3600
$URL[/image/ad.jpg] & $ORGSTATUS[4xx], 10
// CDN v2.7.30 부터 지원
// 원본이 304 Not Modified로 응답할 경우 기존 콘텐츠의 TTL을 설정된 시간으로 설정한다.
$URL[*] & $ORGSTATUS[304], 1000
$ORGSTATUS[] 표현의 값은 명시적인 원본 응답코드(200, 404) 또는 응답코드 그룹(2xx, 3xx, 4xx, 5xx)으로 설정 가능하다.
결합조건(&)을 지원하며, 부정조건(!)은 지원하지 않는다.
원본서버 종료로 인해 응답이 오지 않는 경우에는 장애판단이 명확하지만 간혹 정상적으로 응답하면서 장애상황인 경우가 발생한다.
예를 들어 콘텐츠를 저장하는 Storage와의 연결을 잃거나, 뭔가 정상처리가 불가능하다고 판단하는 경우가 있을 수 있다.
전자의 경우 4xx응답(주로 404 Not Found ), 후자는 5xx응답(주로 500 Internal Error )을 받게된다.
하지만 이미 관련 콘텐츠가 저장되어 있다면,
원본의 응답을 믿는 것보다 TTL을 연장시켜 서비스 전체장애가 발생하지 않도록 하는편이 효과적이다.
고화질 동영상이나 게임처럼 상대적으로 반응성보다 전송속도가 중요한 서비스에서는 이런 방식이 큰 문제가 되지 않는다.
대용량 데이터의 경우 원본서버가 10초만에 갱신에 대한 응답을 한다고 하더라도 전송에 몇 분씩 소요되기 때문에 상대적으로 원본의 반응성이 크게 중요하지 않다.
오히려 접근 빈도가 높지 않은 콘텐츠이기 때문에 반드시 갱신확인이 이루어져야 한다.
하지만 쇼핑몰과 같은 경우 상황은 다르다.
웹 페이지는 빠르게 로딩되는 것이 무엇보다 중요하다.
1~2초 안에 클라이언트 화면구성이 모두 끝나야 한다.
전송속도보다 반응속도가 더 중요하다는 말이다.
이때 TTL이 만료되어 원본서버에게 갱신확인을 해야 한다면 매우 큰 지연이 발생할 수 있다.
보통의 쇼핑몰이 수백만개의 콘텐츠를 동시에 서비스 하는 것을 감안할 때 항상 원본서버로부터 갱신확인 작업이 발생하고 있다고 생각해야 한다.
자칫 원본서버 장애가 발생하거나 네트워크 장애가 발생한다면 최악이다.
우리가 원하는 것은 어떠한 원본서버의 장애나 지연으로부터 캐싱된 콘텐츠가 안전하게 전송되는 것이다.
위 그림에서 원본서버와의 갱신작업이 모두 백그라운드로 이루어지기 때문에 캐싱된 콘텐츠는 기다림없이 즉시 클라이언트에게 서비스된다.
원본서버가 304 Not Modified 로 응답한다면 TTL만 연장된다.
파일이 갱신되어 원본서버에서 200 OK를 응답한 경우 해당 파일이 완전히 다운로드된 후에 파일이 부드럽게 교체된다.
콘텐츠가 바뀌어도 이전 콘텐츠(초록색)를 다운로드 받던 사용자들은 정상적으로 다운로드가 진행된다.
파일 교체 이후 접근된 사용자들(겨자색)은 바뀐 파일로 서비스 된다.
콘텐츠 갱신, 네트워크 장애, 원본서버 장애 등 어떠한 변수에도 콘텐츠 갱신은 백그라운드로 진행되기 때문에 실제 서비스에는 전혀 지연이 없다.
ON 파라미터 URL뿐만 아니라 URL에 QueryString이 존재하는 모든 컨텐츠를 대상으로 지정한다.
Collective 속성이 ON이고 파일이 많을수록 Purge API 수행 CPU부하가 높아진다.
관련 파일을 검색하는 소요시간이 길어질 수 있어 예기치 않은 문제를 일으킬 수 있다.
가급적 QueryString까지 붙은 명확한 URL로 Purge API를 호출할 것을 권장한다.
예외조건이 BodySensitive 설정에 따라 의미가 달라짐에 주의한다.
명확한 URL 또는 패턴(*만 허용한다.)으로 설정이 가능하다.
이 설정은 GET/POST 바이패스 와 정책적으로 혼란스러울 수 있다.
<BypassPostRequest>(기본:ON) 에 의해 POST요청이 캐싱되지 않을 수 있다.
따라서 POST요청을 캐싱하기 위해서는 <BypassPostRequest> 를 OFF 또는 예외조건을 설정해야 한다.
정리하면 우선순위는 다음과 같다.