요약
- ONC RPC는 모든 호출의 시작 부분에 32비트 XID를 두고 이를 응답에 복사해 돌려보냈습니다. 이 필드는 클라이언트가 메시지를 상호 대조하고 서버가 재전송 가능성을 판별할 등식 키를 갖도록 했지만, 시퀀스 번호도 단일 실행의 증거도 아니었습니다.
- NFS는 이 누락된 상태를 드러냈습니다. 휘발성 중복 요청 캐시는 재실행 피해를 줄였지만 삭제나 크래시 이후에는 무너졌고, NFSv4.1은 유한한 세션 슬롯, 슬롯별 시퀀스 ID와 캐시된 응답을 도입해 더 강한 실행 보장이 명시적 메모리 비용을 지도록 했습니다.
침묵은 두 가지 그럴듯한 역사를 남겼다
클라이언트가 파일 삭제를 요청하는 원격 호출을 보냅니다. 서버는 이를 실행할 수 있지만 응답이 클라이언트에 닿지 않습니다. 타임아웃 이후 클라이언트는 같은 호출을 다시 보냅니다. 클라이언트 입장에서는 동일한 침묵과 양립하는 두 가지 역사가 남습니다. 첫 호출이 실행 전에 사라졌거나, 작업은 끝났는데 응답만 사라진 경우입니다.
따라서 재전송은 필요하면서도 위험합니다. 서버가 이를 새 요청으로 다루면 부작용이 반복될 수 있습니다. 비슷한 호출을 모두 오래된 것으로 다루면 정당한 이후 요청을 억제할 수도 있습니다. 타임아웃 안에 이 둘을 가려주는 사실은 존재하지 않습니다.
이 한계는 원래 원격 프로시저 은유가 숨기지 않은 것입니다. 1988년 4월에 발표된RFC 1050은 RPC가 신뢰성을 제공하려 하지 않는다고 명시했습니다. 두 달 뒤 이를 대체한RFC 1057도 그 불편한 규칙을 유지했습니다. UDP에서는 응답이 없으면 실행 횟수에 대해 아무 것도 알려주지 않으며, 응답이 있으면 적어도 한 번의 실행을 확인해 준다는 것입니다.
이 불확실성은 메시지 전달과 확정된 효과 사이에 놓여 있습니다. 네트워크는 호출을 잃을 수도, 응답을 잃을 수도, 서버가 상태를 바꾼 뒤 끊길 수도 있습니다. 클라이언트는 세 경우 모두에서 같은 타임아웃만 관찰합니다.
XID는 더 작은 질문에 답했다
버전 2 RPC 메시지는 모두 부호 없는 32비트 트랜잭션 식별자, 즉 XID로 시작합니다. 응답은 자신을 유발한 호출의 XID를 담습니다. 여러 호출이 동시에 진행 중이라면 클라이언트는 돌아오는 각 결과를 올바른 로컬 대기자에 연결할 수 있습니다.
그러나 이는 연대기가 아니라 상호 대조입니다.RFC 5531은 서비스 측이 재전송 감지 시 XID를 등식으로 비교할 수 있지만, 이 필드를 시퀀스 번호로 다룰 수는 없다고 규정합니다. 이 값에는 표준 서버 에포크, 실행 카운터, 만료 규칙, 부작용의 식별 정보가 전혀 담기지 않습니다.
기본 프로토콜은 재사용도 조건부로 만들었습니다. 클라이언트 애플리케이션은 재전송 시 이전 XID를 재사용할 수 있고, 서버는 그 값을 기억해 두고 일치하는 호출을 다시 실행하지 않을 수 있습니다. 이 두 선택이 모이면 어느 정도의 execute-at-most-once 동작이 만들어질 수 있습니다. 그러나 어느 쪽도 정수 자체가 제공하는 것이 아닙니다.
클라이언트가 재시도에 새 XID를 부여하면 등식이 두 사본을 연결할 수 없습니다. 서버가 옛 XID를 잊었다면 등식은 아무것도 찾지 못합니다. 어떤 값이 다른 문맥에서 재사용되면, 요청자·프로시저·수명 없는 등식은 엉뚱한 사건들을 연결할 수 있습니다. 이 식별자가 유용한 것은 로컬 시스템이 그 범위를 부여하기 때문입니다.
일치하는 응답이 실행 장부를 보증하지 않았다
RPC는 인증 필드를 XID와 분리해 두었습니다. 응답 번호는 승인된 프로시저가 정확히 한 번 커밋했음을 증명하는 서명, 자격 증명, 증거가 결코 아니었습니다. 인증된 메시지조차 누가 그 교환을 보호했는지를 답할 뿐, 애플리케이션 상태가 몇 번 바뀌었는지를 자동으로 답하지는 않습니다.
전송 계층 구분도 들리는 것보다 좁았습니다. RFC1831과 RFC 5531은 신뢰성 있는 전송 위의 응답이 그 모델 안에서 exactly-once 추론을 허용한다고 말하지만, 곧바로 어려운 경우를 남겨 둡니다. 응답이 오지 않으면 호출자는 프로시저가 실행되지 않았다고 가정할 수 없으며, 서버 장애 이후에도 타임아웃과 재연결은 여전히 필요합니다.
신뢰성은 하나의 연결 위에서 바이트를 순서대로 전달할 수 있습니다. 그러나 크래시로 사라진 프로세스와 함께 사라진 애플리케이션 역사를 되살릴 수 없고, 재연결 이후의 재시도가 끊기기 전에 커밋된 작업을 가리키는지도 판단할 수 없습니다. 이 경계는 복구 문맥이 바뀔 때마다 다시 나타납니다.
NFS는 이 모호성을 운영 문제로 만들었다
초기 네트워크 파일 시스템은 의도적으로 무상태 서버를 선호했습니다.RFC 1094는 그 매력을 설명합니다. 크래시나 네트워크 중단 이후 클라이언트는 서버와 프로토콜 상태를 다시 세우는 대신 계속 재시도할 수 있다는 것입니다.
이를 실현 가능하게 하기 위해 NFS는 가능한 한 연산을 멱등으로 만들었습니다. 같은 범위에 대한 읽기나 쓰기를 반복하면 종종 같은 의도된 효과를 낼 수 있습니다. 그러나 사양은 여러 연산을 비멱등일 가능성이 있는 것으로 표시했습니다. 이름은 한 번만 지워질 수 있습니다. 처음에 성공한 이름 변경은 두 번째 시도에서 소스 이름이 이미 옮겨졌기 때문에 실패할 수 있습니다.
멱등성은 무지의 비용을 줄였을 뿐 무지를 제거하지 않았습니다. 이후RFC 1813은 NFSv3의 더 날카로운 예를 제시합니다. truncate에 가까운 비멱등 요청을 반복하면 첫 사본 이후에 수행된 쓰기를 파괴할 수 있습니다. 연결 지향 전송도 끊김과 자동 재연결 이후의 중복 처리를 제거할 수 없습니다.
이제 “같은 요청”이라는 표현에 운영적 정의가 필요해졌습니다. 두 패킷이 서로 닮았다는 것만으로는 부족합니다. 서버는 어느 요청자의, 어느 RPC 프로시저의, 어느 XID의, 어느 보관된 결과가 함께 속하는지 알아야 했습니다.
중복 캐시는 영원이 아니라 창을 샀다
많은 NFSv3 서버는 중복 요청 캐시를 유지했습니다. 호출을 완료한 뒤 서버는 그 완료 상태를 기억합니다. 항목이 남아 있는 동안 같은 요청이 돌아오면 서버는 연산을 다시 적용하는 대신 저장된 답을 보냅니다.
이는 단순한 성능 캐시가 아니라 실질적인 정확성 메커니즘이었습니다. 판단을 클라이언트의 추측에서 실행 경계가 보유한 근거로 옮긴 것입니다. 그러나 RFC 1813은 한계를 명확히 했습니다. 전형적인 캐시 상태는 RAM에 살다가 크래시와 함께 사라집니다. 유한한 캐시는 클라이언트가 원래 응답을 받기 전에 긴 파티션 동안 항목을 축출할 수 있습니다. 그러면 이후의 중복은 새 요청처럼 보입니다.
XID가 XID로서 실패한 것이 아니었습니다. 보관된 문맥이 만료된 것입니다. 이 숫자를 멱등성 키라고 부르면 지배적 사실들, 즉 첫 결과를 누가 저장했는지, 조회 범위가 어떻게 정해졌는지, 항목이 얼마나 살아 남았는지, 페일오버가 어떻게 처리되었는지를 감추게 됩니다.
NFSv3는 때때로 더 강한 증거를 연산 자체에 담았습니다. 배타적 CREATE는 생성된 객체에 연결된 검증자를 사용했는데, 휘발성 중복 캐시 메모리로는 요구되는 의미론이 충분하지 않았기 때문입니다. 이 추가 증거는 그 연산에만 국한된 것이었고, 모든 RPC XID를 영속적 역사로 바꾸지는 않았습니다.
유한한 슬롯이 더 강한 기억을 감당할 수 있게 했다
NFSv4.1은 문제의 형태를 바꿨습니다.RFC 5661이 세션을 도입했고, 현재 사양인RFC 8881은 각 슬롯에 시퀀스 ID와 캐시된 응답을 두는 유한한 슬롯 테이블을 기술합니다.
요청자는 미사용 슬롯을 선택합니다. 그 슬롯의 첫 요청은 정의된 시퀀스 값을 담고, 이후 사용마다 그 값이 진전됩니다. 재시도는 현재 시퀀스를 반복합니다. 응답자는 이를 근거로 세 가지 경우를 로컬에서 구분할 수 있습니다. 다음 새 요청, 현재 요청의 재전송, 잘못 정렬된 값입니다. 완료된 재시도는 또 다른 실행 대신 캐시된 응답을 받습니다.
슬롯은 시퀀스만큼 중요합니다. 슬롯은 미결 요청 수, 즉 서버가 기억해야 할 응답 수를 한정합니다. 새 시퀀스는 요청자가 오래된 결과를 지나쳤다는 뜻이기도 하여, 그 슬롯의 캐시 항목을 교체할 수 있게 합니다.
RFC 8881은 이를 비구조화된 XID 공간과 대조합니다. XID는 응답자에게 불투명하며 호출은 순서 없이 완료될 수 있습니다. 가능한 모든 32비트 결과를 완전히 보관하려면 비현실적인 역사가 필요합니다. 협상된 슬롯 테이블은 무한한 명명 문제를 유한한 보관 의무로 바꿉니다.
exactly once에도 여전히 영속성 경계가 있었다
NFSv4.1은 실패를 폐지하지 않았습니다. 그 exactly-once 의미론은 보장이 걸린 실패들 사이에서 응답 캐시와 복구 상태가 살아남는 데 의존합니다. RFC 8881은 재시작 전반의 완전한 EOS가 영속적 캐시 상태를 필요로 한다고 밝힙니다. 휘발성 구현은 여전히 평범한 재시도 처리를 개선하지만, 잃어버린 기록에 대해 증언할 수는 없습니다.
세션이 XID를 폐지하지도 않았습니다. RPC 계층은 SEQUENCE 경로를 따르지 않는 교환을 포함해 응답과 호출을 맞추는 데 여전히 XID를 사용합니다. 새 메커니즘은 대체 식별자를 만능 권위로 승격시키지 않았습니다. 애플리케이션이 더 강한 결과를 요구하는 곳에 더 좁은 상태 기계를 추가한 것입니다.
이것이 바로 역사적 진행입니다. 숫자 하나가 메시지를 대조했고, 캐시가 등식에 단기적 결과를 부여했으며, 유한한 세션이 더 강한 기억의 비용과 수명을 명시했습니다. 각 계층은 서로 다른 질문에 답했습니다.
숫자 하나가 결코 승인하지 않은 것들
XID는 두 호출의 인수가 동일하다는 것, 같은 인증된 주체에게서 왔다는 것, 서버가 같은 부팅 에포크에 머물렀다는 것을 증명하지 않습니다. 캐시 히트는 영속적 커밋을 증명하지 않습니다. 캐시 미스는 요청이 새 것임을 증명하지 않습니다. 멱등해 보이는 연산도 모든 순서에서 안전하지 않습니다. RFC 8881은 같은 쓰기를 반복하는 것은 보통 같은 효과를 내지만 더 오래된 지연된 쓰기가 이후 쓰기를 덮어쓸 수 있음을 보여줍니다.
올바른 주장은 더 작습니다. XID는 동작 중인 양단점에게 공유 비교 토큰을 줍니다. 한 번만 실행된다는 보장은 실행자가 토큰과 작업, 결과, 복구 경계를 연결할 범위화된 상태를 충분히 유지할 때에만 나타납니다.
출처와 근거의 한계
- RFC 1050은 1988년 4월의 RPC 버전 2 사양을 기록합니다.
- RFC 1057은 그 1988년 6월 후속 사양과 비신뢰 전송에서의 실행 한계를 기록합니다.
- RFC 1831은 RPC 모델을 이후 표준 계열로 이어갑니다.
- RFC 5531은 현재 표준 트랙 RPC 버전 2 계약을 규정합니다.
- RFC 1094는 초기 NFS의 무상태 서버 목표를 설명합니다.
- RFC 1813은 NFSv3의 재시도 위험과 중복 요청 캐시의 한계를 문서화합니다.
- RFC 5661은 NFSv4.1 세션과 그 슬롯 체계를 도입했습니다.
- RFC 8881은 응답 캐시와 영속성 조건을 포함한 현재 NFSv4.1 기술을 담고 있습니다.
이 문서들은 프로토콜을 정의하고 설계 경험을 보고합니다. 현재 캐시 크기, 영속성 정책, 배포 비율 또는 구현 적합성을 측정하지는 않습니다.
회원 브리핑
프로필 심층 컨텍스트
올바른 멤버십 등급으로 로그인하면 전체 브리핑과 출처 노트를 볼 수 있습니다.
Strategic Circle 전용
Strategic Circle
모든 독자에게 공개됩니다. 가입 후 로그인하면 프로필 브리핑를 열람할 수 있습니다.
Strategic Circle 가입하기Leadership Alliance 전용
Leadership Alliance
자격을 갖춘 IP 자산 소유자 및 운영진을 위한 콘텐츠입니다. 로그인하면 Leadership Alliance 브리핑을 열람할 수 있습니다.
Leadership Alliance 가입하기





