데이터 중심 애플리케이션 설계를 독파하며 정리하는 글입니다.
요즘의 애플리케이션은 CPU의 성능보다 데이터의 양, 데이터의 복잡도, 데이터의 변화 속도가 문제이며, 필수 요소는 다음과 같다.
애플리케이션의 필요 요소
- 구동 애플리케이션이나 다른 애플리케이션에서 나중에 다시 데이터를 찾을 수 있게 데이터를 저장함 (데이터 베이스)
- 읽기 속도 향상을 위해 값비싼 수행 결과를 기억함 (캐시)
- 사용자가 키워드로 데이터를 검색하거나 다양한 방법을 통해 필터링할 수 있게 제공함 (검색 색인, search index)
- 비동기 처리를 위해 다른 프로세스로 메시지를 보냄 (스트림 처리, stream processing)
- 주기적으로 대량의 누적된 데이터를 분석 (일괄 처리, batch processing)
또한, 소프트웨어 시스템에서 중요한 세 가지 관심사는 다음과 같은데 하나씩 정리해 보자.
- 신뢰성(Reliability)
- 확장성(Scalability)
- 유지보수성(Maintainability)
# 신뢰성
소프트웨어에서 신뢰성은 무언가 잘못되더라도 지속적으로 올바르게 동작함을 의미한다.
결함(fault) : 잘못될 수 있는 일
내결함성(fault-tolerant), 탄력성(resilient) : 결함을 예측하고 대처할 수 있는 능력
장애(failure) : 사용자에게 필요한 서비스를 제공하지 못하고 시스템 전체가 멈춘 경우
내결함성과 탄력성은 모든 결함을 커버하는 것이 아니라, 특정 유형의 결함 내성에 대해서만 이야기하는 것이 타당하다.
(말장난 같지만 블랙홀이 지구를 삼켜버리는 일과 같이 말도 안 되는 일은 막을 수 없으므로)
결함과 장애는 다르다는 것을 기억하자!
또한, 이런 결함을 고의적으로 유도함으로써 내결함성 시스템을 지속적으로 훈련하는 것이 중요함 -> 테스트 코드의 중요성.
넷플릭스의 chaosmonkey가 이런 접근 방식의 테스트 도구이다.
하드웨어 결함
시스템 장애의 원인 중 대표적으로 떠오르는 것.
하드디스크 고장, 대규모 정전 사태 등
이러한 하드웨어 결함에 대비하는 방법은 구성요소에 중복을 추가하는 방법이 일반적임
디스크 : RAID 구성
서버 : 이중 전원 디바이스, 핫 스왑 가능한 CPU
데이터센터 : 건전지, 예이 전원용 디젤 발전기
생각보다 이 하드웨어 결함이 가까이 있는것이 AWS 같은 클라우드 플랫폼에서도 별도의 경고 없이 흔히 일어나며, 클라우드 플랫폼은 단일 장비 신뢰성보다 유연성과 탄력성을 우선적으로 처리하게끔 설계됨
소프트웨어 오류
말 그대로 소프트웨어단에서 일어나는 오류들이다.
- 2012년 6월 30일일 윤초 리눅스 커널 버그
- 공유 자원을 과도하게 사용하는 일부 프로세스
- 시스템의 속도가 느려져 반응이 없거나 잘못된 응답을 반환하는 서비스
이러한 결함은 예상하기 어렵고 신속한 해결책이 없다.
따라서 빈틈없는 테스트, 프로세스 격리, 모니터링 등을 해야 한다.
인적 오류
사람이 일으키는 오류로 아무리 최선의 의도를 갖고 있어도 생긴다.
대규모 인터넷 서비스에 대한 연구에 따르면 운영자의 설정 오류가 중단의 주요 원인이며, 하드웨어 결함은 10~25%에 그친다고 한다.
이러한 인적 오류로 부터 신뢰성을 지키는 방법은 다음과 같다.
- 잘 설계된 추상화, API, 관리 인터페이스 사용
- 실제 사용자에게 영향이 없는 비 프로덕션 샌드박스 제공
- 단위 테스트부터 전체 시스템 통합 테스트와 수동 테스트까지 모든 수준에서 철저하게 테스트
- 성능 지표와 오류율 같은 상세하고 명확한 모니터링 대책 마련
# 확장성
확장성은 부하가 증가해도 좋은 성능을 유지하기 위한 전략을 의미하며,
확장성을 논한다는 것은 "시스템이 특정 방식으로 커지면 이에 대처하기 위한 선택은 무엇인가?"와 "추가 부하를 다루기 위해 계산 자원을 어떻게 투입할까?" 같은 질문을 고려한다는 것이다.
부하 기술하기
무엇보다 시스템의 현재 부하를 간결하게 기술하는 것이 중요하다. (그래야 부하 성장 질문을 논의할 수 있기 때문)
이를 나타내는 숫자인 부하 매개변수(load parameter)의 예시는 다음과 같다.
- 웹 서버의 초당 요청 수
- 데이터베이스의 읽기 대 쓰기 비율
- 대화방의 동시 활성 사용자(active user)
- 캐시 적중률
- 팬 아웃(fan-out) : 트랜잭션 시스템에서 하나의 수신 요청을 처리하는데 필요한 다른 서비스의 요청 수
등이 있지만, 선택은 시스템 설계에 따라 달라진다.
성능 기술하기
시스템 부하를 기술하면 부하가 증가할 때 어떤 일이 일어나는지 다음의 두 가지 방법으로 조사가 가능해진다.
1. 부하 매개변수를 증가시키고 시스템 자원은 변경하지 않으면 어떻게 될까?
2. 부하 매개 변수를 증가시켰을 때 성능이 유지되려면 자원을 얼마나 늘려야 할까?
두 질문 모두 성능 수치가 필요하게 되며 시스템 성능은 다음과 같은 것들이 있다.
- 처리량(throughput) : 초당 처리할 수 있는 레코드 수나 일정 크기의 데이터 집합으로 작업을 수행할 때 걸리는 전체 시간
- 응답 시간(response time) : 클라이언트가 요청을 보내고 응답을 받는 사이의 시간
- 지연 시간(latency) : 요청이 처리되길 기다리는 시간, 서비스를 기다리며 휴지(latent) 상태인 시간
- 꼬리 지연 시간(tail latency) : 상위 백분위 응답 시간
여기서 응답시간은 단일 숫자가 아닌 측정 가능한 값의 분포로 생각해야 한다.
왜냐하면 특이 값(outlier)이 존재하기 때문인데, 모든 요청이 동일한 시간이 걸려야 한다고 생각하는 상황에도 백그라운드 프로세스의 컨텍스트 스위치, 네트워크 패킷 손실과 TCP 재전송, 가비지 컬렉션 휴지 등으로 인해 추가 지연이 발생할 수 있기 때문이다.
그러므로, 얼마나 많은 사용자가 지연을 경험했는지 전형적인 응답시간을 알고 싶다면 평균 응답 시간은 좋은 지표가 아니며 일반적으로 백분위(percentile)의 중앙값(median)을 사용하는 게 더 좋다.
(예를 들어 중간 응답 값이 200밀리 초면 요청의 반은 200밀리초 미만이고 나머지 반은 그보다 오래 걸린다는 뜻이므로)
꼬리 지연 시간은 서비스의 사용자 경험에 직접 영향을 주기 때문에 중요하다.
예를 들어 99.9 분위는 요청 1000개 중 1개만 영향이 있지만, 응답 시간이 느린 고객일수록 가장 많은 데이터를 갖고 있는 소중한 고객이기 때문이다.
그러나 이 꼬리 지연 시간은 통제할 수 없는 임의 이벤트에 쉽게 영향을 받기에 응답 시간을 줄이기 매우 어렵고, 최적화하는데 비용이 너무 많이 든다.
부하 대응 접근 방식
확장성과 관련된 부하 대응 접근 방식은 두 가지로 구분된다.
- 용량 확장(scaling up), 수직 확장(vertical scaling) : 장비 자체를 좀 더 강력한 장비로 이동하는 방식
- 규모 확장(scaling out), 수평 확장(horizontal scaling) : 다수의 낮은 사양의 장비에 부하를 분산하는 방식
이 중 다수의 장비에 부하를 분산하는 아키텍처를 비공유(shared-nothing) 아키텍처라고 한다.
또한, 부하 증가를 감지하면 컴퓨팅 자원을 자동으로 추가하는 시스템을 탄력적(elastic)이라고 하는데, 수동으로 확장하는 시스템이 더 간단하고 운영상 예상치 못한 일이 더 적다는 것도 인지해야겠다.
(Auto Scaling이 무적은 아니라는 것을 시사하는 것 같은데, 나 역시 이벤트가 있을 경우엔 수동으로 미리 인프라를 증설했다.)
# 유지보수성
소프트웨어 비용의 대부분은 초기 개발이 아니라 버그 수정, 시스템 운영 유지, 새로운 기능 추가 등과 같은 지속 해서 이어지는 유지보수에 들어간다.
하지만 소위 레거시 시스템을 유지보수하는 작업은 기피 대상이어서, 이 중요한 유지보수를 위해 레거시 소프트웨어를 만들지 않도록 하는 것이 중요한데,
그러기 위해서는 다음 세 가지 소프트웨어 시스템 설계 원칙을 지켜야 한다.
- 운용성(operability) : 시스템을 원활하게 운영할 수 있게 쉽게 만들기
- 단순성(simplicity) : 복잡도를 최대한 제거해 새로운 엔지니어가 시스템을 이해하기 쉽게 만들기 (사용자 인터페이스의 단순성과는 다름)
- 발전성(evolvability) : 시스템을 쉽게 변경할 수 있게 만들기 (유연성, 수정 가능성, 적응성으로도 알려짐)
앞전에 정리한 신뢰성, 확장성을 달성하기 위한 쉬운 해결책은 없으니, 그보다 이 유지보수성(운용성, 단순성, 발전성)을 염두에 두고 시스템을 생각하려 노력해야 한다.
'독서 > 데이터 중심 애플리케이션 설계' 카테고리의 다른 글
[데이터 중심 애플리케이션 설계] 저장소와 검색 (0) | 2023.01.29 |
---|---|
[데이터 중심 애플리케이션 설계] 데이터 모델과 질의 언어 (0) | 2023.01.02 |