빈 생명주기에 관해서 그래도 기본은 알고있다고 생각했는데 큰 오산이었다.
운영에 반영을 했는데 몇 일 뒤 최대 Connection을 초과해서 장애가 발생하였다.
원인은 Connection close가 되지 않아서였다.
AS-IS
TO-BE
왜?? 소스를 어떻게 짰길래??
샘플 소스로 확인해보자.
AServiceImpl는 매번 새로운 커넥션을 맺고 사용이 끝나면 자원을 close 하는 역할을 하고 있다.
common.xml에 Impl 클래스를 prototype으로 빈을 등록해놓았다.
<bean id="ConnectionService" class="com.example.service.impl.AServiceImpl" scope="prototype" destroy-method="close"/>
그리고 다른 클래스에서 매번 새로운 인스턴스로 사용하기 위해서 beanFactory에서 getBean을 통해 직접 해당 클래스를 가져왔다.
@Autowired
private AutowireCapableBeanFactory beanFactory;
AService = beanFactory.getBean(AServiceImpl.class);
빈 생명주기에 의해 destroy-method=close가 호출되어 AServiceImpl 클래스의 close 메소드가 동작 할 것이라고 생각했다.
하지만, 생각대로 동작하지 않아 커넥션이 초과되었고 장애가 발생하여 우선은 소스에 하드 코딩으로 close를 호출해주었다.
finally { ... AService.close(); }
왜 destroy-method가 동작하지 않았을까??
갓택오버플로우에서 해답을 찾을 수 있었다.
요약
Spring은 prototype의 scope의 전체 라이프 사이클을 관리하지 않는다.
초기화 메소드로 생성이 되고나면, 더 이상 관여하지 않는다.
왜? 좀 해주지
예를 들어 배치성 작업처럼 일정 주기마다 새로운 prototype scope의 빈을 생성하는 경우, 어플리케이션이 종료될 때 스프링에서 해당 scope들을 모두 destroy 해야 한다면, 일정 주기마다 생성된 scope bean에 대해서 참조를 유지하고 있어야한다.
따라서 메모리 누수를 유발할 수 있기 때문이다..
그러므로 명시적으로 close를 해줌으로써 커넥션이 정상적으로 종료될 수 있었다.
'Spring' 카테고리의 다른 글
자바 싱글톤 VS 스프링 싱글톤 (0) | 2020.10.22 |
---|---|
[Spring] SpringBoot + Gradle(5.x && 6.x) + Querydsl Setting (9) | 2020.09.06 |
[Spring] SpringBoot + Gradle + NPM Build 셋팅하기 (0) | 2020.08.12 |
[Spring] Restful Api example (with Hateoas) 구현 (0) | 2020.07.29 |
[Spring] @Transactional - 2 isolation (격리수준) (0) | 2020.07.09 |
댓글