일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- kotlin coroutine
- 코틀린 코루틴의 정석
- CloudWatch
- Linux
- kotlin querydsl
- Pinpoint
- PETERICA
- Kubernetes
- Spring
- Java
- APM
- 정보처리기사실기 기출문제
- mysql 튜닝
- CKA
- AWS EKS
- kotlin
- aws
- kotlin spring
- Elasticsearch
- MySQL
- IntelliJ
- minikube
- 공부
- 오블완
- 티스토리챌린지
- 정보처리기사 실기 기출문제
- AI
- 기록으로 실력을 쌓자
- CKA 기출문제
- 정보처리기사 실기
- Today
- Total
피터의 개발이야기
[Spring] netty tcpClient 설정방법, Read Timeout을 1초로 설정했는데 1.5초가 걸리는 이유 본문
[Spring] netty tcpClient 설정방법, Read Timeout을 1초로 설정했는데 1.5초가 걸리는 이유
기록하는 백앤드개발자 2025. 2. 7. 12:54ㅁ 들어가며
ㅇ Netty TcpClient를 설정하는 방법을 정리하였다. 알람 개선을 위해 TcpClient 소스를 분석하면서 알게된 내용을 정리해보았다.
ㅇ RequestTimeout이 너무 짧으면 오류에 대한 알람이 자주 발생하고, 그만큼의 side-effect가 발생한다. 하지만 너무 길게 설정하면 리소스 자원의 낭비가 발생할 수 있다.
ㅇ tcpClient가 동시에 처리할 수 있는 pool의 유휴자원을 확보하고 알람의 적절한 발생을 컨트롤 하기 위해 MSA구조에서 각 레벨에서의 적절한 수준의 timeout 설정은 필수이다.
ㅁ 기본 설정
ㅇ TcpClient 인스턴스 생성
TcpClient tcpClient = TcpClient.create();
ㅇ 호스트 및 포트 설정
tcpClient = tcpClient.host("example.com").port(80);
ㅁ 고급 설정
ㅇ 연결 타임아웃 설정
tcpClient = tcpClient.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 3000);
ㅇ 연결 풀 설정
기본적으로 TcpClient는 "고정" 커넥션 풀을 사용하며, 최대 채널 수는 500개, 대기 중인 요청의 최대 수는 1000개이다. 커스텀 설정을 위해 ConnectionProvider를 사용할 수 있다.
ConnectionProvider provider = ConnectionProvider.builder("fixed")
.maxConnections(50)
.pendingAcquireTimeout(Duration.ofMillis(30000))
.maxIdleTime(Duration.ofMillis(60))
.build();
TcpClient tcpClient = TcpClient.create(provider);
ㅇ 타임아웃 설정: 읽기 및 쓰기 타임아웃을 설정할 수 있다.
tcpClient = tcpClient.doOnConnected(connection ->
connection.addHandlerLast(new ReadTimeoutHandler(3000, TimeUnit.MILLISECONDS))
.addHandlerLast(new WriteTimeoutHandler(3000, TimeUnit.MILLISECONDS)));
ㅇ SSL/TLS 설정: 보안 연결이 필요한 경우
tcpClient = tcpClient.secure();
ㅇ 와이어 로깅 활성화: 디버깅을 위해 와이어 로깅을 활성화할 수 있다.
tcpClient = tcpClient.wiretap(true);
이러한 설정들을 조합하여 TcpClient를 구성할 수 있으며, 최종적으로 connect()
메서드를 호출하여 연결을 시작한다.
ㅁ Read Timeout을 1초로 설정했는데 1.5초가 걸리는 이유
tcpClient에서 Read Timeout을 1초로 설정했는데도 1.5초로 동작할 수도 있다. 왜냐하면, 이유는 여러 가지가 있겠지만, 주된 원인은 Reactor Netty의 이벤트 루프 동작 방식과 내부 타이머 스케줄링 방식, GC 때문이다.
Reactor Netty의 이벤트 루프 딜레이
ㅇ Reactor Netty는 비동기 논블로킹 이벤트 루프를 사용한다.
ㅇ ReadTimeoutHandler는 이벤트 루프에서 동작하며, 정확히 1초 후에 즉시 트리거되지 않을 수도 있다.
ㅇ 상황에 따라 0~500ms 정도의 지연이 추가될 수 있다.
타이머 스케줄링 오차
ㅇ ReadTimeoutHandler는 내부적으로 Netty의 HashedWheelTimer 를 사용하여 타이머를 관리한다.
ㅇ 이 타이머는 정확한 밀리초 단위가 아니라, 버킷 방식으로 동작한다.
ㅇ 따라서 1초로 설정해도 실제 타이머 실행 시점은 1.0초 ~ 1.5초 사이에서 실행될 수 있다.
GC(Garbage Collection) 영향
ㅇ 만약 애플리케이션이 GC를 수행하는 동안 이벤트 루프가 잠시 멈추면 타이머 실행이 지연될 수 있음.
ㅇ 특히 JVM의 Stop-The-World (STW) 이벤트가 발생하면 타임아웃이 지연될 수 있음.
ㅁ timeout() 연산자 사용
ㅇ Netty의 내부 타이머를 사용하지 않고, timeout( )을 사용하면 보다 정확하게 제어 가능하다.
webClient.get()
.uri("https://example.com/api")
.retrieve()
.bodyToMono(String.class)
.timeout(Duration.ofSeconds(1)) // 요청별로 정확한 1초 timeout 적용
.onErrorResume(TimeoutException. class, ex -> Mono.just ("Timeout 발생"));
ㅁ 함께 보면 좋은 사이트
ㅇ 리액터 네티(Reactor Netty)로 간단한 TCP 서버 만들기
'Programming > Spring' 카테고리의 다른 글
[Spring] @Cacheable 사용법 (1) | 2024.11.27 |
---|---|
[Spring] JIB으로 JAVA 애플리케이션 컨테이너화하기 (2) | 2024.11.15 |
[Spring] RestTemplate의 Connection Timeout 설정과 에러 패턴 (0) | 2024.11.14 |
[Spring] Hadoop- Hive 컨넥션 유지 방법, @Scheduled (0) | 2024.10.28 |
[Spring] embedded Tomcat을 사용할 때 메모리가 누적 경우 (0) | 2024.10.22 |