본문 바로가기

개발/Node.JS

사례 연구 : Ghost에서 Node.js 메모리 누수 찾기

유령(Ghost)이란?

그냥 블로깅 플랫폼

Node.js Memory Leak - 고스트 블로깅 플랫폼 로고

Ghost는 전적으로 JavaScript로 작성된 완전히 공개 된 출판 플랫폼입니다. 백엔드는 Node.js를, 관리자는 Ember.js를 사용하고 렌더링에는 Handlebars.js를 사용합니다.

유령이 적극적으로 개발되었습니다. 지난 30 일 동안 마스터 브랜치에 66 명의 커밋을 한 10 명의 저자가있었습니다. 프로젝트의 로드맵은 https://trello.com/b/EceUgtCL/ghost-roadmap 에서 확인할 수 있습니다 .

https://ghost.org/ 에서 계정을 열고 즉시 작성하기 시작할 수 있습니다. 또는 우리가하는 것처럼 자신의 Ghost 버전을 호스트 할 수 있습니다.

유령 배포

첫째, RisingStack에서 프로덕션 환경에서 Ghost를 배포하고 사용하는 방법에 대한 간략한 개요를 알려드립니다. 우리는 Ghost를 npm 모듈로 사용합니다. 다음과 같이 더 큰 프로젝트에 필요합니다.

// adding Trace to monitor the blog
require('@risingstack/trace')
const path = require('path')
const ghost = require('ghost')

ghost({
  config: path.join(__dirname, 'config.js')
}).then(function (ghostServer) {
  ghostServer.start()
})

Docker 이미지를 생성하고 Docker 레지스트리에 푸시하여 준비 환경에 배포하는 Circle CI를 사용하여 배포가 수행 됩니다. 모든 것이 좋게 보인다면, 업데이트는 지금 읽고있는 프로덕션 블로그로 이동합니다. 백업 데이터베이스로이 블로그는 PostgreSQL을 사용합니다.

Node.js 메모리 누수

의존성을 최신 상태로 유지하기 위해 우리 ghost@0.9.0는 그것이 나오 자마자 업데이트 했습니다. 이렇게하면 메모리 사용량이 증가하기 시작하면서 경고가 시작됩니다.

Node.js 유령의 메모리 누출 - 메모리 메모리 메트릭 추적

다행히도 Trace에서 메모리 사용에 대한 경고를 설정했는데, 이는 옳지 않다는 것을 알려주었습니다. 으로 추적이 원활 Opsgenie 및 Pagerduty와 통합 , 우리는 그 채널에 대한 경고를 설정 할 수 있었다.

우리는 180과 220 메가 바이트에서 블로그 서비스에 대한 경고를 설정합니다. 보통 모든 것이 괜찮을 때 약 150 MB를 소비하기 때문입니다.

Trace에서 Node.js 메모리 누수에 대한 경고 설정

더 나은 점은 경고가 수집기 수준에서 작업을 트리거하는 방식으로 설정된다는 것입니다. 이것은 무엇을 의미 하는가? 즉, Trace가 사람의 개입없이 자동으로 메모리 힙 덤프를 만들 수 있음을 의미 합니다. 이 문제를 조사하기 시작하자 메모리 힙 덤프가 이미 Google 크롬 DevTools에서 지원하는 형식으로 Trace의 프로필러 섹션에있었습니다.

이를 통해 우리는 문제를 즉각적으로 볼 수 있었고 , 로컬 개발 환경에서 문제를 재현하려고 시도하지 않고 프로덕션 시스템 에서 문제가 발생하는 것을 막을 수있었습니다.

또한 응용 프로그램 자체에서 여러 힙 덤프를 가져올 수 있으므로 DevTools의 비교보기를 사용하여 비교할 수 있습니다.

Trace 및 Chrome의 Devtools와의 메모리 힙샷 비교

비교보기를 사용하여 문제의 원인을 찾는 방법? 위의 그림에서 알 수 있듯이, 이전에 요청한 힙 덤프로 경고가 트리거되었을 때 Trace가 자동으로 수집 한 힙 덤프를 비교했습니다.


당신이 찾아야 만하는 것은 우리의 경우에 +772를 보여주는 #Delta입니다. 즉, 메모리 사용량이 많은 경고가 트리거되었을 때 힙 덤프에 772 개의 개체가 추가로 있음을 의미합니다. 그림의 아래쪽에서이 요소들이 무엇인지 알 수 있고, 그들은 lodash 모듈과 관련이 있다는 것을 알 수 있습니다.


이것을 알아내는 것은 그렇지 않습니다. 현지 환경에서 문제를 재현해야하기 때문에 매우 어려울 것입니다. 문제의 원인을 모르더라도 까다로운 문제입니다.

업데이트해야합니까? 잘..

유출의 최종 원인은 유령 핵심 공헌자 인 Katharina Irrgang 이 발견했습니다 전체 스레드를 확인하려면 GitHub 문제 ( https://github.com/TryGhost/Ghost/issues/7189)를 살펴보십시오 수정 사항은 0.10.1과 함께 제공되었습니다. - 그러나 그것을 업데이트하면 또 다른 문제가 발생할 것입니다 : 느린 응답 시간.

느린 응답 시간

새 버전으로 업그레이드하고 나면 새로운 문제가 발생했습니다. 블로그의 응답 시간이 저하되기 시작했습니다. 95 백분위 수는 100ms에서 거의 300ms로 증가했습니다 . 그것은 즉시 응답 시간에 대한 경보 설정을 시작했습니다.

추적에서 느린 응답 시간 그래프

응답 시간이 느린 경우 Trace를 사용하여 CPU 프로파일을 사용하기 시작했습니다 . 현재로서는 정확한 이유를 조사 중입니다. 그러나 지금까지는 순간적으로 무언가가 빠졌다고 여겨집니다. js가 사용되었습니다.

Trace로 CPU 프로필 분석

우리는 그것이 일어난 이유를 알게되면 게시판을 업데이트 할 것입니다.

결론

이 기사가 Node.js 애플리케이션에서 메모리 누수가 발생했을 때를 대비해 어떻게해야 하는지를 이해할 수 있기를 바랍니다.