작년에 Uber 엔지니어링 팀은 마이크로서비스 아키텍처를 위해 설계된 새로운 로드 차단 메커니즘에 대한 기사를 발표했습니다 .
이 글은 다양한 관점에서 매우 흥미롭습니다. 그래서 읽으면서 이해를 돕기 위해 메모를 했고, 끝까지 답을 얻지 못하면 나중에 더 깊이 탐구하고 싶은 내용을 적어 두었습니다. 나는 이것이 새로운 것을 배우는 가장 좋은 방법이라는 것을 여러 번 발견했습니다.
처음부터 저를 사로잡은 것은 이 솔루션을 구축하는 데 사용된 수백 년 된 원칙에 대한 참조였습니다. 제가 좋아하는 것은 다양한 분야의 개념/아이디어를 빌려서 이를 적용하여 다른 영역의 문제를 해결하는 것입니다.
시스템 탄력성과 안정성에 관심이 있다면 훌륭한 책인 'Release It!' 도 읽어 보시기 바랍니다. 마이클 T. 나이가드(Michael T. Nygard) 지음.
오래되었지만 좋은 책입니다. 탄력적이고 안정적인 소프트웨어 시스템을 구축하기 위한 전략, 패턴 및 실제 지침을 자세히 설명하고 실패를 효과적으로 처리하는 방법을 강조하는 책입니다.
Uber는 PID 컨트롤러(수세기에 걸친 메커니즘)를 활용하여 서비스의 현재 로드와 요청 우선순위에 따라 서비스에서 어떤 요청을 처리하거나 삭제해야 하는지 결정하는 Cinnamon이라는 새로운 로드 차단 솔루션을 구현했습니다.
서비스 수준의 조정이 필요하지 않고(물론 이에 대해 질문이 있었지만) 자동으로 적응할 수 있으며 이전 솔루션인 QALM보다 훨씬 더 효율적입니다. Uber의 마이크로서비스 아키텍처는 마음이 약한 사람들을 위한 것이 아니라는 점도 기억하세요…
PID 컨트롤러는 온도, 유량, 압력, 속도 및 기타 프로세스 변수를 조절하기 위해 산업 제어 애플리케이션에 사용되는 계측기입니다. PID(비례 적분 미분) 컨트롤러는 제어 루프 피드백 메커니즘을 사용하여 프로세스 변수를 제어하며 가장 정확하고 안정적인 컨트롤러입니다.
이 수백 년 된 개념에 대해 더 많은 정보를 알고 싶다면 Wikipedia를 방문하세요.
이제 기사로 돌아갑니다. PID는 비례, 적분, 미분을 의미합니다. 이 경우 PID 컨트롤러라는 구성 요소를 사용하여 세 가지 구성 요소(또는 측정값)를 기반으로 서비스 상태(입력 요청)를 모니터링합니다.
"비례"라는 용어는 취해진 조치가 현재 오류에 비례함을 나타냅니다. 간단히 말해서 이는 적용된 수정이 원하는 상태와 실제 상태의 차이에 직접적으로 비례한다는 것을 의미합니다. 오류가 크면 그에 비례하여 수정 조치도 커집니다.
엔드포인트가 오버로드되면 백그라운드 고루틴은 우선순위 대기열로의 요청 유입 및 유출을 모니터링하기 시작합니다.
따라서 로드 차단기의 비례(P) 구성 요소는 현재 대기열 크기가 대상 또는 원하는 대기열 크기와 얼마나 떨어져 있는지에 따라 차단 비율을 조정합니다. 대기열이 원하는 것보다 크면 더 많은 삭제가 발생합니다. 더 작으면 흘리기가 줄어듭니다.
그것이 제가 이해한 바입니다.
PID 컨트롤러의 임무는 대기열에 있는 요청 수를 최소화하는 것이고, 자동 조정기의 임무는 응답 지연 시간을 너무 많이 희생하지 않고 서비스 처리량을 최대화하는 것입니다.
텍스트에서는 대기열 크기와 관련하여 "적분(I)"을 명시적으로 언급하지 않지만 PID 컨트롤러의 역할은 대기열에 있는 요청 수를 최소화하는 것임을 나타냅니다. 대기 중인 요청을 최소화하는 것은 시간이 지남에 따라 누적된 오류를 해결하려는 통합 구성 요소의 목표와 일치합니다.
엔드포인트가 오버로드되었는지 확인하기 위해 요청 대기열이 마지막으로 비어 있던 시간을 추적하고 마지막 10초 동안 비워지지 않은 경우 엔드포인트가 오버로드된 것으로 간주합니다(Facebook에서 영감을 얻음).
로드 차단기에서는 요청 대기열이 마지막으로 비워진 이후의 시간과 같은 요청 대기열의 기록 동작과 관련된 결정과 연관될 수 있습니다.
솔직히 그것은 나에게 완전히 명확하지 않습니다. 조금 실망스럽습니다. 그들은 수백 년 된 메커니즘 활용을 언급하지만, 어떤 부분이 그것이 무엇인지, 어떻게 작동하는지 명시적으로 언급했다면 도움이 되었을 것입니다. 나는 그들의 놀라운 기사의 가치를 줄이고 싶지 않습니다. 그건 내 호언장담일 뿐이야… 결국, 나는 프랑스 사람이야… ;)
제 생각엔 이게 식별하기 더 쉬운 것 같아요.
기존 PID(비례-적분-미분) 컨트롤러에서 "미분(D)" 동작은 오류의 현재 변화율을 기반으로 컨트롤러가 시스템의 향후 동작을 예측하도록 하려는 경우에 특히 유용합니다. 이는 진동을 완화하고 시스템 안정성을 향상시키는 데 도움이 됩니다.
기사에 언급된 로드 차단기 및 PID 컨트롤러의 맥락에서 파생 구성 요소는 요청 대기열이 얼마나 빨리 채워지는지 평가하는 데 사용될 가능성이 높습니다. 이를 통해 안정적인 시스템을 유지하고 갑작스럽거나 예측할 수 없는 변경을 방지하기 위한 의사 결정을 내리는 데 도움이 됩니다.
거부자 구성 요소에는 두 가지 책임이 있습니다. a) 엔드포인트가 오버로드되었는지 확인하고 b) 엔드포인트가 오버로드된 경우 요청의 일정 비율을 차단하여 요청 대기열이 가능한 한 작은지 확인합니다. 엔드포인트가 오버로드되면 백그라운드 고루틴은 우선순위 대기열로의 요청 유입 및 유출을 모니터링하기 시작합니다. 이 숫자를 기반으로 PID 컨트롤러를 사용하여 차단할 요청 비율을 결정합니다. PID 컨트롤러는 올바른 레벨을 찾는 데 매우 빠르며(반복이 거의 필요하지 않음) 일단 요청 큐가 비워지면 PID는 비율을 천천히 줄이는 것을 보장합니다.
언급된 맥락에서 PID 컨트롤러는 엔드포인트에 과부하가 걸렸을 때 차단할 요청 비율을 결정하는 데 사용되며 요청의 유입 및 유출을 모니터링합니다. 변화율에 응답하는 PID 컨트롤러의 파생 구성 요소는 요청 대기열이 얼마나 빨리 채워지거나 비워지는지 평가하는 데 암시적으로 관여합니다. 이는 시스템 안정성을 유지하기 위한 동적 결정을 내리는 데 도움이 됩니다.
과부하를 결정하는 맥락에서 필수 구성요소는 요청 큐가 비어 있지 않은 상태에 있었던 기간을 추적하는 것과 연관될 수 있습니다. 이는 시간이 지남에 따라 오류 신호의 적분을 누적한다는 아이디어와 일치합니다.
"적분 — 요청이 대기열에 있었던 기간에 따라…"
반면에 파생 구성 요소는 변화율과 관련이 있습니다. 요청 대기열의 상태가 얼마나 빨리 변경되는지에 응답합니다.
"파생 — 대기열이 얼마나 빨리 채워지는지에 따라 거부…"
Integral 구성 요소는 비어 있지 않은 상태의 지속 시간을 강조하는 반면 Derivative 구성 요소는 대기열이 변경되는 속도를 고려합니다.
게임이 끝나면 이 세 가지 측정 방법을 활용하여 요청에 대한 조치 과정을 결정합니다.
내가 가진 질문은 이 세 가지 구성 요소를 어떻게 결합하느냐는 것입니다. 그들이 어떻게 모니터링하는지 이해하고 싶습니다.
그래도 생각은 있는 것 같아요...
엣지의 엔드포인트에는 요청의 우선순위가 주석으로 추가되며 이는 Jaeger를 통해 엣지에서 모든 다운스트림 종속성으로 전파됩니다. 이 정보를 전파함으로써 요청 체인의 모든 서비스는 요청의 중요성과 그것이 사용자에게 얼마나 중요한지 알게 됩니다.
가장 먼저 떠오르는 생각은 서비스 메시 아키텍처에 원활하게 통합된다는 것입니다.
요청 우선 순위를 전파하기 위해 분산 서비스 추적 및 헤더를 사용하는 개념에 감사드립니다. 이러한 맥락에서 Istio 플러그인과 같이 서비스 외부에 배치하는 대신 각 마이크로서비스에 이 종속성이 추가된 공유 라이브러리를 선택하는 이유는 무엇입니까? 독립적인 릴리스/배포 주기, 다중 언어 지원 등 제공되는 이점을 고려합니다.
다음은 몇 가지 추가 생각입니다.
글쎄, 나는 공유 라이브러리의 열렬한 팬이 아니기 때문에 편견이 있습니다. 공유 라이브러리가 릴리스/배포 프로세스를 복잡하게 한다고 생각하기 때문입니다. 그러나 고려해야 할 서비스별 구성 측면이 있는지 잘 모르겠습니다. 아마도 서비스가 쿼리 처리를 시작하고 완료하기까지 기다려야 하는 시간을 구성할 수 있을까요?
테스트할 가치가 있는 측면 중 하나는 이젝터의 의사 결정 과정일 것입니다.
내가 이해한 바로는 서비스에 현지화된 PID 컨트롤러를 기반으로 요청을 거부할지 여부를 결정합니다. 보다 글로벌한 접근 방식을 위한 옵션이 있습니까? 예를 들어, 파이프라인의 다운스트림 서비스 중 하나가 자체 PID 컨트롤러로 인해 오버로드된 것으로 알려진 경우 업스트림 서비스가 이 오버로드된 서비스에 도달하기 전에(n 단계 더 아래로 내려갈 수 있음) 요청을 거부하기로 결정할 수 있습니까? 길)?
이 결정은 PID 컨트롤러 또는 다운스트림 서비스의 자동 조정기가 반환한 값을 기반으로 할 수 있습니다.
이제 저는 그들이 기사를 마무리하면서 언급된 다양한 측면에 대해 숙고하고 있으며 시스템의 효율성을 보여주기 위해 몇 가지 수치를 제공하고 있습니다. 이는 매우 인상적입니다.
그들은 어느 시점에서 '각 요청의 시간 제한은 1초입니다.'라고 언급합니다.
고정된 양의 RPS(예: 1,000)를 전송하는 5분 동안 테스트를 실행합니다. 여기서 트래픽의 50%는 계층 1이고 50%는 계층 5입니다. 각 요청의 시간 초과는 1초입니다.
분산 시스템에서는 요청을 특정 만료 시간 또는 기한과 연결하고 처리 경로에 따라 이 시간 제한을 적용하는 각 서비스를 연결하는 것이 일반적입니다. 요청이 완료되기 전에 만료 시간에 도달하면 체인의 모든 서비스에는 요청을 중단하거나 거부할 수 있는 옵션이 있습니다.
이 1초 제한 시간이 요청에 첨부되어 있고 각 서비스는 이 기한의 현재 위치에 따라 요청을 중단하기로 결정할 수 있다고 가정합니다. 이는 서비스를 통해 집계되므로 전역적인 측정값입니다. 아래 서비스 중 하나로 인해 요청을 완료할 기회가 없는 경우 가능한 한 빨리 요청을 중단하기로 결정하는 것이 전체 시스템 상태 또는 종속성에 대한 전역적 관점을 갖는 것에 대해 앞서 언급한 요점과 공감한다고 생각합니다. 길.
다운스트림 서비스(로컬 PID 컨트롤러의 데이터로 구성)의 '상태'가 응답에 첨부된 헤더로 반환되고 보다 발전된 회로 차단기/초기 선점형 차단 메커니즘을 구축하는 데 사용될 수 있습니까?
마지막으로, 이 문서에 제공된 설명을 기반으로 볼 때 이전 접근 방식이 타당해 보이기 때문에 더 자세히 알아보고 싶습니다.
좋은 처리량과 지연 시간을 측정해 보면 QALM과 Cinnamon 중 어느 것이 가장 좋은 성능을 발휘하는지 의심할 여지가 없습니다. 기사에서 QALM 접근 방식에 대한 링크를 언급하고 있습니다. 아마도 거기서 부터 시작해야 할 것 같습니다.)
항상 그렇듯이 이러한 접근 방식은 모든 사람에게 적합한 것은 아닙니다. Uber의 아키텍처와 로드는 그 자체로 다릅니다. 나는 실제로 이 시리즈의 다음 기사, 특히 PID 컨트롤러와 자동 튜너에 대해 더 자세히 알아보고 싶은 마음이 듭니다.
Cinnamon을 통해 우리는 수백 년 된 기술을 사용하여 서비스 용량을 거부하고 추정하기 위한 임계값을 동적으로 설정하는 효율적인 로드 차단기를 구축했습니다. 이는 QALM(및 모든 CoDel 기반 로드 차단기)에서 발견한 문제, 즉 Cinnamon이 다음을 수행할 수 있는 문제를 해결합니다.
- 안정적인 거부율을 빠르게 찾아보세요.
- 서비스 용량 자동 조정
- 구성 매개변수를 설정하지 않고 사용 가능
- 오버헤드가 매우 적음
이 접근 방식에서 흥미로운 점은 (우선순위) 대기열을 사용하기 때문에 각각의 새로운 입력 요청에 대해 무엇을 할지 결정하기 위해 처리할 모든 요청을 고려한다는 것입니다. 언급한 대로 메커니즘이 동일한 PID 측정값을 기반으로 모든 종속 서비스의 상태도 고려할 수 있는지 궁금합니다.
이 기사에는 전략의 효과를 측정하는 방법 및 이전 접근 방식과의 비교와 같은 다른 흥미로운 측면이 있습니다. 그러나 이미 제시된 것보다 더 자세한 메모가 필요하지는 않습니다. 따라서 원본 기사를 읽어 보시기를 적극 권장합니다.
이 기사가 유용하다고 생각하시나요? Linkedin , Hackernoon 및 Medium 에서 저를 팔로우하세요 ! 이 글을 공유하려면 👏해주세요!
여기에도 게시되었습니다 .