프로덕션 실습 - 메모리 부족(OOM) 문제 해결

이 문서에서는 메모리 오버플로 환경을 시뮬레이션하고 프로덕션 서버 문제 해결 프로세스를 재현합니다.

1. 환경 구축

  1. 시뮬레이션을 위해 SpringBoot 애플리케이션을 사용합니다. 코드는 다음과 같습니다.
...
@RequestMapping("/oom/creation")
public void createOOM() {
    List<OOMObject> oomList = new ArrayList<>();
    for (;;){
        oomList.add(new OOMObject());
    }
}
复制代码
  1. 다음으로 서버에 배포합니다. 호스트의 다른 서비스에 영향을 미치지 않도록 여기에서 최대 힙 메모리를 128MB 로 설정합니다 .

nohup java -jar -Dserver.port=8083 -Xms128m -Xmx128m springboot-web-demo-1.0-SNAPSHOT.jar &

여기에서 설치해야 하며 , 설치 JDK되어 있지 않으면 OpenJDK의 Linux 설치 를 참조하십시오 .

3. 마지막으로 애플리케이션 시작 상태를 확인하고 다음을 실행합니다.

jps

b0a7d18eb4378d7047513f005543d53.png

또는ps -ef | grep java | grep -v grep

3ca45656ed157204874da4d03b5ff1d.png

프로세스 ID가 16327 인 응용 프로그램이 시작되었음을 알 수 있습니다 .

2. 메모리 오버플로 시뮬레이션

시뮬레이션하기 전에 top -Hp 16327(pid)프로세스의 CPU 사용량을 살펴보겠습니다.

-H 线程模式
-p 指定进程ID
复制代码

e996316f413a43e9478b4e2ef795991.png

그런 다음 이전에 정의한 인터페이스를 호출하여 시뮬레이션합니다.

1e3c4252a4e2ff12154da7d3fa2b305.png브라우저 를 통해 직접 액세스 하거나 curl 명령 을 사용하여 호출 할 수도 있습니다 . 호출 후 top -Hp 16327(pid)쿼리 프로세스의 CPU 사용량은 다음과 같습니다.

8d062f2f1162c76b182f6041dc63496.png여기에서 메모리 사용량이 몇 초 만에 82.5%로 치솟는 것을 볼 수 있습니다.

3. 문제 해결

다음 jstack으로 PID 16330의 스레드를 살펴보겠습니다. 여기서 먼저 PID를 16진수로 변환합니다.

printf "x%\n" 16330

100f4e3a4c0cb2895ee6880b536fcaa.png

그런 다음 다음 jstack명령으로 스레드를 봅니다.

jstack -l 16327 | grep -20 3fca

39453fdaa1448f4e74695f4640b803d.png

쓰레드가 GC 쓰레드임을 확인하고, jmapGC 상황을 질의하여 heap 메모리의 객체 상황을 직접적으로 살펴본다.

jmap -histo 16327 | head -n 10

c366b584cd5fe9a159c5723157c3690.png400만 개 이상의 OOMObejct 개체 인스턴스가 생성되었음을 알 수 있으며 이는 분명히 비정상입니다.

...
@RequestMapping("/oom/creation")
public void createOOM() {
    List<OOMObject> oomList = new ArrayList<>();
    for (;;){
        oomList.add(new OOMObject());
    }
}
复制代码

여기에 무한루프가 존재하는데 현재까지는 문제를 확인하였으며 수정 후 재실행될 예정입니다.

4. 기타 조사방법

온라인 서버 보안 문제로 인해 JDK 및 Linux에서 제공하는 기본 명령을 사용하여 문제를 해결하고 다른 방법은 다음을 참조하십시오.

  • JConsolejvisualvm 을 통해 덤프 로그 분석
  • 아서스 를 통해 확인

여기서 우리는 arthas를 보여줍니다.

1. 아서스 시작

wget https://alibaba.github.io/arthas/arthas-boot.jar 
java -jar arthas-boot.jar
复制代码

2. 다음은 대시보드 명령을 간략하게 보여줍니다.

e395857be47a44737d9274261650af6.png

GC 쓰레드의 메모리 비율이 높다는 것을 알 수 있다. 다른 방법 에 대한 자세한 내용은 참고 자료 를 참조하십시오 .

5. 참고문헌

  1. 아서스
  2. 제이콘솔
  3. JVisualVM
  4. 맨 위
  5. 제이맵

추천

출처juejin.im/post/7085326528560496653