프롬프트에 따라 3.2.0.beta3-dev에서 3.2.0.beta3로 업그레이드를 시도했는데, 에셋의 엠퍼(ember) 빌드 중 메모리 부족으로 인해 Discourse 인스턴스가 손상되었습니다. ./launcher rebuild app 명령을 실행해도 동일한 결과가 나타났습니다.
FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory
1: 0xb83f50 node::Abort() [ember]
2: 0xa94834 [ember]
3: 0xd647c0 v8::Utils::ReportOOMFailure(v8::internal::Isolate*, char const*, bool) [ember]
4: 0xd64b67 v8::internal::V8::FatalProcessOutOfMemory(v8::internal::Isolate*, char const*, bool) [ember]
5: 0xf42265 [ember]
6: 0xf5474d v8::internal::Heap::CollectGarbage(v8::internal::AllocationSpace, v8::internal::GarbageCollectionReason, v8::GCCallbackFlags) [ember]
7: 0xf2ee4e v8::internal::HeapAllocator::AllocateRawWithLightRetrySlowPath(int, v8::internal::AllocationType, v8::internal::AllocationOrigin, v8::internal::AllocationAlignment) [ember]
8: 0xf30217 v8::internal::HeapAllocator::AllocateRawWithRetryOrFailSlowPath(int, v8::internal::AllocationType, v8::internal::AllocationOrigin, v8::internal::AllocationAlignment) [ember]
9: 0xf113ea v8::internal::Factory::NewFillerObject(int, v8::internal::AllocationAlignment, v8::internal::AllocationType, v8::internal::AllocationOrigin) [ember]
10: 0x12d674f v8::internal::Runtime_AllocateInYoungGeneration(int, unsigned long*, v8::internal::Isolate*) [ember]
11: 0x17035b9 [ember]
Aborted (core dumped)
error Command failed with exit code 134.
I, [2023-11-26T17:19:26.345389 #1] INFO -- : yarn run v1.22.19
$ /var/www/discourse/app/assets/javascripts/node_modules/.bin/ember build
Environment: development
WARNING: ember-test-selectors: You are using an unsupported ember-cli-babel version. data-test properties are not automatically stripped from your JS code.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
비영리 단체를 위해 1GB 메모리를 가진 DigitalOcean 인스턴스에서 실행 중이라, 메모리를 늘리기 위해 리사이즈할 여유가 없습니다. 1GB는 Discourse의 최소 사양이며, 이전 버전들은 문제없이 실행되었습니다. 다시 정상적으로 실행할 수 있는 방법에 대한 아이디어가 있을까요?
Discourse 측에서 문제를 완화하는 데 도움이 될 수 있는 추가 정보를 공유합니다. 제 인스턴스(DigitalOcean ~1GB 드롭렛, 스왑 2GB)는 최근 재빌드 시간이 눈에 띄게 길어졌으며, 4번 중 3번꼴로 동일한 치명적 오류가 보고되고 있습니다(./launcher cleanup를 실행한 뒤에는 운이 좋아지는 것 같지만, 이를 확인할 만큼 표본 수가 충분하지는 않습니다).
힙 아웃 오브 메모리 오류가 발생하기 직전, 다음과 같은 로그가 기록됩니다:
Node.js heap_size_limit (491.0) is less than 1024MB. Setting --max-old-space-size=1024.
Node.js heap_size_limit (491.0) is less than 2048MB. Disabling Webpack parallelization with JOBS=0 to conserve memory.
이 부분은 제 전문 영역이 아니므로, 잘못 짚은 부분이 있을 수 있습니다. 간단한 조사를 해본 결과, ember-cli가 node.js에 의존하고 있어 이 문제가 관련이 있다고 생각합니다. --max-old-space-size 플래그는 RAM보다 더 높은 값으로 설정할 수 있습니다(이 경우 스왑 공간으로 넘어가며, 이 경우에는 문제가 되지 않습니다). 따라서 1024는 더 이상 재빌드를 감당할 수 없는 인공적인 상한선일 수 있습니다.
참고: --optimize-for-size는 메모리 사용량을 줄이는 데 도움이 되는 node.js 플래그로 알려져 있습니다(Discourse/ember에서 사용 중인지, 이미 사용 중인지 확실하지 않습니다). 또한, 특정 node.js 사용 환경에서 가비지 컬렉터가 활성화되지 않는다는 사례가 있어 이것이 문제가 될 수 있습니다.
이 중 일부가 Discourse 측에서 ember/node.js 사용과 관련하여 관련이 있고 제어할 수 있다면, 누군가가 조사해 볼 가치가 있을 것입니다. 그렇지 않다면 걱정하지 마시고, 위에서 제안한 임시 2GB 업그레이드 솔루션을 진행하겠습니다.
치명적인 오류가 매번 발생하는 것은 아니고, 최근에는 재빌드에 약 25분(이전 5~10분에서 증가)이 걸리기 때문에, 이 서버 사양에서 해당 수치를 늘리는 것이 메모리 문제를 해결하는지 확인하려면 시간이 좀 걸릴 것 같습니다.
하지만 이미 두 개의 Node.js heap_size_limit 경고가 더 이상 재빌드 로그에 표시되지 않고, 첫 번째 재빌드가 성공적으로 완료되었으므로 좋은 징조입니다.
수정: 위에서 언급한 app.yml의 NODE_OPTIONS 설정 덕분에 여러 번 재빌드해도 문제가 없었습니다. 좋아요!
수정2: 이 해결책은 그 마법 숫자 (데이비드의 게시물에서 가져온 링크)를 늘리는 방식으로 Discourse에 반영되어야 할 것 같습니다. 이렇게 하면 다른 저사양 RAM 머신들도 계속 작동할 수 있을 테니까요. 만약 이를 어떻게 해야 하는지 아는 분이 이 글을 보신다면, 정말 좋겠습니다.
./launcher rebuild app를 몇 번 실행해 보았지만, 여러 가지 문제로 인해 실패했습니다.
처음에는 bundle install에서 rbtrace에 대한 오류가 발생했습니다 (An error occurred while installing rbtrace (0.5.0), and Bundler cannot continue. 메시지로 종료되었습니다).
그 후 결국 다음과 같은 OOM(메모리 부족) 문제가 발생했습니다:
I, [2023-12-12T07:50:59.497921 #1] INFO -- : > cd /var/www/discourse && su discourse -c 'bundle exec rake themes:update assets:precompile'
Node.js heap_size_limit (1010.0) is less than 1024MB. Setting --max-old-space-size=1024.
Node.js heap_size_limit (1010.0) is less than 2048MB. Disabling Webpack parallelization with JOBS=0 to conserve memory.
<--- Last few GCs --->
[3683:0x5dab130] 279104 ms: Scavenge 981.3 (1037.1) -> 974.5 (1037.1) MB, 8.3 / 0.0 ms (average mu = 0.699, current mu = 0.681) allocation failure;
[3683:0x5dab130] 279136 ms: Scavenge 981.8 (1037.1) -> 975.0 (1037.1) MB, 8.0 / 0.0 ms (average mu = 0.699, current mu = 0.681) allocation failure;
[3683:0x5dab130] 282606 ms: Mark-sweep 994.8 (1050.6) -> 987.7 (1048.9) MB, 3316.1 / 0.0 ms (average mu = 0.593, current mu = 0.501) allocation failure; GC in old space requested
<--- JS stacktrace --->
FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory
1: 0xb83f50 node::Abort() [ember]
2: 0xa94834 [ember]
3: 0xd647c0 v8::Utils::ReportOOMFailure(v8::internal::Isolate*, char const*, bool) [ember]
4: 0xd64b67 v8::internal::V8::FatalProcessOutOfMemory(v8::internal::Isolate*, char const*, bool) [ember]
5: 0xf42265 [ember]
6: 0xf5474d v8::internal::Heap::CollectGarbage(v8::internal::AllocationSpace, [snip]
Aborted (core dumped)
error Command failed with exit code 134.
마지막으로 ./discourse_doctor를 실행하니 결국 그 문제를 넘어갈 수 있었습니다 (왜 그랬을까요? 후속 실행 시 캐시에 더 많은 내용이 저장되어 메모리 사용량이 줄어든 걸까요? )
I, [2023-12-12T08:02:50.556442 #1] INFO -- : > cd /var/www/discourse && su discourse -c 'bundle exec rake themes:update assets:precompile'
Node.js heap_size_limit (1010.0) is less than 1024MB. Setting --max-old-space-size=1024.
Node.js heap_size_limit (1010.0) is less than 2048MB. Disabling Webpack parallelization with JOBS=0 to conserve memory.
110:M 12 Dec 2023 08:07:50.026 * 100 changes in 300 seconds. Saving...
110:M 12 Dec 2023 08:07:50.030 * Background saving started by pid 3706
3706:C 12 Dec 2023 08:07:51.292 * DB saved on disk
3706:C 12 Dec 2023 08:07:51.294 * Fork CoW for RDB: current 1 MB, peak 1 MB, average 1 MB
110:M 12 Dec 2023 08:07:51.334 * Background saving terminated with success
Purging temp files
Bundling assets
하지만 이것은 우리가 겪어야 했어야 할 마찰이 아니었습니다. 앞으로 이 부분이 개선되기를 바랍니다.
참고로:
# free -h
total used free shared buff/cache available
Mem: 1.9Gi 1.3Gi 87Mi 138Mi 593Mi 394Mi
Swap: 2.0Gi 337Mi 1.7Gi