마이크로 서비스 인 액션 6장을 읽고 정리해보았습니다.
가용성은 신뢰성의 척도가 된다.
마이크로 서비스에서 전체 애플리케이션은 각각 구성요소보다 신뢰성이 떨어진다. 예를들면 하나의 서비스가 의존하고 있는 체인이 6개이고 각각의 신뢰성은 99.99%라고 하자. 그러면 전체의 신뢰성은 0.9999^6은 0.94가되어 94%의 신뢰성을 가지게 된다. 즉 체인에 참여하는 모든 가용성 수치를 곱하면 전체 시스템의 실패율을 예측할 수 있다.
가용성을 극대화하거나 낮은 신뢰성의 영향을 고립시켜서 가용성을 보장하는 것은 매우 중요하다. 가용성을 측정하는 것이 신뢰할 수 있는 서비스를 만드는 방법을 알려주지는 않지만 목표를 제시해 준다. 서비스 개발과 그 서비스를 사용하는 서비스와 엔지니어의 기대치 모두에 목표를 제시한다.
다음 3가지 목표를 방어적으로 설계할 필요가 있다.
복잡한 시스템에서 장애는 불가피하다. 애플리케이션이 감당할 수 있는 다양한 장애의 유형을 이해하여 적절한 완화 전략을 설계하고 장애가 발생했을 때 즉각 대응할 수 있도록 해야한다.
실용적인 것이 중요하다. 모든 가능한 장애의 원인을 예측하거나 제거할 수는 없다. 회복성을 설계할 때 다음을 고려하여 균형을 맞출 필요가 있다.
책임 있는 서비스 설계자라면 가능한 장애 유형을 식별하고 기대하는 주기와 영향도에 따라 순위를 매긴 후 어떻게 그 영향에 대처할지 결정해야 한다.
서비스와 다른 구성요소 간에 상호작용하는 모든 지점이 장애가 발생할 수 있는 영역이다. 장애는 네가지 주요 영역에서 발생할 수 있다.
애플리케이션은 서로 끊임없이 상호작용하는 여러 서비스로 이루어지기 때문에 서비스 하나의 장애는 전체 시스템으로 퍼질 수 있다. 장애 전파는 분산 애플리케이션에서 일반적인 장애의 형태다.
과부하는 도미노 현상을 발생시킬 수 있다. 장애 전파는 부하가 가장 일반적인 원인의 하나지만 부하에 의해서만 유발되지는 않는다. 일반적으로 증가된 오류율 또는 느린 응답 시간이 서비스를 건강하지 못하게 만들 수 있고 서로 의존하는 여러 서비스에 장애를 증가시킬 수 있다. 장애를 제한하기위해 회로 차단기, 폴백, 부하 검사와 용량 계획, 백오프가 재시도, 적절한 타임아웃등이 있다.
실패를 피할 수 없다면 실패가 발생했을 때 가용성을 극대화하고 정확하게 동작하며 신속히 복구하는 서비스를 설계하고 구축해야 한다.
장애는 격리되거나 지속될 수 있지만, 각각 서비스는 이 하나의 요청이 어떤 경우인지 알 수 없다. 장애가 격리되고 과도기적 현상이라면 재시도가 합리적인 선택이다. 하지만 재시도 예산을 고려하는 것이 중요하다. 장애가 지속되어 시장 데이터 서비스의 용량이 감소된다면 이후의 호출은 문제를 악화시키고 시스템을 더욱 불안하게 할 것이다.
기하급수적 백-오프 전략을 사용하여 가변적인 시간 간격을 두고 성공적인 재시도를 하여 재시도가 고르게 퍼지도록 하고 재시도 부하를 빈도를 줄일 수 있다.
재시도는 간헐적인 의존성 오류를 견디는 데 효과적이지만, 하위 이슈를 악화시키거나 불필요하게 자원을 소모하지 않도록 조심해야 한다.
서비스가 재시도 제한에 걸리거나 재시도를 할 수 없으면 실패를 받아들이거나 요청을 처리할 다른 방법을 찾아야 한다.
의존하는 서비스가 실패할 경우 4가지 폴백 옵션이 있다.
상호작용에 적절한 데드라인을 설정하면 자원 소모 시간을 제한할 수 있다.
장애 서비스로의 요청을 멈춰 장애가 확산되는 것을 방지한다.
목표 서비스의 예상 신뢰도와 서비스 간의 상호작용 규모를 고려해 조심스럽게 고려해서 시간 간격과 임계치를 설정해야 한다. 회로가 열리고 닫힐 때를 모니터링해야 할 뿐만 아니라 특히 회로가 자주 열릴 경우 담당팀에 알림을 보내야 한다. 연결이 정상 상태인지 결정하기 위해 회로 차단기는 시험 요청을 보내야 한다. 시험 상태에서 회로는 반만 열린다. 시험이 성공하면 회로는 닫힌다.
즉각적이고 일정한 응답이 필요하지 않은 경우라면 더욱 복잡해지는 비즈니스 로직의 비용을 감수하고서라도 이 기법을 사용해 서비스 간 직접 커뮤니케이션을 줄여서 전체적인 가용성을 증가시킬 수 있다. 커뮤니케이션 브로커 자체가 단일 장애 지점이므로 확장과 모니터링, 효율적인 운영을 위한 조심스러운 관심이 필요할 것이다.
부하 분산기는 상태 점검을 실행하고 결과를 사용하는 것을 담당한다. 실제 질의하는 순간이 아니라 항상 하위 애플리케이션의 상태를 이해할 수 있는 방법이 있어야 한다. 모든 서비스에 적절한 상태 점검 방법을 구현해야 한다. 비동기식 서비스에서는 큐와 컨슈머간의 연결을 테스트하기 위해 하트비트 메커니즘을 사용할 수 있다.
상태 점검은 2가지 기준으로 분류해야 한다.
상위서비스가 단일 일괄 처리 호출이 더 적절한 곳에 여러 호출을 하거나 가용 리소스가 호출자에게 고르게 분산되지 않았을 수 있다. 제 3자 의존 서비스가 의존하는 다른 서비스가 부여한 제한에 걸릴 수 있다. 적절한 해결 방법은 협업 서비스가 일정 시간 범위 내에서 사용할 수 있는 요청의 비율 또는 전체 요청 수를 명시적으로 제한하는 것이다. 이렇게 하면 특히 수많은 협업 서비스를 가지고 있는 서비스가 부하를 받지 않도록 도움을 준다. 비율 제한은 서비스의 클라이언트에 설계할 때 공유하거나 운영 중에 공유하면 더 좋다. 서비스가 요청을 반환할 때 남아 있는 사용 가능한 요청의 수를 헤더에 담아 컨슈머에게 제공할 수 있다. 호출자는 이 정보를 이용해 요청의 비율을 조정한다. 이 기술을 백프레셔라고 한다.
서비스가 장애를 견딜 수 있고 우아하게 회복할 수 있는지 검증해야 한다. 철저한 테스트는 예측할 수 있거나 예측할 수 없는 장애가 발생했을 때 선택한 설계가 효과적인지를 확신하도록 도와준다.
정기적이고 조직적으로 카소트 이벤트에 대해 시스템을 검증하고 발견된 이슈를 해결하면 애플리케이션의 장애 회복성에 대한 상당한 수준의 확신을 얻게 될 것이다.
장애가 발생한 후에야 중요한 기능이 그 장애를 견디지 못한다는 사실을 발견하는 것을 원치 않을 것이다. 프레임워크와 프락시는 여러 서비스 간의 커뮤니케이션 표준에 적용하는 2가지 기술적 접근 방법으로 서비스 커뮤니케이션의 회복성과 기본적으로 인접한 것을 보장해 엔지니어가 올바른 것을 하기 쉽게 한다.
라이브러리를 사용해 서비스 간의 상호작용을 표준화하는 것은 다음의 장점들이 있다.
대안으로 서비스 메시(service mesh)를 도입할 수 있다. 다양한 기술이 혼합된 애플리케이션에서 방어적 커뮤니케이션을 간단하게 해준다.
자바스크립트로 직접 만들면서 배우는 - 자료구조와 알고리즘 강의 바로 가기
실습으로 마스터하는 OAuth 2.0: 기본부터 보안 위험까지 - OAuth 2.0 강의 바로 가기
기계인간 이종립, 소프트웨어 개발의 지혜 - Git 강의 바로 가기
코드숨에서 매주 스터디를 진행하고 있습니다. 메일을 등록하시면 새로운 스터디가 시작될 때 알려드릴게요!