노드의 무한 순환을 어떻게 디버깅합니까?js 생산 코드
노드js는 실행 중인 프로그램을 중단하고 창고 추적을 인쇄할 수 있는 기존의 도구가 없습니다.따라서 생산 코드가 100% CPU에서 갑자기 최고치에 이르렀을 때 어디에 걸렸는지 찾기가 매우 어렵다.응용 프로그램 코드의 무한 순환은 비확정성으로 인해 발생하기 때문에 -prof와 -cpu-prof(V8 디버거가 제공하는 본 컴퓨터의 Node.js 분석 도구)는 도움이 되지 않습니다.
Apify에서 무상태Kubernetes(K8s) 용기에서 실행되는 생산 응용 프로그램에서 이러한 문제가 발생했습니다.이 프로그램은 간단한 express.js 기반의 웹 서버입니다.본고는 우리에게 효과적인 해결 방안을 소개하였다.그것도 너를 도울 수 있기를 바란다.
TL;DR — We used a script based on this GitHub gist, which attaches the GNU debugger (GDB) to Node.js processes to print the leaking code’s stack trace. We had to run the script with K8s’ livenessProbe check to get the stack trace and save it to a persistent volume.
응용 프로그램 컨테이너에서 GDB 디버거 사용
노드로 삼다.js 개발자는 V8와 기본 C++ 코드에 대한 기본 지식을 갖추고 있으며, GDB 디버깅 노드를 사용하지 않았을 수도 있습니다.js 응용 프로그램.대부분의 경우 사용하지 않았을 수도 있지만, 이 특정한 상황에서 GDB는 매우 유용하다는 것을 증명합니다.
GDB를 사용하면 디버거를 실행 중인 노드에 연결할 수 있습니다.js 프로세스, 그리고 C++에 인터럽트를 설정합니다. 거기서 무한 순환이 발생합니다.V8의 이곳은 stack guard라고 하는데, 우리는 그 중에서 그것을 사용할 생각을 얻었다GitHub gist. (더 많은 것을 알고 싶으면 전체 스크립트에 대한 설명을 포함한다.)
GDB와 V8의 스택 보호에 대한 기본 지식을 통해 무한 순환을 초래하는 절차를 복사하고 발생하는 곳에서 응용 프로그램 코드의 스택 추적을 인쇄할 수 있습니다.다음 코드는 인터럽트를 창고 보호에 추가하고 창고 추적을 인쇄합니다.
GDB가 설치된 간단한 Docker 컨테이너를 실행하여 쉽게 테스트할 수 있습니다.먼저 무한 순환을 실행한 다음 GDB 명령을 실행합니다
다음은 Docker를 사용하여 로컬 터미널에서 테스트하는 단계입니다
이 명령을 실행하면 터미널에 myLoop 함수의 창고 추적을 표시해야 합니다
Update K8s deployment to use the GDB script
이제 무한 순환의 창고 추적을 얻을 수 있는 방법을 알게 되었습니다. 생산 용기에서 사용할 수 있습니다.먼저 Docker 컨테이너에 GDB를 추가합니다.이 경우 테스트에 사용된 명령을 사용하여 Dockerfile
apt-get update
apt-get install gdb
다음은 이 장면의 Dockerfile
현재 Docker 컨테이너에 GDB가 설치되어 있습니다. 무한 순환 상태에서 GDB 명령을 추가해야 합니다.위에서 말한 바와 같이, 우리의 순환은 비확정성으로 인해 일어난 것이기 때문에, 우리는livenessprobe 명령을 사용하여 그것을 찾습니다
우리의 예에서 우리는 기본적인 HTTP 활성 탐지 검사를 설정했다.그것은 5초에 한 번씩/건강검진 경로를 검사하고 세 번의 실패한 시도를 허용합니다
이 탐지가 네 번째 실패하면 K8s 스케줄러는 용기를 죽은 용기로 선언하고 탱크로 대체합니다.용기가 실행될 때 용기가 죽었다고 선고되는 위치는 GDB 명령이 실행되어야 하는 위치입니다
당신은 순환을 초래하는 행위를 보류하기를 원합니다.그러나 건강검진에 실패하면 GDB 스크립트를 실행하고 특정 파일에 무한 순환 스택 추적을 저장해야 합니다.다음 bash 스크립트는 바로 이렇게 하는 것입니다
스크립트를 liveness\u probe로 저장합니다.응용 프로그램의 루트 디렉터리에 들어갑니다.bash 스크립트의 역할은 HTTP 활성도 탐지와 완전히 같습니다.그러나 건강검진이 네 번 실패하면 GDB 명령을 실행하고 스택 추적을 인쇄합니다
우리 응용 프로그램에서 이 스크립트를 사용하기 위해서는 K8s배치규범에서 livenessprobe를 편집해야 합니다. 아래와 같습니다
이것은 우리의 건강검진 스크립트가 40초에 한 번씩 실행되는 것을 확보합니다. 이것은 5초에 네 번씩 HTTP 프로브를 실행할 수 있습니다.하지만 조심해야 합니다. 여기서 디버거를 사용하기 때문에 SYS\u PTRACE 로고가 있는 process trace
우리는 K8s배치에서 보안Context를 사용하여 이 점을 실현할 수 있다
Saving the stack trace file to a persistent volume
순환을 추적하여 특정 파일에 인쇄할 수 있다면 다시 시작한 후에 이 파일을 삭제하지 않도록 해야 합니다.응용 프로그램이 무상태로 실행되기 때문에 용기를 다시 시작하면 메모리와 저장된 모든 데이터가 손실됩니다
영구권을 K8s 크레인에 연결하려면 these steps에 따라 조작할 수 있습니다.K8s 호스팅 클러스터마다 연결 가능한 볼륨이 약간 다릅니다.우리의 어플리케이션은 AWS Elastic Kubernetes Service(EKS)를 사용하여 Elastic File System(EFS)와 쉽게 호환됩니다
아래 명령을 실행하여 EFS의 기본 설정을 완성할 수 있습니다
aws efs create-file-system
출력에서 추가 사용을 위해 FileSystemId 속성이 필요합니다.EFS를 영구 볼륨으로 EKS 클러스터에 연결하려면Amazon EFS CSI Driver을 시작합니다.설치 후 StorageClass K8s 리소스를 작성하여 어플리케이션에 알립니다
다음, 생성persistent volume 및persistent volume claim
참고: FileSystemId를 volumeHandle
마지막으로, 영구 볼륨 성명을 배치에 불러옵니다
영구 볼륨을 설정한 후 SSH를 사용하여 응용 프로그램의 용기에 연결합니다.스택 추적을 포함하는 파일은 디버거 폴더에 있습니다
Conclusion
한 마디로 하면 우리 응용 프로그램은 생산 시에만 발생하는 불확실한 무한 순환이 있다.우리는 GNU 디버거를 응용 프로그램의 노드에 연결하여 식별합니다.js 프로세스, 누출 코드의 창고 추적을 출력할 수 있습니다.그리고 Kubernetes의livenessProbe 검사를 실행하여 창고 추적을 가져오고 영구 볼륨에 저장합니다
우리의 예에서 무한순환은 제3자 패키지로 인해 일어난다
노드에서 무한 순환을 만나면 본고가 유용하다는 것을 발견할 수 있기를 바랍니다.js 응용 프로그램
그 밖에 우리는 k8s 집단에 a sidecar container을 추가하여 창고 추적 파일을 AWS S3 메모리 통에 직접 동기화합니다.만약 당신이 우리가 어떻게 하는지에 대해 흥미가 있다면, 평론에서 우리에게 미래의 블로그 글에서 이것에 대해 묘사할 것이라고 알려주십시오
Reference
이 문제에 관하여(노드의 무한 순환을 어떻게 디버깅합니까?js 생산 코드), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/apify/how-to-debug-an-infinite-loop-in-node-js-production-code-4pk7텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)