요약

  • Argus에서 가디언(guardian)은 프로세스와 객체, 복구 책임을 하나로 감쌌고, 원자적 액션은 참여하는 복구 가능한 객체 변경을 직렬화 가능하고 전부 아니면 전무 방식으로 만들었습니다.
  • 커밋은 외부 장치, 사람의 워크플로 또는 관리되지 않는 입출력이 완료되었음을 증명하지 않습니다. 핸들러 호출 뒤에 있는 사람을 식별하지도, 더 넓은 비즈니스 불변 조건을 보증하지도 않습니다.

초록색 커밋 표시등과 침묵하는 기계

영속적인 제어 객체를 갱신한 다음, Argus 세계 밖의 장비에게 움직이라고 요청하는 핸들러를 상상해 보십시오. 탑액션(topaction)은 깨끗한 결정에 도달합니다. 참여하는 모든 가디언이 동의합니다. 안정적인 객체 버전이 기록됩니다. 응답이 돌아옵니다.

그런데 장비는 그대로 멈춰 있습니다.

이 장면의 어떤 것도 트랜잭션 결과와 모순되지 않습니다. Argus는 자신의 액션에 등록된 복구 가능한 객체에 대해서는 강력한 주장을 할 수 있지만, 그 밖의 관리되지 않는 장치에 대해서는 아무런 주장도 하지 않습니다. ‘커밋’이라는 말이 최종처럼 들리기 때문에 이 구분은 쉽게 흐려집니다. 바버라 리스코프(Barbara Liskov)의 Argus 연구에서 최종성은 분위기나 기업 전반의 약속이 아니었습니다. 그것은 언어와 런타임이 갖는 신중하게 한정된 속성이었습니다.

1983년 논문Guardians and Actions은 리스코프와 로버트 샤이플러(Robert Scheifler)가 쓴 것으로, 두 추상화를 결합했습니다. 가디언은 어떤 노드에서 분산 프로그램에 속한 자원과 프로세스를 모았고, 액션은 직렬된 것처럼 보여야 하며 함께 반영되거나 관련 복구 가능 상태를 원래대로 두어야 하는 연산들을 모았습니다. 이 결합은 실패 처리를 흩어진 애플리케이션 관례에서 프로그래머가 추론할 수 있는 시스템으로 옮겼습니다.

또한 이것은 증거의 경계를 그었습니다. 커밋은 참여자 집합 안에서만 권위 있었고, 그 집합 밖에서는 다른 영수증이 필요했습니다.

가디언은 복구 도메인을 담당했을 뿐, 세계 전체를 담당하지 않았다

가디언은 하나의 프로세스 너머의 수명을 지닌 모듈과 비슷했습니다. 객체를 보유하고, 프로세스를 실행하고, 다른 가디언이 호출할 수 있는 핸들러를 내보낼 수 있었습니다. 복구 가능한 상태는 노드 장애를 견딜 수 있었고, 휘발성 상태는 복구 후 다시 구성되었습니다. 덕분에 가디언은 어떤 데이터를 누가 복구하는가를 명시하기에 자연스러운 자리가 되었습니다.

‘가디언’이라는 단어는 현대 독자를 보편적 보안 모니터의 상상으로 유혹할 수 있습니다. 그것은 너무 넓은 해석입니다. 이 추상화는 프로그램의 자원과 복구 작업을 캡슐화했을 뿐, 조직이 건드리는 모든 파일, 장치, 사람, 서비스를 자동으로 감싸지 않았습니다.

이 구분은 Argus 자신의 저장소 모델에도 나타납니다. 안정 변수(stable variable)는 복원력 있는 객체를 복구할 수 있는 루트였습니다. 탑액션이 커밋하기 전에는 수정된 안정 객체의 새 상태가 안정 저장소에 도달해야 했습니다. 반면 휘발성 변수는 복구 후 다시 초기화되었습니다. 안정 변수가 복원력 없는 무언가를 가리키게 만드는 것만으로는 그 참조 대상이 내구성 있는 트랜잭션 상태가 되지 않았습니다. 객체 타입과 복구 구현이 여전히 중요했습니다.

이것은 “Argus가 분산 프로그램을 신뢰할 수 있게 만들었다”는 주장보다 더 정확합니다. Argus는 정의된 실패 가정 아래에서 정의된 상태 클래스를 복구 가능하게 만들었습니다. 실제 일을 한 것은 그 정의였습니다.

핸들러 호출은 액션 트리를 만들었다

Argus에서 원격 작업은 트랜잭션으로부터 보이지 않는 우회가 아니었습니다. 다른 가디언의 핸들러를 호출하면 액션 트리에 구조가 생겼습니다. 호출자는 콜 액션을 갖고, 대상은 액티베이션 액션을 실행했습니다. 인자와 결과는 값으로 가디언 경계를 넘었고, 반환 경로는 그 서브액션들이 어떻게 끝나는지 결정하는 데 참여했습니다.

평범한 반환 또는 시그널은 보통 핸들러 액티베이션을 커밋했습니다.abort return이나abort signal은 어보트로 끝냈습니다. 이 디테일이 중요한 이유는 예외가 자동으로 트랜잭션 실패의 동의어가 아니기 때문입니다. 프로그램이 예외를 상위 작업을 커밋하지 않을 이유로 간주한다면, 그 조건을 적절한 액션 경계에서 잡아 처리해야 했습니다.

서브액션은 프로그래머에게 포함(containment)을 제공했습니다. 서브액션은 부모를 반드시 파괴하지 않으면서 어보트될 수 있었습니다. 그러나 서브액션이 커밋하면 그 잠정 버전과 잠금은 상위로 이동했습니다. 그 작업은 부모에게, 궁극적으로는 탑액션에 조건부로 묶여 있었습니다. 따라서 “서브액션이 커밋했다”는 것은 “호출자와 무관하게 영구적이다”를 뜻하지 않았습니다. 그 가지가 성공적으로 자신의 결과를 부모 액션에 결합했다는 뜻이었습니다.

탑액션은 루트였습니다. 탑액션이 커밋할 때 시스템은 참여하는 가디언들을 조율했고, 분산 결정이 필요한 곳에서는 2단계 커밋을 사용했으며, 액션과 커밋된 자손들이 수정한 안정 객체의 새 버전을 기록했습니다. 탑액션이 어보트하면 트랜잭션으로 관리되는 상태는 이전 버전으로 돌아갔습니다.

이 계층 구조가 과장된 증거에 대한 첫 번째 방어선입니다. 성공한 핸들러 액티베이션은 아직 탑액션 커밋이 아닙니다. 커밋된 서브액션은 독립적으로 내구적이지 않습니다. 탑액션 커밋은 비참여자에 대한 증명이 아닙니다.

고아(오팬)는 응답이 이야기 전부가 아니었음을 보여주었다

분산 호출은 모호하게 실패합니다. 다른 곳에서 작업이 진행되는 동안 노드가 사라질 수 있습니다. 호출자는 원격 액티베이션이 멈췄는지 알지 못한 채 반환 경로를 잃을 수 있습니다. Argus는 조상이 죽었거나 결과를 더 이상 전달할 수 없는 액션을 고아(오phan)라고 불렀습니다.

시스템의 고아 처리 장치는 단순히 더 강한 언어로 포장된 타임아웃이 아니었습니다. 그것은 고아가 결국 어보트되도록 하고, 결정적으로, 합법적 계보가 사라진 뒤 방황하면서도 일관성 없는 원자적 데이터를 관찰하지 않도록 하는 것을 목표로 했습니다. 매뉴얼은 또한 불편한 운영 사실을 기록합니다. 호출자 측의unavailable결과는 고아로서 여전히 실행 중인 원격 활동과 공존할 수 있다는 것입니다.

따라서 흔한 두 결론은 안전하지 않습니다. 첫째, 결과를 받지 못했다고 아무것도 실행되지 않았음을 증명하지는 않습니다. 둘째, 액션 시스템 안의 강제 어보트가 관리되지 않는 외부 효과가 철회되었음을 증명하지는 않습니다. 고아 보장은 액션들이 원자적 데이터를 통해 통신하는 것에 의존합니다. 모터 펄스, 인쇄된 페이지, 이미 외부 서버에 넘겨진 이메일, 사람의 지시는 Argus 조상이 사라졌다고 해서 롤백되지 않습니다.

Argus는 자신이 제어할 수 있는 상태를 정의함으로써 어려운 문제를 해결했습니다. 나머지 세계가 트랜잭션이라고 가장함으로써 다른 문제를 해결한 것은 아닙니다.

오픈 네스팅은 의도된 탈출구였다

평범하게 커밋된 서브액션은 부모에 조건부로 묶여 있었습니다. Argus는 다른 구성 요소도 제공했습니다. 바로 중첩 탑액션(nested topaction)입니다. 이것이 오픈 네스팅(open nesting)입니다. 중첩 탑액션은 독립적으로 커밋할 수 있었고, 자신을 감싼 액션이 나중에 어보트하더라도 생존했습니다.

이 힘은, 예를 들어 의도적으로 내구성 있는 조율 기록처럼 남아 있어야 하는 부수 효과에 유용했지만 증명을 바꾸어 놓았습니다. 프로그래머는 그 독립 효과가 안전하고 부모보다 앞서 직렬화되었음을 스스로 보장해야 했습니다. 부모가 나중에 실패하더라도, 중첩 탑액션은 원자성에서 새어 나온 수수께끼 같은 누출이 아니라 부모의 롤백 도메인에 대한 명시적으로 선택된 예외였습니다.

현대 시스템은 아웃박스, 사가 스텝, 독립 감사 기록 같은 이름으로 이 패턴을 다시 발견하곤 합니다. 역사적 어휘보다 중요한 것은 규율입니다. 독립적으로 커밋된 효과는 그렇게 식별되어야 합니다. 부모 작업 전체가 잔여물 없이 롤백되었다고 주장하는 보고서에 몰래 섞여서는 안 됩니다.

커밋은 상태를 확정했을 뿐, 신원이나 목적을 확정하지 않았다

Argus 액션 식별자는 동시성 제어와 복구를 위해 작업을 연결했습니다. 그것은 사람 주체를 인증하지 않았습니다. 핸들러는 인자, 결과, 액션 계보를 알 수 있었지만 어떤 직원, 고객, 임원이 비즈니스 명령을 내렸는지는 알지 못했습니다.

마찬가지로 직렬화 가능성은 목적 제한이 아닙니다. 두 요청은 객체 인터페이스에서 똑같이 유효할 수 있지만, 승인된 변경 티켓은 하나만 가질 수 있습니다. 전부 아니면 전무 방식의 갱신은 내부 객체 불변 조건을 지키면서 결제 네트워크, 물리적 프로세스, 조직에 걸친 규칙을 위반할 수 있습니다. 이것들은 액션 모델에 대한 비판이 아닙니다. 모델이 답하도록 설계된 질문에만 질문하라는 요령일 뿐입니다.

따라서 올바른 운영 기록은 계층을 갖습니다. Argus식 트랜잭션 기록은 어떤 가디언과 복구 가능한 객체가 참여했는지, 서브액션이 어떻게 끝났는지, 커밋 결정이 무엇이었는지, 무엇이 안정 저장소에 도달했는지를 말합니다. 신원 기록은 어떤 실행 주체가, 필요하다면 어떤 사람이 작업을 시작하거나 승인했는지 말합니다. 외부 영수증은 다른 서비스, 장치 또는 사람의 프로세스가 완료되었는지 말합니다. 더 넓은 불변 조건은 그 조건의 모든 관련 도메인에 걸친 관찰을 필요로 합니다.

공로의 경계도 중요하다

리스코프가 자연스러운 입구입니다. 그녀가 연구 프로그램을 이끌었고 성숙한 1988년 개관 논문을 썼기 때문입니다. 그러나 Argus는 집단적 작업이었습니다.Guardians and Actions는 바버라 리스코프와 로버트 샤이플러가 썼으며 Argus 설계 그룹, 특히 모리스 헤를리히(Maurice Herlihy), 폴 존슨(Paul Johnson), 윌리엄 와이얼(William Weihl)에 감사를 표합니다. 1987년 참조 매뉴얼에는 리스코프, 마크 데이(Mark Day), 헤를리히, 존슨, 게리 리븐스(Gary Leavens), 샤이플러, 와이얼이 이름을 올렸습니다. 구현 논문에는 리스코프, 존슨, 샤이플러와 함께 도러시 커티스(Dorothy Curtis)가 추가됩니다.

이 이름들을 지키는 것은 허례허식이 아닙니다. 언어 아이디어와 복구 프로토콜, 매뉴얼, 동작하는 구현 사이의 경계는 기술사의 일부입니다. 커밋이 세계 전체에 대한 주장을 흡수해서는 안 되듯이, 한 사람의 유명한 이름이 시스템 전체의 작업을 흡수해서는 안 됩니다.

출처