Spring RestTemplate을 사용하여 대용량 업로드 처리

KHS·2022년 9월 6일
0

trouble shooting

목록 보기
3/3
post-thumbnail

요건

  • 화면에서 입력받은 String key 값과 첨부 파일을 원격지 서버에 업로드
  • 첨부 파일의 크기는 약 2 GB 이상
  • Content-Type은 다음과 같음
    • 화면 -> 백엔드 multipart/form-data
    • 백엔드 -> 원격지 서버 multipart/form-data
  • JVM 메모리 옵션은 -Xmx6g로 설정되어 있음

사용 코드

MultiValueMap<String, Object> uploadParam = new LinkedMultiValueMap<>();
uploadParam.add("key", key);
uploadParam.add("file", file.getResource());

//헤더 설정
HttpHeaders uploadheaders = new HttpHeaders();
uploadheaders.setContentType(MediaType.MULTIPART_FORM_DATA);

HttpEntity<?> uploadEntity = new HttpEntity<>(uploadParam, uploadheaders);

RestTemplate restTemplate = new RestTemplate();

ResponseEntity<String> uploadResponseEntity = restTemplate.exchange(
  "http://%s:%d/data/upload".formatted(
	  serverEntity.getServiceServerIp(),
	  serverEntity.getServiceServerPort()
	),
  HttpMethod.POST,
  uploadEntity,
  String.class
);

오류 로그

c.s.v.config.ExceptionAdviceConfig - Handler dispatch failed; nested exception is java.lang.OutOfMemoryError: Required array length 2147483639 + 386 is too large
org.springframework.web.util.NestedServletException: Handler dispatch failed; nested exception is java.lang.OutOfMemoryError: Required array length 2147483639 + 386 is too large

원인 분석

해결 방안

  • ClientHttpRequestFactory의 메소드 중 setBufferRequestBody의 주석 내용

    Indicate whether this request factory should buffer the request body internally.

    Default is true. When sending large amounts of data via POST or PUT, it is recommended to change this property to false, so as not to run out of memory.

  • 현재 발생하고 있는 오류인 OOM 오류와 연관되어 있는 것으로 판단하여 해당 값을 설정하여 RestTemplate 생성

수정 코드

SimpleClientHttpRequestFactory simpleClientHttpRequestFactory = new SimpleClientHttpRequestFactory();
simpleClientHttpRequestFactory.setBufferRequestBody(false);

RestTemplate restTemplate = new RestTemplate(simpleClientHttpRequestFactory);

기타 사항

  • 기본 값이 무한대로 설정되어 있는 타임아웃 같은 파라미터도 ClientHttpRequestFactory의 구현체를 통해 설정 가능
  • 자주 사용하게 된다면 Spring Bean으로 등록하여 @Autowired로 주입 가능
profile
Java & Vue ...

0개의 댓글