요약

  • HTTPAge는 오리진이 응답을 생성하거나 성공적으로 검증한 이후 경과한 시간(초)의 추정치입니다. 이는 해당 응답이 나타내는 자원, 문서 또는 바이트의 생성 날짜가 아닙니다.
  • 각 캐시는 상속받은Age, 오리진의Date, 요청·응답 타이밍, 네트워크 지연, 로컬 체류 시간을 결합한 뒤, 저장된 응답을 재사용할 때 그 필드를 갱신된 단일current_age로 대체합니다.
  • 신선도는 별개의 판단입니다: current age는 캐시 지시자,Expires또는 허용된 휴리스틱에서 파생된 수명과 비교됩니다. 이 스칼라 값은 검증을 증명하지도, 수신자에게 재사용이 허용되는지 알려주지도 않습니다.

작은 숫자가 오래된 문서를 가리킬 수 있다

3년 전에 작성된 정책 페이지가 2분 전에 오리진에서 검증되어 캐시에서 제공되었다고 상상해 보십시오. 응답은Age: 120과 함께 정당하게 도착할 수 있습니다. 그 값은 문장이 120초 전에 쓰였다는 뜻이 아닙니다. 캐시가 현재 재사용 중인 응답을 오리진이 생성하거나 성공적으로 검증한 후 약 120초가 경과했다고 추정한다는 뜻입니다.

이 구분은 일상 언어가 사물에 “나이”를 부여하기 때문에 놓치기 쉽습니다. HTTP는 응답에 그것을 부여합니다. URL이 식별하는 자원은 웹 서버보다 앞서 존재할 수 있습니다. 표현 바이트는 여러 차례 검증을 거치며 변하지 않았을 수 있습니다. 캐시 항목은 교체되거나 갱신되거나 제거되었을 수 있습니다.Age는 이들 어떤 것의 역사도 아닙니다. 특정 캐시 계산을 위한 간결한 타이밍 값입니다.

이것은 장식적 메타데이터가 아니었습니다. 캐시는 오리진에 접촉하지 않고 이전 응답으로 새 요청에 답할 수 있는지 판단해야 했습니다. 여러 독립 운영 중개자 사이에서 그 판단을 하려면 캐시에서 다음 캐시로 넘겨지는 과정에서 살아남는 추정치가 필요했습니다.

HTTP/1.0에는 캐시 관행은 있었지만 공유된 응답 연령은 없었다

1996년 HTTP/1.0 명세는 캐싱, 날짜, 만료를 기술했지만 정의된 응답 헤더 집합에Age는 없었습니다. 수신자는Date나Expires를 보고, 로컬 수신 시각을 사용하고, 구현 정책을 적용할 수 있었습니다. 응답이 다른 곳에서 이미 축적한 시간을 담은 표준화된 스칼라는 전달받지 못했습니다.

이 간격은 체인에서 중요합니다. 캐시 A가 응답을 80초 동안 보유한 뒤 캐시 B로 보낸다고 가정하십시오. B가 0부터 다시 세면 응답에 두 번째 청춘을 부여합니다. B가 오리진의 벽시계Date에만 의존하면 시계 오차가 응답을 실제보다 젊거나 늙어 보이게 할 수 있습니다. 공통 규칙은 모든 기계가 완벽한 시계를 공유한다고 가정하지 않으면서 경과 시간을 보존해야 했습니다.

HTTP/1.1이 1997년에 그 규칙을 제공했습니다.Age는 발신자의 추정치로서 캐시된 응답과 함께 이동했습니다. 초기 명세는 핵심 재검증 경계를 명시적으로 밝혔습니다: 성공적인 재검증 이후 연령은 원래 응답이 아니라 재검증 시각을 기준으로 한다고. 따라서 이 필드는 기록 보관 연대기가 아니라 캐시 재사용에 속했습니다.

추정치는 두 가지 불완전한 관점에서 나왔다

수신 캐시는 두 가지 독립적 방식으로 초기 연령을 추정할 수 있었습니다. 첫째, 오리진의Date와 응답 도착 시각의 로컬 시간을 비교할 수 있었습니다. 현재 표기법으로는:

apparent_age = max(0, response_time - date_value)

0과의 최댓값은 오리진의 시계가 앞서 있을 때 음수 연령이 나오는 것을 막습니다. 이 관점은 두 시계를 사용하며 둘이 불일치하면 왜곡될 수 있습니다.

둘째, 캐시는 상류에서 받은Age값을 신뢰한 뒤 요청-응답 교환에 소요된 시간을 더할 수 있었습니다:

response_delay = response_time - request_time

corrected_age_value = age_value + response_delay

이 관점은 캐시 시계에서 오리진 시계를 빼지 않아도 됩니다. 그러나 상류 캐시들이Age를 올바르게 삽입하고 갱신하는 데 의존합니다. 구식이거나 결함이 있는 구현을 포함한 경로는 이미 경과한 시간을 과소 보고할 수 있습니다.

보수적인 호환성 계산은 더 큰 쪽을 취합니다:

corrected_initial_age = max(apparent_age, corrected_age_value)

현대 HTTP는Age를 생략하는 구식 캐시가 문제 되지 않는 경우 교정된 연령 값을 직접 사용할 수 있도록 허용합니다. 역사적 최댓값은 여전히 시사적입니다. 프로토콜은 어느 관측도 형이상학적으로 참이라고 주장하지 않았습니다. 하나의 원격 시계를 주권으로 세우지 않으면서 로컬 구현이 증거를 결합하는 방식을 명시했습니다.

체류 시간이 숫자를 현지에서 커지게 했다

응답이 저장된 후 캐시는 어떤 상류 주체도 미리 알 수 없는 것을 알게 되었습니다: 이 특정 사본이 다음 요청 전까지 얼마나 체류했는가. 계산은:

resident_time = now - response_time

current_age = corrected_initial_age + resident_time

캐시가 검증 없이 그 응답을 사용할 때 다른 연령을 덧붙이거나 이전 값 목록을 보존하지 않았습니다. 하나의Age를 생성하고 상류에서 받은 필드를 자신이 계산한current_age로 대체했습니다. 다음 캐시는 그 결과를 상속하고 관측된 응답 지연을 더한 뒤 나중에 자신의 체류 시간을 더합니다.

스칼라는 경로 상세를 흘려보내면서 시간을 축적했습니다. 전송과 저장 사이에 시간이 흘렀다는 것은 말할 수 있지만 대부분이 어디에서 흘렀는지는 말할 수 없습니다. 긴 체류를 가진 두 캐시와 짧은 체류를 가진 열 캐시가 같은 숫자를 내보낼 수 있습니다. 필드에는 캐시 이름, 홉 목록, 영수증, 보관 서명이 없었습니다.

그래서Age는 동시에 유용하고 제한적입니다. 다운스트림 수신자는 모든 상류 로그를 얻지 않고도 계산을 계속할 수 있습니다. 최종 정수에서 출처 그래프를 재구성할 수는 없습니다.

응답 연령과 신선도 수명은 서로 다른 질문에 답했다

가장 흔한 개념 오류는Age: 120을 “120초 동안 신선” 또는 “120초가 남았다”로 읽는 것입니다. 둘 다 아닙니다. 연령은 얼마나 많은 추정 시간이 경과했는지에 답합니다. 신선도 수명은 적용 가능한 캐시 규칙 하에서 검증 없는 재사용이 얼마나 허용되는지에 답합니다.

판단은 둘을 비교합니다:

response_is_fresh = (freshness_lifetime > current_age)

수명은 공유 캐시s-maxage,max-age,Expires와Date사이의 간격, 또는 허용되는 경우 다른 응답 메타데이터에서 파생된 휴리스틱에서 올 수 있습니다. 오리진 정책이 일부 입력을 제공하고, 캐시가 적용 가능한 규칙을 선택해 실행합니다. 120초의 연령은 300초 수명에서는 신선하고 60초 수명에서는 부실합니다.

“부실(stale)”조차 바이트에 대한 도덕적 판정이 아닙니다. 통상의 신선도 비교가 실패했다는 뜻입니다. 검증은 저장된 응답을 신선하게 만들 수 있습니다. 적용 가능한 지시자나 단절 운영 규칙은 부실 재사용을 허용할 수 있습니다. 반대로 젊은 응답도 저장 또는 요청 제약이 금지하면 자동으로 재사용 가능하지 않습니다. 숫자, 수명, 재사용 정책은 분리된 계층입니다.

재검증은 같은 바이트를 정확한 의미에서 젊게 만들었다

캐시가 표현을 하루 저장한 뒤 조건부 요청을 보내고 유효하다는 확인을 받았다고 가정하십시오. 기반 기사는 여전히 하루, 1년, 10년 낡았을 수 있습니다. 저장된 바이트는 동일할 수 있습니다. 그러나 응답의 캐시 연령은 그 성공적인 검증에 기반할 수 있습니다.

이것은 역사를 위조하는 것이 아닙니다. HTTP는 운영적 질문에 답합니다: 캐시가 재사용하려는 응답을 오리진이 마지막으로 생성하거나 확인한 지 얼마나 되었는가? 이 구분 덕분에 안정적인 표현은 연령 필드를 발행 타임스탬프로 제시하지 않고도 효율을 유지할 수 있습니다.

또한 증거 경계를 확립합니다. 검증 후 낮은 연령이 콘텐츠가 변경되었음을 증명하지 않습니다. 높은 연령이 오리진을 이용할 수 없음을 증명하지도 않습니다.Age는 검증자 세부 사항도, 저장된 메타데이터 갱신을 정당화한 결과 기록도 담지 않습니다. 그 사실들은 별도로 관측되어야 합니다.

필드의 존재는 캐시의 증거지만 부재는 오리진 접촉의 증거가 아니다

현재 HTTP는 더 좁은 추론을 허용합니다:Age필드가 있으면 응답은 1차(first-hand)가 아니며 캐시가 저장된 상태에서 생성한 것입니다. 필드만으로는 그 캐시가 이 요청에서 오리진과 검증했는지, 아니면 이전 검증에 의존했는지 드러나지 않습니다.

역은 의도적으로 부정됩니다.Age가 없는 응답이 오리진 접촉을 증명하지 않습니다. 구형 중개자는 생략할 수 있고, 구현은 비준수일 수 있으며, 관측자는 변형되거나 불완전한 기록을 볼 수 있습니다. 부재를 1차 증명서로 승격시킬 수는 없습니다.

필드는 구문적으로도 소박합니다. 초 단위의 음이 아닌 정수입니다. 잘못된 값은 캐시가 무시해야 합니다. delta-seconds 값이 너무 커서 표현할 수 없거나 산술이 오버플로하면 현대 명세는 2147483648, 즉 편리한 최대 양의 정수라는 역사적 포화 관행을 유지합니다. 그 sentinel 값은 실용적 무한대이지 정확히 측정된 68년 캐시 체류의 증거가 아닙니다.

내구성 있는 기록은 헤더보다 크다

캐시 사건을 설명하려는 운영자에게 최종 출력 정수만으로는 부족합니다. 증거는 선택된 캐시 키와 변형, 받은Date와Age, 같은 로컬 시계의 요청·응답 타임스탬프, 모든 파생 항, 신선도 수명의 출처를 보존해야 합니다. 검증이 발생했는지, 어떤 상태와 검증자 메타데이터가 반환되었는지, 판단 경로가 신선한 재사용인지, 검증된 재사용인지, 허용된 부실 재사용인지, 실패였는지도 기록해야 합니다.

Age: 120만 보존하면 여러 원인이 하나의 결과로 압축됩니다. 같은 숫자가 상속된 체류, 전송 지연, 로컬 저장, 시계 차이로 인한 apparent-age 보정을 반영할 수 있습니다. 스칼라만 보여주는 그래프는 증상을 드러낼 수 있지만 책임을 배분할 수 없습니다.

HTTP의 설계는 반대 과잉도 피했습니다. 모든 캐시 판단이 통과해야 하는 중앙 연대기 서비스를 요구하지 않았습니다. 오리진은Date, 정책, 검증자를 제공했습니다. 각 캐시는 저장된 응답을 선택하고 로컬 경과 시간을 측정하고 current age를 계산하고 재사용의 결과를 감수했습니다. 다음 수신자는 산술을 반복할 수 있었습니다.

공통 필드는 조율했습니다. 통치하지 않았습니다. 그 권위는 실행 중인 구현이 소비하고, 다른 입력과 대조하고, 대체할 수 있는 추정치에만 미쳤습니다. 그래서 이 숫자가 살아남았습니다: 네트워크를 통해 이동할 만큼 작으면서, 객체의 정체성이 되지 않을 만큼 좁았습니다.

출처