go 어플리케이션 cpu 과점유에 대한 원인 분석

김재영·2024년 6월 30일
0

상황

go 기반으로 짜여진 모니터링 에이전트가 있다.
하나의 서버에 10개정도의 어플리케이션이 있고 이를 모니터링하는 에이전트 10개가 있음.

top | grep <go 에이전트 pid> 의 결과 어플리케이션의 cpu 사용량이 60~70%이상으로 비정상적으로 높은 결과가 나왔다.

이 서버정보 간단히 소개하자면
OS 는 Linux CentOS7
cpu capa는 총 32코어다.

1개의 에이전트당 1코어 기준 60%를 사용하므로 총 9코어(15*0.6)를 모니터링 프로세스가 쓰고 있는 상황

perf top 으로 봤을때

kernel(native_queued_spin_lock_slowpath)의 cpu 사용량이 대부분이였고 이를 통해 프로세스에서 systemcall 을 사용하는 메서드가 cpu 부하를 일으키는 원인이라고 추정하였다.

테스트 과정

우선은 어플리케이션의 동작 이후 실행되는 주요 메서드를 모두 제거하고 제거된 코드로 빌드 후 동작시켜 보았다.

cpu 사용량을 측정해보았다.
메서드 모두 제거헀을 때 1코어 기준 3% 정도 사용한다.

주요 메서드는 총 6개 정도되는데 한개씩 추가해보았다.
(메서드가 뭘하는지는 중요하지 않아서 설명은 생략)

이과정에서 4번째 메서드가 cpu 상승의 원인으로 파악되었고
해당 메서드에서 kernel cpu 를 상승시킬 수 있는 원인 코드를 추적했다.

해당 메서드는 여러 task를 실행하는데, 특히 filesystem을 scan 하는 부분들이 있으면 의심해보았다(perf 결과로 systemcall 비중이 높았기에)

우선 이 추측이 맞는지 확인해보기 위해 scan 관련 메서드를 모두 뺏다. 그리고 다시 배포해서 실행하니 cpu 사용량이 3% 나왔다(빼기전 60%)

이후 scanning 메서드를 한개씩 추가해보았다. 노가다 작업이였다.
빼고 넣고 10번정도 반복하면서 빌드해보니 파일디스크립터 조회(/proc//fd) 하는 코드를 추가했을때 갑자기 cpu 가 올라가는것을 확인했다.

결과

즉각적인 대응을 위해 원인이 되는 코드 부분을 옵션처리 하여 작동하지 않도록 했다. 해당 코드가 레거시로 존재하는것으로 보였고(제거가 모니터링 동작, 기능에 영향을 주지 않았음), cpu 과점유가 서버상에 부하를 주고 있었기 때문에 빼도록 판단했음.

여러개의 모니터링 프로세스가 동시에 파일 디스크립터 조회(systemcall)를 하는건 커널에 상당한 부하를 주었고 이로 인한 cpu 사용량이 증가한것으로 보인다.

0개의 댓글