개발 오류 및 해결 방안

많은 데이터를 처리할 때 - OutOfMemoryError

레알윙 2020. 4. 23. 13:01
반응형

오류 발생 이유

 

방재회사 회사 특성상 실시간으로 들어오는 데이터를 분석하여 피해결과를 구하는 부분이 많았고,

 

금융 회사처럼 피해결과에 대해 구하는 부분에 대해 보수적으로 대하는 부분이 있었다.

 

그렇기 때문에 소규모 테스트에서는 발생되지 않았던 오류가 실제 운영서버로 가면서 발생되는 오류가 생겼다.

 

하나의 지역(시군구)에 대한 피해액을 계산 할 때는 문제가 없었으나 이게 전국으로 확장이 되면서 많은 데이터를 가져오거나 insert를 할 때 발생이 되었다. 

 

오류 결과는 아래와 같다.

 

java.util.concurrent.ExecutionException: java.lang.OutOfMemoryError: GC overhead limit exceeded
   at java.util.concurrent.FutureTask.report(FutureTask.java:122)
   at java.util.concurrent.FutureTask.get(FutureTask.java:192)
   at org.apache.coyote.AbstractProtocol.startAsyncTimeout(AbstractProtocol.java:603)
   at org.apache.coyote.AbstractProtocol$1.run(AbstractProtocol.java:591)
   at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
   at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308)
   at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180)
   at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294)
   at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
   at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
   at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
   at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.OutOfMemoryError: GC overhead limit exceeded
   at java.util.concurrent.ConcurrentHashMap$KeySetView.iterator(ConcurrentHashMap.java:4578)
   at java.util.Collections$SetFromMap.iterator(Collections.java:5516)
   at org.apache.coyote.AbstractProtocol$2.run(AbstractProtocol.java:613)
   ... 8 more

 

위의 오류 결과가 나오는 이유는 크게 2가지로 나뉜다.

  • CPU 사용량중 98%이상이 GC가 작동되는 경우 GC Overhead limit exceeded가 발생이 된다.
    • 대부분의 GC가 CPU를 사용하기 있기 때문에 user work은 작동이 되지 않는다.
  • 한정된 Heap Memory안에서 GC 대상의 객체는 없지만 새롭게 생성되는 객체가 메모리를 할당하지 못할경우에 GC의 시간이 길어지게된다.

 

 

오류 결과 해결을 위해 처음 내가 한 작업은 local PC 및 개발서버의 메모리의 사용량을 늘려주는 것이다.

-XX:permSize=1024m
-Xms4096m
-Xmx6144m
-XX:MaxPermSize=6144m

위와같이 메모리 사용량을 늘렸고, local PC 및 개발서버에 테스트를 진행하였으나 같은 오류가 발생이되었다.

 

이 후 몇 번의 테스트를 진행하였으나, 한 번에 계산하면 메모리 오류가 발생하는 것을 인지하고, 일부의 데이터만 가지고와서 테스트를 진행을 하였다. 

 

테스트는 성공적이었다.

 

이 후 해당 모듈 및 다른 모듈들에 대하여 같은 오류가 발생하지 않게 페이징 형태로 수정하여 테스트를 진행하였고, 해당 오류는 발생하지 않았다..

 

 

다른 방법은 GC overhead limit exceeded Option 을 끄는 것이다.  -> 추천을 하지 않음

  -> 원인을 찾아야함

 

결론

많은 데이터를 처리(= 메모리상에서 데이터를 처리하는 경우)할 때 (DB Connection 시간이 긴 경우) 한꺼번에 처리하지 말고, 페이징형태로 데이터를 처리해야 한다.

 

 

 

 

 

 

 

참고

https://helloino.tistory.com/97

https://m.blog.naver.com/PostView.nhn?blogId=clotho95&logNo=140047605746&proxyReferer=https:%2F%2Fwww.google.com%2F

반응형