
SAP 시스템(PI ABAP+JAVA 스택) 중 하나에서 성능 문제가 발생했습니다. 머신에 구성된 전체 64GB가 꽉 차게 됩니다(그리고 8개 코어도 마찬가지). 모두가 Java 부분을 의심하지만 내 생각은 다릅니다.
메모리 부족 오류로 다시 시작되는 Java 서버 노드입니다. hprof 파일을 살펴보면 서버 노드에 대해 3GB(-Xms 및 Xmx 모두)의 힙이 구성된 경우 크기가 1.2G(3개 서버 노드의 평균)에 불과하다는 것을 발견했습니다. 이 관찰은 다음과 같은 의심으로 이어진다.
Xms와 Xmx가 동일한 값으로 설정되면 jvm이 시작될 때 전체 힙이 할당된다는 것을 읽었습니다. 이 경우 서버 노드는 처음부터 3GB의 힙을 갖게 됩니다. 그렇다면 왜 hprof 파일에 반영되지 않거나 hprof에 런타임 중에 객체에 할당된 메모리만 포함되어 있는 경우 크기는 힙 메모리가 사용 가능한지(50% 이상) 명확하게 나타내므로 OOM 오류가 발생합니다. ..!!..??
나는 또한 리눅스가 메모리 오버 커밋(memory over-commit)이라는 것을 한다는 것을 알고 있습니다. 즉, 메모리는 요청될 때가 아니라 실제로 사용될 때 제공됩니다. 이것이 메모리 부족 예외에 영향을 미치고 있습니까? JVM이 시작될 때와 마찬가지로 OS는 3GB의 메모리가 할당되었다고 말하지만 실제로 필요할 때까지 이를 연기합니다. jvm이 실제로 메모리를 객체에 할당하려고 시도할 때 일부 다른 애플리케이션이 메모리를 모두 소모했을 수 있습니다. 이것이 가능한가...??
Java 노드에 메모리 누수 문제가 있더라도 3GB의 힙으로 제한되지 않을까요? 어떻게 물리적 메모리의 전체 64G를 차지할 수 있습니까...???
내가 관찰한 또 하나는 스왑 공간이 50%만 사용되었다는 것입니다.
이것에 대한 어떤 빛이라도 ...!
답변1
SAP OSS도 이 문제를 조사하고 있었습니다. 오늘 나는 그들로부터 답장을 받았습니다. 내 관찰이 정확했습니다. 자바는 범인이 아니었습니다. ABAP 스택에 문제가 발생하여 메모리가 해제되지 않았습니다. ABAP 작업 프로세스를 다시 시작한 후 OS 수준에서 메모리가 해제되었습니다.
그러나 그러한 상황이 발생하여 JAVA OOM 오류가 발생할 수 있는지 여부와 같이 질문에서 강조 표시된 부분에 대해서도 이해하고 싶습니다...??..!!. 이와 관련된 모든 정보가 도움이 될 것입니다.
답변2
오버커밋은 기본적으로 Linux의 휴리스틱 모드에서 활성화됩니다. 이는 커널이 일반적으로 오버커밋을 허용한다는 것을 의미합니다. 즉, 프로세스가 실제로 동시에 모든 메모리를 사용하기 시작하지 않기를 바라면서 이를 요청하는 모든 프로세스에 더 많은 메모리를 약속한 다음 실제로 제공할 수 있다는 의미입니다. 서버에서 오버커밋이 비활성화되었을 수 있습니다. 다음을 실행하여 확인할 수 있습니다.
$ cat /proc/sys/vm/overcommit_memory
값이 0이면 경험적 오버커밋이 활성화됩니다.
실제 메모리 사용량이 시스템이 제공할 수 있는 RAM 양을 초과하는 상황이 발생하면 커널은 메모리를 확보하기 위해 프로세스를 종료하는 OOM 킬러를 활성화합니다. 일반적으로 많은 양의 RAM을 소비하는 가장 어린 프로세스를 종료하지만 이에 의존할 수는 없습니다. 그것은 혼란을 일으킬 수 있습니다. /proc//oom_adj를 조정하여 OOM의 선호도를 수정하여 특정 프로세스를 종료할 수 있습니다(예를 들어 OOM이 데이터베이스나 다른 대규모 RAM [ab]사용자를 종료하는 상황을 피하려는 경우).
따라서 시스템이 OOM 단계에 들어가면 Java 프로세스가 즉시 종료될 수 있습니다. 이로 인해 관찰 중인 Java 로그에 '메모리 부족' 메시지가 표시되지 않습니다.
Xmx와 Xms를 모두 동일한 값으로 설정하면 힙 크기 조정이 방지되지만 이것이 시작 시 Java 프로세스가 모든 메모리를 한꺼번에 사용하기 시작한다는 의미는 아닙니다. VIRT 메모리가 필요한 만큼 할당하지만 상주 데이터 세트는 Xms까지 커지지 않고 필요한 만큼 낮게 유지됩니다.
가상 메모리 측면에서 커널은 Java 프로세스가 요구하는 만큼(Xmx + 일부 추가)을 약속(오버커밋)하지만 모든 메모리가 즉시 할당되지는 않습니다. 현재 데이터에 필요한 양만 할당되며, 상주 세트 크기(작업이 사용한 스왑되지 않은 물리적 메모리)를 관찰하여 얼마인지 확인할 수 있습니다. VIRT 및 RSS 크기를 보려면 다음 명령을 실행할 수 있습니다.
$ ps aux | egrep '(^USER|java)'
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
tomcat 10229 21.5 9.1 6813688 548344 ? Sl 09:01 1:10 ....java...
아마도 여러분이 관찰하고 있는 오류는 Java Virtual Machine 프로세스에서 실행되는 프로그램에 힙 공간이 부족하다는 의미입니다. Xmx 설정을 높이고 앱을 다시 테스트해 보세요.