결함 허용 시스템 설계를 위한 패턴 소개

시스템의 일부가 고장 나더라도 다운이 허용되지 않는 시스템이 있다. 이런 성격을 갖는 시스템을 “내결함성” 또는 “결함 허용” 시스템(Fault tolerant system)이라고 한다. 처음부터 결함을 갖고 있었거나, 사용 중에 발생한 결함에도, 시스템 명세서에 명시된 기능을 제공하도록 만들어진 “고 신뢰성” 시스템이다. 이런 시스템을 만들기 위해서 아키텍쳐 관점에서 고려해야 할 사항은 무엇일까? 이런 시스템 설계에 적용될 수 있는 설계 Pattern은 무엇일까? Patterns for fault tolerant software책에서 제시하는 설계 Pattern들을 소개하고자 한다.

 

내 결함성은 결함허용 시스템에만 적용되는 기능이 아니다. 다양한 시스템에 그들의 완성도를 높이기 위해 적용될 수 있는 방법이다. 어떤 시스템이나 결함을 가질 수 있고, 운행 도중 결함이 실행되어 오류가 발생할 수 있다. 이런 오류가 특정 서비스를 실행시키는데 영향을 준다면 서비스 장애가 발생할 것이다. 이번 칼럼에서는 결함이 실행되어 오류가 발생하더라도 오류의 파급 효과를 줄이거나 제거해 장애가 발생하지 않는 방법을 소개할 것이다. 칼럼을 읽고 우리가 만드는 시스템에 내 결함 기능을 추가하여 시스템의 완성도를 높여 보자.

 

대표적인 결함 허용 시스템

고장에 강해, 단 한 순간의 시스템 다운도 허용될 수 없는 온라인 시스템, 특히 높은 신뢰성이 요구되는 환경인 은행이나 e-Commerce 시스템, 좌석예약시스템 등 실시간 프로세스 제어시스템, 병원이나 우주 항해 시스템과 같이 컴퓨터의 고장이 인명 손실에 관계되는 시스템, 년 중 보수작업이 거의 불가능한 상황에서 사용되는 시스템, 고장에 의해 막대한 경제적 손실을 야기하는 업무 환경 등에 사용되는 원전 시스템 등을 들 수 있다.

 

장애 발생 과정과 결함 허용 기술

결함 허용이란 오류가 발생한 것을 감지하고, 오류가 다른 영역에 영향을 미치기 전에, 미리 정의된 오류 복구나 완화 정책을 통해, 오류가 장애로 이어지는 것을 막고, 오류의 원인인 결함을 발견해, 결함을 치료하여 오류의 재발을 막는 기술이다.

용어장애 발생 과정

결함 허용 기술결함 허용 방법

 

장애

장애란 명세서대로 동작하지 않는 시스템의 동작을 나타내고 예는 아래와 같다.

  • 시스템이 멈추지 말아야 할 때, 문제가 생겨 멈춰버렸다.
  • 시스템이 잘못된 결과를 도출했다.
  • 시스템이 서비스되지 않는다.
  • 시스템이 사용자의 조작에 반응을 하지 않는다.

오류

오류는 장애를 일으킬 수 있는 올바르지 않은 시스템 동작으로 예는 아래와 같다.

  • 시간 조건 또는 경쟁 상태(race condition)
  • 무한 반복
  • 프로토콜 오류
  • 데이터 불일치
  • 오버로드 조건을 제어하는데 실패
  • 잘못된 전송 또는 기록

결함

결함은 오류를 발생시키는 시스템의 결함을 말한다. 결함이 예측되면, 오류가 생길 수 있는 시스템의 부분을 파악할 수 있고, 오류에 대한 파급 효과를 줄이거나 완화하는 처리를 통해 장애를 발생시키지 않을 수 있다. 결함이 발생하는 원인은 다음과 같다

  • 소프트웨어 설계자와 개발자가 부정확한 요구사항을 전달받았을 때 발생하는 오류
  • 시스템 요구사항을 소프트웨어 설계로 옮기는 과정에서 발생하는 설계 오류
  • 설계를 코드로 옮기는 과정에서 발생하는 코딩 오류

 

시스템 결함 허용 정도 측정 기준

안정성과 가용성은 결함 허용 시스템의 결함허용 측정 기준이며, 결함 허용 시스템의 기능 사항 명세서가 가져야 할 요구사항 이다.

안정성

시스템이 특정 기간 동안 장애가 없는 정도를 나타내며, MTTF(Mean Time To Failure)값을 지표로 삼는다. MTTF는 아래 그림에서와 같이 시스템 수리 후 혹은 처음 시작해서 고장이 날 때까지의 시간을 나타낸다.

MTTFMTTF(Mean Time To Failure)

MTTF시간이 길수록 장애 없이 시스템이 사용자에게 서비스를 제공하는 시간이 길므로, 안정성은 높다

시스템 명세서에 들어가는 비행기의 안정성 요구사항의 예제이다.

시카고에서 로스앤젤레스로 가는 비행기 경우 MTTF가 5보다 커야 한다 이는 시카고에서 로스앤젤레스까지 비행 거리가 5이고 이 시간에는 장애가 발생하면 안되기 때문이다.

 

가용성

시스템이 기능 수행할 수 있는 기간이 전체 가동 기간의 몇 퍼센트인지 나타내며, MTTF(Mean Time To Failure)값과 MTTR(Mean Time to Repair)값을 지표로 삼는다. MTTR은 아래 그림에서와 같이 시스템 고장 후 수리가 되기까지의 시간을 나타낸다.

MTTF2MTTF(Mean Time To Failure), MTTR(Mean Time To Repair)

MTTF시간이 길수록 장애 없이 시스템이 서비스 제공하는 시간이 길므로, 가용성은 높다. MTTR시간이 길수록 수리시간이 길어 그만큼 시스템이 서비스를 제공하는 시간은 짧아지므로, 가용성은 낮다.

시스템 명세서에 들어가는 비행기의 가용성 요구사항의 예제이다.

4ESS™ 스위치는 40년간 고장시간을 2시간만 허용한다. 즉 가용할 수 없는 시간이 연간 3분이어야 함을 의미한다.

 

예제로 보는 결함 허용 기능

데이터 방송 TV에 결함 허용 기능을 넣는 예를 들어 보자. 데이터 방송 TV는 A/V와 함께 게임이나 노래방 같은 애플리케이션을 실행하여 사용자에게 보여주는 TV이다.

TV의 Thread 관리 코드에 결함이 있는 경우를 생각해 보자

사용자가 게임을 하다 노래방을 키는 경우, TV 소프트웨어는 아래와 같이 동작한다.

application 실행 sequence어플리케이션의 실행 단계

TV의 Thread 관리 모듈이 결함을 가지지 않는다면 아래와 같이 동작할 것이다.

application 메모리와 스레드 상태결함을 가지지 않는 Thread 관리 모듈

 

그러나 결함이 있는 경우, 결함을 가진 Thread 관리 모듈은 애플리케이션 종료 시, 애플리케이션이 사용하던 Thread 중 일부를 정리하지 못해 Zombie Thread로 남게 된다. Zombie Thread는 어플리케이션이 사용하던 비디오 메모리를 참조하고 있어, 새 어플리케이션에 의해 사용되지 못하게 된다.

application 메모리와 스레드 상태2결함을 가지는 스레드 관리 모듈

 

사용자가 빈번하게 게임과 노래방 어플리케이션을 실행했다 종료하는 경우, Zombie Thread는 계속 쌓이고, 새 어플리케이션이 사용할 수 있는 메모리 계속 줄어든다. 어느 순간, TV는 어플리케이션 구동을 위해 필요한 메모리를 할당할 수 없게 되고, 정상적으로 기능을 수행하지 못하게 된다

TV에 결함 허용 기능을 넣은 그림이다

TV의 결함 허용 기능TV의 결함 허용 기능 소프트웨어 구조

 

한 부분씩 자세히 보자

오류 감지 & 완화

장애가 발생할 수 있는 주기에 따라 결함 허용 기능을 추가할 수 있다. 이 예제에서 주기는 어플리케이션 실행 주기이다. 그러므로 어플리케이션 종료 시, 정리 안된 Thread가 있는지 검사하는 기능을 넣어 오류를 감지한다.

정리 안된 Thread를 정리하여 오류를 완화한다. Thread를 정리되면, 주기적으로 실행되는 TV 시스템의 GC는 Thread가 사용하고 있던 객체들의 finalize 코드를 부르게 된다. 그리고 finalize 코드는 heap외에 잡힌 native 메모리나 static 객체 등을 정리한다.

그러나 GC의 수행주기는 일정하지 않다. 어플리케이션 종료 시 수행될 수도 있고, 새로운 어플리케이션 실행 시, 수행될 수도 있다. 어플리케이션 종료 시, 어플리케이션 실행 전 상태로 메모리가 정리될 수 없으므로 이 방법은 복구가 아니라 완화이다.

 

오류 감지 & 복구

GC에 의존해 메모리를 정리하지 않고, 메모리 오류를 복구할 수 있는 코드를 추가할 수 있다. 어플리케이션이 사용하는 메모리 테이블을 만들어 관리하고, 어플리케이션 종료 시, Thread 정리와 함께 메모리도 명시적으로 정리해 준다. 결과 어플리케이션 종료 시, 어플리케이션에서 사용하던 Thread와 메모리 리소스는 어플리케이션 실행 전의 상태를 가지는 오류 완화이다.

 

결함 제거

완화와 복구 기능이 추가되면 장애를 막아 사용자에게 서비스는 제공할 수 있으나, 오류 발생

가능성은 여전히 있다. Fault tolerant system 저자는 이 문제를 해결하는 방법으로 결함 제거 기능을 소개한다. 결함이 있는 소프트웨어의 단위 모듈이 실행시간에도 업데이트 될 수 있도록 소프트웨어 구조를 설계하여, 완화와 복구 과정을 마친 후에, 오류의 발생 가능성까지 없애도록 하는 기능이다.

 

결함 허용 시스템을 위한 설계 Pattern 소개

결함 허용 시스템의 Architecture 설계 시 고려해야 할 사항들

아키텍쳐 결함 허용 시스템을 위한 아키텍처 패턴 언어 지도

결함 허용 시스템을 설계하기 위해, 초기 단계에 고려해야 하는 사항들에 대한 Pattern Map이다.

각각에 대해 살펴보자

  • Units of Mitigation (결함 허용 기능 단위 결정하기)

“결함 허용의 단위” 와 “오류 모니터링의 overhead” 는 tradeoff 관계를 가진다. 단위가 커질수록 오류 발생에 대한 모니터링 overhead가 커지기 때문이다. 오류 발생 빈도와 오류에 대한 영향력을 판단하여 atomic하게 나뉠 수 있는 단위로 결정해야 한다. 단위 결정의 기준으로는 n-tier architectural 구조를 갖는 시스템에서의 각 tier, 예를 들어 시스템의 미들웨어 혹은 어플리케이션 등을 예를 들 수 있다. 또 다른 기준은 기능이나 resource(CPU, Memory)의 사용 단위, 위 데이터 방송 TV 예제에서 어플리케이션을 예로 들었는데, 이것이 Memory의 사용 단위로 단위를 정한 예이다.

정해진 결함 허용 단위에 따라 복구나 완화 메커니즘을 포함해야 한다.

  • Redundancy, Redundancy Blocks(중복 기능 설계)

복구나 완화하는 시간을 줄이는 것이 시스템의 가용 시간을 높이는 가장 좋은 방법이다. 복구나 완화하는 동안 기능 구현을 위한 대체 코드 (n version programming)혹은 중복 구성된 하드웨어를 사용하여 기능을 수행할 수 있다면, 시스템의 가용 시간은 늘어날 것이다.

  • Software update(소프트웨어 업데이트하기)

복구와 완화 후, 결함을 치료하여 오류를 방지하는 방법이다. 1번에서 정한 결함 허용 단위대로 소프트웨어가 업데이트 될 수 있어야 한다. 이 단위로 결함 치료 루틴을 포함할 수 있도록 소프트웨어 구조가 정해져야 한다. 예를 들면, 각 단위를 library처럼 정해진 규격에 따라 구현하거나, 범용 OS의 어플리케이션 설치, lifecycle을 관리하듯 관련 규격을 정하고, 모든 단위의 기능이 그 규격에 따르도록 구현하는 것이다.

  • Correcting Audits(데이터 감사하기)

데이터가 오염되어 오류가 발생할 수 있다. Linked list, pointer가 가리키는 데이터의 type이 오염되거나, 분산되어 중복 저장된 데이터의 불일치 같은 경우를 예로 들 수 있다. 데이터를 검사하고 오류를 검출하고, 바로 복구할 수 있도록 데이터에 대한 감사 기능이 필요하다.

  • Escalation(단계적으로 확대하기)

에러 복구나 완화의 단위는 1번에서 정한 단위여야 한다. 그러나 이 단위로 복구 시행 시, 완화나 복구가 되지 못하는 경우가 있다. 이런 경우, 범위를 넓혀서 복구를 시도한다. 여러 번 시도에도 복구되지 않는 경우, 복구를 멈추고, 기능 제공의 수준을 낮춘다.

  • Someone in charge(책임자 두기)

에러나 복구 처리 과정 또한 모니터링 되어야 하고, 이 과정에 실패할 경우, 이 과정을 초기화 시키고 다른 에러나 복구 처리 과정을 진행시킬 수 있어야 한다.

  • Maintenance interface, Maximize Human interaction, Minimize Human interaction(유지보수 인터페이스 만들기, 사람 간섭 최대화하기, 사람 간섭 최소화하기)

완화나 복구를 사람이 할 수 있도록, 오류 원인 분석과 사용자 처리를 위한 인터페이스를 제공해야 한다. 사용자 인터페이스는 시스템이 기능하는데 영향을 받거나 주지 않는 보안이 보장된 부가적으로 설치된 관리자용 인터페이스여야 한다.

또한 사람의 개입은 전문가에 한해서 허용되어야 하며, 시스템이 처리하지 못하는 복합적이고 시스템 처리 불가능한 경우에 한해서 허용되어야 한다. 복구와 완화 과정이 여러 단계를 필요로 하거나, 통상적일 경우 사람은 실수를 할 수 있기 때문이다.

  • Fault Observer(결함 감시자 두기)

결함과 오류, 완화와 복구 관련된 모든 사항을 받아서 관심 있는 시스템 모듈이나 전문가에게 Report하는 Observer가 있어야 한다.

 

오류 감지 Pattern

  • System monitor(시스템 모니터 하기)

시스템 각 파트가 정상적으로 동작하는지 감시하는 파트를 두어야 한다. 정상적으로 동작하지 않을 경우, 다른 파트로 전파되지 않도록 초기화 하고, 완화나 복구 절차를 수행될 수 있도록, 다른 파트들에게 알려야 한다. 이것은 Fault Observer나, Someone In charge의 한 파트나 혹은 시스템의 독립적인 한 파트로 개발될 수 있다.

  • Heartbeat(심장 박동)

관찰 컴포넌트로부터 주기적으로 반응이 전달되도록 한다. 이 방법을 통해 시스템 모니터는 관찰 하는 컴포넌트가 잘 수행 되고 있다는 것을 알 수 있다.

 

오류 복구 Pattern

  • Data Reset(데이터 리셋 하기)

수정할 수 없는 데이터가 있을 경우, 초기값으로 리셋 하기

  • Restart(재 시작 하기)

오류 복구가 불가능 할 때, 각 모듈 단위나 시스템을 재 시작한다.

 

오류 완화 Pattern

  • Equitable resource allocation(공평한 자원 할당하기)

모든 비슷한 요청을 요청 풀(Pool)에 넣고 우선순위에 맞춰 공평하게 자원을 할당한다.

  • Fresh work before stale(새로운 일 먼저 하기)

LIFO 큐를 사용하여 새로운 요청을 가장 먼저 처리한다. 적어도 몇몇은 좋은 서비스를 받게 된다.

 

결함 제거 Pattern

  • Reintegration(재통합 하기)

미리 정해진 절차에 따라 수정된 컴포넌트를 시스템에 재통합한다.

  • Root cause analysis(근본원인 분석하기)

오류나 결함의 근본 원인을 분석할 때 왜? 라는 질문을 5번 이상 하면 근본 원인을 찾을 수 있고 수정할 수 있다.

 

참고자료

  • Patterns for Fault Tolerant Software, Robert S. Hanmer Alcatel-Lucent Naperville, IL 60566-7033
  • http://www.slideshare.net/sunheehwang39/fault-tolerant-system130629-23956274