개요
기존에 Excel 생성 및 다운로드 기능을 구현하는 코드를 공유했었습니다.
https://jaimemin.tistory.com/1768
https://jaimemin.tistory.com/2069
https://jaimemin.tistory.com/2096
https://jaimemin.tistory.com/2191
해당 기능을 구현하고 한동안 문제가 없었는데 여러 사용자가 동시에 대용량 데이터를 엑셀로 다운로드하면서 Out of Memory Exception이 발생하면서 상용 서버가 다운되는 문제가 발생했습니다.
동시에 여러 쓰레드가 대용량 데이터를 다운로드를 시도하다 보니 서버 CPU 사용량이 98%에 육박했고 이때 GC가 발동하면서 OOM 예외가 발생했던 것입니다.
OOM 원인
기존에 작성한 엑셀 다운로드 기능은 크게 두 가지 문제점이 있었습니다.
1. 리스트를 불러올 때 페이징을 적용하지 않고 한번에 불러왔으며
2. 엑셀을 생성할 때 주기적으로 memory flush를 진행하지 못했습니다.
위 두 문제점 때문에 앞서 개요에 언급한 것처럼 CPU 사용량이 급격히 올라갔고 이때 GC가 발동하면서 서버가 죽었습니다.
또한, 기존 코드에서도 다행히 SXSSFWorkbook을 사용했는데 SXSSFWorkbook은 다른 workbook과 달리 streaming api를 사용하기 때문에 대용량 데이터 다운로드에 용이합니다.
해결 코드
원인에서도 이미 언급했지만 아래의 두 가지 코드를 적용하면 해결이 됩니다.
1. 리스트를 불러올 때 페이징을 적용하여 여러차례에 걸쳐 불러오고
2. 엑셀을 생성할 때 주기적으로 memory flush를 진행합니다.
ExcelController.java
ExcelService.java
ExcelView.java
* 위 코드를 보면 리스트를 한번에 불러오지 않고 만개씩 끊어서 불러오는 것을 볼 수 있고 SXSSFWorkbook도 주기적으로 flush 해주는 것을 확인할 수 있습니다!
* 2021-10-14: 코드가 조금 수정되었습니다. 자세한 이유는 아래 포스팅을 참고해주세요.
https://jaimemin.tistory.com/1996
요청하는 클라이언트 사이드 (jQuery 예시)
* 2021-10-21 추가 코멘트: gateway timeout이 설정되어있을 경우 데이터 양이 많아 time-out이 발생할 수 있습니다.
참고자료
https://roytuts.com/handling-large-data-writing-to-excel-using-sxssf-apache-poi/
https://stackoverflow.com/questions/48040638/how-to-insert-a-linebreak-as-the-data-of-a-cell
'[DEV] 기록' 카테고리의 다른 글
[Git] git repository들을 하나의 repository로 합치는 방법 (0) | 2021.08.18 |
---|---|
[H2] Database not found, either pre-create it or allow remote database creation (0) | 2021.08.16 |
[SpringBoot] HV000232: No JSR 223 script engine found for language "javascript" (0) | 2021.07.24 |
[SpringBoot] Excel 생성 및 다운로드 (0) | 2021.05.17 |
티스토리 블로그 내 gist css 수정하는 방법 (0) | 2021.04.25 |