여러 도구를 사용한 JVM 튜닝 및 온라인 문제 해결의 예

1 FullGC 튜닝

면접관: JVM 튜닝 방법(실제 사례 포함)

2 arthas를 사용하여 사례 진단

2.1 arthas를 사용하여 시간이 많이 걸리는 요청이 어느 컨트롤러에서 오는지 확인하고 코드를 분석 및 최적화

2.1.1 "요청 소스의 컨트롤러 결정"의 첫 번째 단계를 수행하는 이유는 무엇입니까?

분석: 먼저 사용자 로그인 요청 등 분석하려는 요청이 무엇인지 알아야 하며, 두 번째로 springMVC의 특성을 이해해야 합니다. 모든 요청이 DispatcherServet 클래스를 거쳐 다시 DispatcherServet 클래스로 돌아간다는 것을 알고 있습니다. 처리를 위한 getHandler 메소드의 DispatcherServet 이 요청에 대한 컨트롤러입니다.

2.1.2 1단계: 특정 솔루션 찾기

  1. 따라서 우리의 초점은 watch 명령을 직접 사용하여 getHandler 메소드의 입력 매개변수 및 반환 값을 관찰하는 것입니다.
watch org.springframework.web.servlet.DispatcherServlet getHandler 'returnObj'
  1. 그런 다음 프런트 엔드나 우체부에서 이러한 요청을 트리거합니다. 예를 들어 여기에서 로그인 요청을 트리거합니다.

3. 어떤 컨트롤러를 얻었는지 확인하세요.
아래 빨간색 부분을 통해 이 로그인 요청이 UserController 컨트롤러의 로그인 메서드와 StudentController 컨트롤러의 findAll 메서드를 통과했음을 알 수 있습니다.
여기에 이미지 설명을 삽입하세요

2.1.3 2단계: 분석

  1. 입력 매개변수 및 반환 값 분석: watch 명령을 사용하여 이 특정 컨트롤러의 처리 방법의 입력 매개 변수 및 반환 값을 관찰합니다.
watch com.itheima.controller.* * '{params,returnObj}' -x 2

얻은 결과는 다음과 같습니다.

method=com.itheima.controller.UserController.login location=AtExit
ts=2023-08-21 20:55:52; [cost=5.2786ms] result=@ArrayList[
    @Object[][
        @User[User{
    
    id=null, name='newboy', password='123'}],
        @StandardSessionFacade[org.apache.catalina.session.StandardSessionFacade@2a57d000],
    ],
    @String[forward:/student/list],
]
method=com.itheima.controller.StudentController.findAll location=AtExit
ts=2023-08-21 20:55:52; [cost=6.0088ms] result=@ArrayList[
    @Object[][isEmpty=true;size=0],
    @ModelAndView[
        view=@String[list],
        model=@ModelMap[isEmpty=false;size=1],
        status=null,
        cleared=@Boolean[false],
    ],
]
  1. 호출 링크 및 노드 시간 소모 분석: 추적 명령을 사용하여 컨트롤러 처리 방법의 호출 링크 및 각 노드에 소요된 시간을 가져옵니다.

com.itheima.controller.* 로그인 추적

여기에 이미지 설명을 삽입하세요
우리는 이 컨트롤러가 가장 시간이 많이 걸리는 메소드 "com.iheima.service.UserService:login()"을 호출하는 것을 발견했습니다.

  1. 따라서 우리는 이 비즈니스 계층의 로그인 방법을 계속해서 분석할 수 있습니다.

com.itheima.service.UserService 로그인 추적

그 결과, 데이터베이스에 접근하기 위한 com.iheima.dao.UserDao:login() 메소드가 가장 시간이 많이 걸리는 것으로 나타났으며, 요청을 처리하는 데 IO 작업이 대부분의 시간을 차지하는 경우가 많다는 것을 알 수 있습니다. .

Affect(class count: 3 , method count: 2) cost in 78 ms, listenerId: 12
`---ts=2023-08-21 21:10:42;thread_name=http-nio-8080-exec-3;id=1a;is_daemon=true;priority=5;TCCL=org.apache.catalina.loader.ParallelWebappClassLoader@64e2f243
    `---[7.7167ms] com.sun.proxy.$Proxy25:login()
        `---[28.93% 2.2322ms ] com.itheima.service.impl.UserServiceImpl:login()
            `---[98.83% 2.206ms ] com.itheima.dao.UserDao:login() #17
  1. 생성된 프록시 메소드를 보고 jad 명령을 사용하여 디컴파일합니다.

jad com.sun.proxy.$Proxy24 로그인

ClassLoader:

  +-java.net.URLClassLoader@1c4af82c
    +-sun.misc.Launcher$AppClassLoader@764c12b6
      +-sun.misc.Launcher$ExtClassLoader@3d82c5f3

Location:

public final User login(User user) {
    
    
    try {
    
    
        return (User)this.h.invoke(this, m3, new Object[]{
    
    user});
    }
    catch (Error | RuntimeException throwable) {
    
    
        throw throwable;
    }
    catch (Throwable throwable) {
    
    
        throw new UndeclaredThrowableException(throwable);
    }
}

2.1.4 세 번째 단계: 코드 최적화

  1. SQL 최적화:

참고: 이 프로젝트에서 가장 시간이 많이 걸리는 방법은 com.sun.proxy.$Proxy25:login()경로가 있는 프록시 방법입니다. 이 방법은 mybatis 플러그인에 의해 생성됩니다. 일반적으로 변경할 수 없습니다. 데이터베이스에 액세스하는 데 실제로 시간이 많이 걸리는 경우 sql문을 수정하고 조정하는 것도 가능합니다.데이터베이스 관련 파라미터

  1. 요청을 처리하는 비즈니스 계층 방법이 매우 시간이 많이 걸리는 경우 코드 최적화에는 일반적으로 바이트코드 파일 수정이 포함되므로 dump 명령을 사용하여 비즈니스 메서드가 있는 바이트코드 파일을 다른 디렉터리에 저장해야 합니다. 6단계에서 구체적인 구현 클래스를 얻습니다. -com.itheima.service.impl.UserServiceImpl:login() 메서드는 시간이 많이 걸리므로 지금 개선해야 합니다.

복구를 위해 UserServiceImpl 클래스를 다른 디렉터리에 저장합니다.

덤프 com.itheima.service.impl.UserServiceImpl > /root/UserServiceImpl.java

UserServiceImpl 구현 클래스를 지정된 디렉터리로 디컴파일하고,

jad --source-only com.itheima.service.impl.UserServiceImp > /root/UserServiceImpl.java

로컬 아이디어나 vim 편집기에서 /root/UserServiceImpl.java 파일을 수정하고 mc 명령을 사용하여 Java 파일을 /root/bbb/ 디렉터리로 컴파일합니다.

mc -d /root/bbb/ /root/UserServiceImpl.java

재정의 명령을 사용하여 새 바이트코드 로드

/root/bbb/UserServiceImpl.class 재정의

3 OOM 오류 문제를 해결하는 방법

Java 애플리케이션이 발생하면 OutOfMemoryError(종종 OOM으로 축약됨) 이는 사용 가능한 메모리가 모두 소모되었기 때문에 JVM이 객체에 더 이상 메모리를 할당할 수 없음을 의미합니다. 다음은 OOM 문제를 해결하는 일반적인 단계입니다.

  • 오류 메시지를 살펴보세요java.lang.OutOfMemoryError: Java heap space . OOM 오류 메시지는 일반적으로 힙 오버플로( )인지 메타스페이스 오버플로( ) 인지와 같은 추가 컨텍스트를 제공합니다 java.lang.OutOfMemoryError: Metaspace.

  • 힙 덤프 생성 : OOM이 발생하면 힙 덤프(힙 덤프)를 생성하도록 JVM을 구성할 수 있습니다. 이는 JVM 매개변수를 통해 달성할 수 있습니다: -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/path/to/dump. Eclipse MAT힙 덤프 파일은 또는 같은 도구를 사용하여 VisualVM분석 하여 많은 양의 메모리를 소비하는 개체를 찾을 수 있습니다.

  • 모니터링 도구 : , , 등의 도구를 사용하여 VisualVMJVM JConsole메모리 사용량을 실시간으로 모니터링합니다.GrafanaPrometheus

  • 로그 분석 : 비정상적인 동작이나 장기 실행 작업에 대한 애플리케이션 및 서버 로그를 검사합니다.

  • 코드 검토 : 수명이 긴 대형 개체, 제대로 정리되지 않은 컬렉션 클래스, 닫히지 않은 데이터베이스 연결 등 메모리 누수의 가능한 원인을 찾습니다.

  • JVM 매개변수 조정 : 힙 메모리 제한( -Xms-Xmx)을 늘리는 것을 고려하지만 이는 단기적인 해결 방법일 뿐입니다. 장기적으로는 여전히 OOM의 근본 원인을 찾는 것이 필요합니다.

4 실행 중인 특정 SQL 문에서 쿼리한 데이터의 양이 너무 커서 힙 OOM이 발생할 수 없는 경우 이 SQL 문을 어떻게 찾을 수 있습니까?

  • 로그 : 대규모 장기 실행 쿼리에 대해서는 데이터베이스 쿼리 로그와 애플리케이션 로그를 확인하세요. SQL 느린 쿼리 로그를 활성화하면 도움이 될 수 있습니다.

  • 모니터링 도구Performance Schema : 많은 데이터베이스에는 실행 중이거나 최근에 실행된 쿼리를 볼 수 있는 MySQL 및 MySQL 과 같은 모니터링 도구가 있습니다 Information Schema.

  • 힙 분석 : OOM 중에 생성된 힙 덤프는 어떤 개체가 많은 메모리를 차지하고 있는지 보여줄 수 있습니다. 예를 들어, Hibernate를 사용하는 경우 많은 수의 Hibernate 엔터티를 볼 수 있습니다.

  • 코드 분석 : 데이터베이스 쿼리, 특히 대량의 데이터를 반환할 수 있는 쿼리에 대한 코드를 검사하세요. 이 모든 데이터를 실제로 로드해야 하는지, 아니면 일괄적으로 로드할 수 있는지 또는 추가 필터링을 수행할 수 있는지 고려하세요.

  • 애플리케이션 모니터링 도구 : 또는 New Relic같은 도구는 애플리케이션 성능과 데이터베이스 쿼리를 모니터링하고 비용이 많이 드는 쿼리를 찾는 데 도움을 줄 수 있습니다.DynatraceElastic APM

즉, OOM을 다루기 위해서는 체계적인 조사와 다각도의 분석이 필요합니다. 데이터베이스 쿼리로 인해 발생하는 OOM의 경우 쿼리를 최적화하고 페이징, 스트림 처리 사용 등 메모리 사용량을 합리적으로 관리하는 데 중점을 둡니다.

5 주요 공장 인턴십 중 온라인 OOM 문제 해결 및 케이스 코드 최적화

5.1 배경

대규모 공장에서 인턴십을 하면서 데이터 동기화 작업에 대한 요구 사항을 맡아 LLDP 배선과 빌드 배선을 비교 판단했는데, LDP 배선은 데이터 센터의 초기 배선 상태를 기록하고, 빌드는 계획에서 배선 상태를 기록합니다. 및 구축, 그리고 향후 계획 및 시공이 실제로 구현되며, 구축 중인 것은 구현 예정이나 아직 구현되지 않았으며, 구현이 성공하면 빌드의 배선 데이터를 lldp로 교체한 후 build는 새로운 건설 계획 데이터를 저장하는 데 사용됩니다. 나에게 필요한 것은 lldp와 빌드 배선의 차이점을 비교하고 비교 정보를 새 테이블에 삽입하여 데이터 센터 운영 및 유지 관리 담당자가 볼 수 있도록 하고 건설 계획의 배선으로 lldp의 배선을 덮어쓰는 것입니다. 배선 공사를 완료합니다.

5.2 결함의 원인

lldp와 빌드 모듈은 여러 데이터센터의 내부 배선과 데이터센터 간의 실제 배선을 기록하는데, 처음에는 테스트 라이브러리의 lldp 테이블에 기록된 모든 데이터센터 배선을 직접 꺼내서 목록에 넣었습니다. 를 클릭한 다음 빌드의 모든 연결을 제거하여 두 연결을 비교합니다. select * from lldp left jon ... left join ....테스트 중에는 문제가 없었으나 온라인으로 실행한 지 얼마 되지 않아 붐이 발생하였고, 조사 결과 온라인 데이터베이스 접속 기록이 전체 데이터센터에서 수십만 건의 접속을 갖고 있기 때문에 이 문구로 인해 발생한 것으로 밝혀졌습니다. , 각 연결은 테이블 쿼리의 결과이므로 일회성 전체 테이블 쿼리는 OOM입니다.

5.3 문제 해결 단계

세 번째 단계를 참고하시면 됩니다.

Java 애플리케이션이 발생하면 OutOfMemoryError(종종 OOM으로 축약됨) 이는 사용 가능한 메모리가 모두 소모되었기 때문에 JVM이 객체에 더 이상 메모리를 할당할 수 없음을 의미합니다. 다음은 OOM 문제를 해결하는 일반적인 단계입니다.

  • 오류 메시지 또는 로그 보기java.lang.OutOfMemoryError: Java heap space : OOM 오류 메시지는 일반적으로 힙 오버플로( )인지 메타스페이스 오버플로( ) 인지와 같은 추가 컨텍스트를 제공합니다 java.lang.OutOfMemoryError: Metaspace.

  • 힙 덤프 생성 : OOM이 발생하면 힙 덤프(힙 덤프)를 생성하도록 JVM을 구성할 수 있습니다. 이는 JVM 매개변수를 통해 달성할 수 있습니다: -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/path/to/dump. Eclipse MAT힙 덤프 파일은 또는 같은 도구를 사용하여 VisualVM분석 하여 많은 양의 메모리를 소비하는 개체를 찾을 수 있습니다.

5.4 솔루션

더 작은 입도의 비교 방식을 사용하고 매번 단일 데이터 센터의 입도에 따른 차이점만 비교합니다. 이 데이터 센터를 비교한 후 다음 데이터 센터를 비교하여 각 데이터 센터의 연결 수가 0이 되도록 합니다. 100,000 이상.

추천

출처blog.csdn.net/yxg520s/article/details/132494598