Node는 서버측 Javascript의 런타임으로서 Javascript의 애플리케이션 시나리오를 크게 강화합니다.
하지만 Node.js 런타임 자체는 블랙박스이므로 런타임 상태를 인지할 수 없으며 온라인 문제를 재현하기 어렵습니다 .
따라서 성능 모니터링 은 Node.js 애플리케이션의 "정상 작동"의 초석입니다. 다양한 런타임 표시기를 언제든지 모니터링할 수 있을 뿐만 아니라 비정상적인 시나리오 문제를 해결하는 데도 도움이 될 수 있습니다.
성능 모니터링은 성능 지표 수집 및 표시의 두 부분으로 나눌 수 있습니다
.
성능 데이터 캡처 및 분석
위 그림에서 현재 주류를 이루는 세 가지 Node.js 성능 모니터링 솔루션의 장단점을 확인할 수 있습니다. 다음은 이 세 가지 솔루션의 구성에 대해 간략하게 소개합니다.
Prometheus
AliNode를 형성하기 위해 다른 스냅샷 도구가 필요합니다.
Alinode는 공식 nodejs와 호환되는 확장 런타임으로 몇 가지 추가 기능을 제공합니다:
Agenthub는 성능 지표를 수집하는 데 사용되는 상주 프로세스입니다.
된
는
모니터링, 표시, 스냅샷 및 분석에서 폐쇄 루프를 형성합니다. 액세스는 편리하고 간단하지만 런타임을 확장할 때 여전히 위험이 있습니다.
Node.js Addon
사용하여 샘플러현재 프로세스의 CPU 시간 소모 데이터는 process.cpuUsage()
반환 값의 단위는 마이크로초이다.
현재 프로세스의 메모리 할당 데이터는 process.memoryUsage()
를 통해 얻을 수 있습니다. 반환 값의 단위는 바이트입니다.
위 그림에서 볼 수 있듯이 rss
에는 코드 세그먼트( Code Segment
), 스택 메모리( Stack
) 및 힙 메모리( Heap
)가 포함됩니다.
v8.getHeapStatistics()
및 v8.getHeapSpaceStatistics()
다음 그림은 v8의 힙 메모리 구성 분포를 보여줍니다.
힙 메모리 공간은 먼저 공간으로 나누어지고, 메모리는 1MB 정렬에 따라 페이징됩니다.
뉴 스페이스(New Space): 상대적으로 짧은 수명 주기로 일부 객체 데이터를 저장하는 데 사용되는 신세대 공간으로 두 개의 공간으로 구분됨(공간 유형은 semi space
): from space
to space
올드 스페이스(Old Space) : New Space
에서 승격된 객체를 저장하는 데 사용되는 Old Generation 공간
Code Space: v8 JIT로 컴파일된 실행 코드를 저장합니다.
Map Space: Object가 가리키는 히든 클래스의 포인터 객체를 저장합니다. 런타임에 따른 객체 레이아웃 구조는 객체 멤버에 빠르게 액세스하는 데 사용됩니다.
대형 객체 공간: 페이지에 할당할 수 없는 1MB보다 큰 객체를 저장하는 데 사용됩니다.
의 가비지 수집 알고리즘은
두Mark-Sweep-Compact
알고리즘을 사용합니다.Scavenge
두
from space
공간
New space
from
to
New space
Old space
으로 승격되고to space
으로복사가 완료되면 to space
에서 살아남은 개체만 있으며 from space
from space
에서 to space
교환되고 다음 라운드 Scavenge
시작됩니다.
보다 두 배의 공간을 낭비한다는 단점이 있습니다
.3단계: 표시, 지우기, 정리
트리거 타이밍: Old space
가득 찬 경우
단계:
표시(3색 표시 방법)
marking queue
(명시적 스택)에 넣고 해당 객체를 회색으로 표시합니다.marking queue
에서 pop
검은색으로 표시합니다.marking queue
로 push
스윕은
메모리 공간을 불연속적으로 만듭니다컴팩트
Old space
이 연속적이고 완전해지도록 하기 위해v8은 처음에 가비지 수집을 수행할 때 프로그램을 다시 실행하기 전에 프로그램을 중지하고 전체 힙을 검색한 후 메모리를 회수해야 합니다. 이 동작을 전체 일시 중지( Stop-The-World
)라고 합니다.
새로운 세대의 활성 개체는 작고 자주 재활용되지만, 전체 중지는 거의 영향을 미치지 않습니다. 그러나 이전 세대의 살아남은 개체는 많고 큽니다. 마킹, 청소, 분류 등으로 인한 일시정지 등은 더욱 심각할 것입니다.
이 개념은 실제로 React 프레임워크의 Fiber 아키텍처와 약간 비슷합니다. 브라우저의 자유 시간 동안에만 Fiber 트리를 통과하여 해당 작업을 수행합니다. 그렇지 않으면 실행이 지연되어 메인 스레드의 작업에 최소한의 영향을 미칩니다. , 애플리케이션 지연을 방지하고 애플리케이션 성능을 향상시킵니다.
v8에는
New space
기본 제한이 있으므로 64비트 시스템의 경우 32M, 32비트 시스템의 경우 16M,Old space
비트 시스템의 경우 1400M입니다이므로 node
신세대와 구세대의 공간 상한을 조정하기 위해 두 개의 매개변수가 제공됩니다
--max-semi-space-size
: New Space
공간의 최대값을 설정합니다.--max-old-space-size
: Old Space
공간 보기의 최대값을 설정합니다.node
GC 로그를 보는 세 가지 방법도 제공합니다.
--trace_gc
: 로그 줄은 각 GC의 시간, 유형, 힙 크기 변경 및 원인을 간략하게 설명합니다--trace_gc_verbose
: 각 GC 이후 각 V8 힙을 표시합니다. 공간의 세부 상태--trace_gc_nvp
: GC 유형, 일시 중지 시간, 메모리 변경 등을 포함한 각 GC의 세부 키-값 쌍 정보입니다.GC 로그는 상대적으로 원시적이고 필요하므로 보조 처리를 수행하려면 AliNode 팀에서 개발한 v8-gc를 사용할 수 있습니다. 로그 파서
실행 중인 프로그램의 힙 메모리 스냅샷을 찍고 메모리 소비를 분석하고
힙스냅샷 파일.heapsnapshot
다음과 같은 방법으로 생성됩니다.
heapdump 사용
v8의 힙 프로필 사용
nodejs의 내장 v8 모듈에서 제공하는
apiv8.getHeapSnapshot()
v8.writeHeapSnapshot(fileName)
v8-profiler-next 사용
Chrome devtools 툴바의 Memory에 업로드 .heapsnapshot
, 결과는 아래와 같이 표시됩니다.
기본 보기는 Summary
보기입니다. 여기서 가장 오른쪽 두 열인 Shallow Size
와 Retained Size
Retained Size
Shallow Size
v8 힙 메모리에 할당된 개체 자체의 크기를 나타냅니다.Shallow Size
Retained Size
가 특히 큰 것으로 확인되면 개체 내부에 메모리 누수가 있을 수 있습니다.
Comparison
보기를 사용하여 문제를 비교할
서로 다른 두 기간의 힙 스냅샷을 분석합니다. Delta
열은 가장 큰 메모리 변경 사항이 있는 개체를 필터링하는 데 사용할 수 있습니다.
프로그램을 실행하는 CPU의 스냅샷 샘플링을 수행하며, 이는 CPU 시간과 비율을 분석하는 데 사용할 수 있습니다.
.cpuprofile
파일을 생성하는 방법에는 여러 가지가 있습니다:
5분 분량의 CPU 프로필 샘플 모음입니다.
Javascript Profiler
생성된 .cpuprofile
파일은
기본 보기는 Heavy
보기입니다. 여기에는 Self Time
과 Total Time
Self Time
: 이 함수 자체의 실행 시간을 나타냅니다(다른 호출 제외).Total Time
: 다른 호출을 포함하여 이 함수의 실행 시간을 나타냅니다. 함수 호출) 총 시간과 자체 시간이 크게 벗어나는 경우 해당 함수에많은 시간이 소요되는 CPU 집약적인 계산이 Self Time
Total Time
.
응용 프로그램이 예기치 않게 충돌하고 종료되는 경우
추가 문제 해결시스템은 이를 자동으로 기록합니다. 프로세스는 해당 순간에 메모리 할당 정보, 프로그램 카운터 및 스택 포인터 및 기타 주요 정보를 충돌시켜 코어 파일
.core
ulimit -c unlimited
커널 제한을 엽니다node --abort-on-uncaught-exception
노드 시작 시 이 매개변수를 추가하면 애플리케이션에서 포착되지 않은 예외가 발생할 때 코어 파일을 생성할 수 있습니다.gcore <pid>
코어 파일.core
mdb, gdb, lldb 등의 도구를 통해 진단 가능 프로세스 충돌의 실제 원인
llnode `which node` -c /path/to/core/dump
힙 메모리가 계속해서 증가하는 것을 모니터링을 통해 관찰할 수 있으므로 문제 해결
heapsnapshot
상대적으로 큰 메모리를 항상 유지하고 있는 newThing
객체가 있다는 것을 분석하여 알아낼 수 있습니다
unused
theThing
newThing
클로저로 인한 replaceThing
사례
일반적인 메모리 누수
에는
자동으로 재활용되지 않으면 수동으로 객체를 null
로 설정, 타이머 제거, 이벤트 리스너 바인딩 해제 등과 같은 수동 재활용이 필요합니다.
이 기사는 전체 Node.js 성능 모니터링 시스템에 대한 자세한 소개를 제공했습니다.
먼저, 성능 모니터링을 통해 해결되는 문제점과 그 구성요소를 소개하고, 주류 솔루션의 장단점을 비교한다.
그런 다음 성능 지표의 두 가지 주요 부분과 스냅샷 도구를 자세히 소개합니다.
마지막으로 관찰, 분석 및 문제 해결을 통해 간단한 메모리 누수 사례를 재현하고 일반적인 메모리 누수 상황과 해결 방법을 요약합니다.
이 글이 모든 사람이 전체 Node.js 성능 모니터링 시스템을 이해하는 데 도움이 되기를 바랍니다.