우아한테크 세미나Java의 미래 Virtual Thread

KIMYEONGJUN·2024년 4월 23일
0
post-thumbnail

목표

오늘 세미나에서 Java 관련된 부분을 제대로 공부해서 내가 써먹을 수 있도록 하는게 내목표이다.

오늘 세미나 관련된 목차이다.

우아한 형제들에서는 2021년부터 게이트웨이 시스템 개발에 대해서 고민을 먼저했던것같다.

Virtual Thread는 Java의 새로운 동시성 기능 중 하나로, 가상 스레드를 생성해 non-blocking 방식으로 코드를 실행할 수 있게 해주는 기능이다.

가장 큰 장점은 blocking I/O를 non-blocking I/O처럼 쉽게 처리할 수 있다는 것이다. 예를 들어 데이터베이스나 네트워크 I/O와 같은 작업을 할 때, 기존에는 별도의 스레드를 생성하거나 콜백 방식으로 처리했어야 했다. 하지만 Virtual Thread를 사용하면 이를 별도의 스레드 없이 가상의 non-blocking 스레드에서 수행할 수 있다.

Virtual Thread 장점

사용 메모리 크기가 작다.
OS가 아닌 JVM내 스케줄링을 할 수 있다.

Virtual Thread 단점

새로운 기술이기 때문에 실무에서의 대규모 적용하기 어렵다.
Blocking 코드와 섞여 사용 시 교착 상태 발생 가능하다.

코드로 구현했을때

public static void main(String[] args) {
	List<Tread> threads = IntStream.range(0, 1_000_000)
		.mapToObj(i -> new Thread(() -> {}))
		.toList();
	threads.forEach(Thread::start);
}

위 코드를 실행했을때 31sec, 632ms 가 걸렸다. 100만개의 스레드를 생성하고 있어서 성능측면에서 좋지 않다고 생각이 들었다.

public static void main(String[] args) {
	List<Tread> threads = IntStream.range(0, 1_000_000)
		.mapToObj(i -> Thread.ofVirtual().unstarted(() -> {}))
		.toList();
	threads.forEach(Thread::start);

위 코드를 실행했을때 375ms 가 걸렸다. 두번째 코드가 성능적인 측면에서 훨씬 더 빠르게 느껴졌다.

Virtual Thread 동작원리

1.실행될 virtual thread의 작업인 runContinuation을 carrier thread의 workQueue에 push 한다.
2.Work queue에 있는 runContinuation들은 forkJoinPool에 의해 work stealing 방식으로 carrier thread에 의해 처리된다.
3.처리되던 runContinuation들은 I/O, Sleep으로 인한 interrupt나 작업 완료 시, work queue에서 pop되어 park과정에 의해 다시 힙 메모리로 되돌아간다.

기존 스레드 모델 서버와 비교

장점
적은 수의 네이티브 스레드에서도 병렬 처리 성능 뛰어나다.
불필요한 리소스 사용이 적어 효율적이다.

단점
복잡한 동시성 문제 시 디버깅이 더 어려워질 수 있다.
성능 저하나 데드락 위험이 있다.

성능테스트

성능테스트에서는 I/O Bound 작업은 더 높은 처리량이 보여주고있다.
CPU Bound 작업은 더 낮은 처리량을 보여주고있다.

서비스 적용시 주의사항

주의사항으로는 Blocking carrier thread(Pin)
캐리어 스레드를 block하면 Virtual Thread 활용을 할 수 없다.
병목 가능성이 존재한다.
사용 라이브러리 release 점검이 필요하다.
변경 가능하다면 java.util의 ReentrantLock을 사용하도록 변경해야한다.

No Pooling
CPU bound task
경량 스레드
배압

결론
Virtual Thread는 가볍고 빠르다. nonblocking인 경량 스레드
Virtual Thread는 JVM 스케줄링 + Continuation
Thread per request 사용중이고 I/O blocking time이 주된 병목인 경우 고려해야한다.

쉽게 적용가능하다.
Reactive가 러닝커브로 부당되는 경우
Kotlin coroutine이 러닝커브로 부담되는 경우

마무리

오늘 세미나에서 Virtual Thread 관련된 부분을 소개와 동작원리 기존 모델 서버와 비교 서능 테스트 등을 들으면서 처음에는 이게 무슨 소리인지는 잘몰랐지만 천천히 관련개념을 찾아서 공부할 수 있는 계기가 된것같다.

profile
Junior backend developer

0개의 댓글