이 문서에서는 메모리 오버플로 환경을 시뮬레이션하고 프로덕션 서버 문제 해결 프로세스를 재현합니다.
1. 환경 구축
- 시뮬레이션을 위해 SpringBoot 애플리케이션을 사용합니다. 코드는 다음과 같습니다.
...
@RequestMapping("/oom/creation")
public void createOOM() {
List<OOMObject> oomList = new ArrayList<>();
for (;;){
oomList.add(new OOMObject());
}
}
复制代码
- 다음으로 서버에 배포합니다. 호스트의 다른 서비스에 영향을 미치지 않도록 여기에서 최대 힙 메모리를 128MB 로 설정합니다 .
nohup java -jar -Dserver.port=8083 -Xms128m -Xmx128m springboot-web-demo-1.0-SNAPSHOT.jar &
여기에서 설치해야 하며 , 설치 JDK
되어 있지 않으면 OpenJDK의 Linux 설치 를 참조하십시오 .
3. 마지막으로 애플리케이션 시작 상태를 확인하고 다음을 실행합니다.
jps
또는ps -ef | grep java | grep -v grep
프로세스 ID가 16327 인 응용 프로그램이 시작되었음을 알 수 있습니다 .
2. 메모리 오버플로 시뮬레이션
시뮬레이션하기 전에 top -Hp 16327(pid)
프로세스의 CPU 사용량을 살펴보겠습니다.
-H 线程模式
-p 指定进程ID
复制代码
그런 다음 이전에 정의한 인터페이스를 호출하여 시뮬레이션합니다.
브라우저 를 통해 직접 액세스 하거나 curl 명령 을 사용하여 호출 할 수도 있습니다 . 호출 후
top -Hp 16327(pid)
쿼리 프로세스의 CPU 사용량은 다음과 같습니다.
여기에서 메모리 사용량이 몇 초 만에 82.5%로 치솟는 것을 볼 수 있습니다.
3. 문제 해결
다음 jstack
으로 PID 16330의 스레드를 살펴보겠습니다. 여기서 먼저 PID를 16진수로 변환합니다.
printf "x%\n" 16330
그런 다음 다음 jstack
명령으로 스레드를 봅니다.
jstack -l 16327 | grep -20 3fca
쓰레드가 GC 쓰레드임을 확인하고, jmap
GC 상황을 질의하여 heap 메모리의 객체 상황을 직접적으로 살펴본다.
jmap -histo 16327 | head -n 10
400만 개 이상의 OOMObejct 개체 인스턴스가 생성되었음을 알 수 있으며 이는 분명히 비정상입니다.
...
@RequestMapping("/oom/creation")
public void createOOM() {
List<OOMObject> oomList = new ArrayList<>();
for (;;){
oomList.add(new OOMObject());
}
}
复制代码
여기에 무한루프가 존재하는데 현재까지는 문제를 확인하였으며 수정 후 재실행될 예정입니다.
4. 기타 조사방법
온라인 서버 보안 문제로 인해 JDK 및 Linux에서 제공하는 기본 명령을 사용하여 문제를 해결하고 다른 방법은 다음을 참조하십시오.
- JConsole 및 jvisualvm 을 통해 덤프 로그 분석
- 아서스 를 통해 확인
여기서 우리는 arthas를 보여줍니다.
1. 아서스 시작
wget https://alibaba.github.io/arthas/arthas-boot.jar
java -jar arthas-boot.jar
复制代码
2. 다음은 대시보드 명령을 간략하게 보여줍니다.
GC 쓰레드의 메모리 비율이 높다는 것을 알 수 있다. 다른 방법 에 대한 자세한 내용은 참고 자료 를 참조하십시오 .