2023. 1. 24. 23:15ㆍNetwork
Connection reset by peer
io.netty.channel.unix.Errors$NativeIoException: readAddress(..) failed: Connection reset by peer
Spring cloud gateway 도입을 위해 dev 환경에 배포를 해놓고 Monitoring 중이었습니다.
간간히 발생하는 500 에러... 에러 메시지는 위와 같았습니다.
처음에는 backend 서버에서 connection을 어떤 오류와 같은 이유로 단순히 connection이 끊어지는 건가? 라고 추측하고, 관련해서 backend와 연동해서 로그를 보기위해 Sleuth를 적용하고 trace-id를 이용해서 해당 이슈가 발생할때 backend server에는 무슨일이 일어나는 가, 확인을 해보고자 했습니다.
하지만 예상과 달리 문제가 발생하는 trace-id를 가진 request는 backend 서버에 실제로 당도하지도 못한다는 사실을 확인하고는 이 문제가 단순하지 않다는 불안감에 휩쌓이게 되었습니다.
이게 어디서 끊기는 것일까 고민을 하다가 의심을 해보게 된건 AWS Network lb 였습니다.
backend 까지 도달하지는 못하고, Spring cloud gateway는 어딘가와 연결은 시도하며 끊기는 걸로 봐서는 가운데 있는 network loadbalancer 이외에는 의심할 곳이 없었습니다.
실제로 nlb의 모니터링을 살펴보니 connection reset에 대한 기록이 보였습니다.
관련해서 인터넷을 통해 문제의 힌트를 발견할 수 있었습니다.
내용인 즉슨 Idle timeout에 대한 것 이었습니다.
ALB의 경우에는 옵션이 명확하게 기본 1분으로 존재하고 조절이 가능합니다.
이는 정해진 시간동안 Connection pool을 맺어놓고 일정시간동안 왕래가 없을 경우 끊어지는 것 동작입니다.
NLB의 경우에는 이 값이 조절이 안되는 데 내부적으로 350초로 설정이되어져 있다고 합니다.
Spring cloud gateway의 경우 Routing시 이 값이 기본 무제한 입니다.
ConnectionProvider.java
/**
* Default max idle time, fallback - max idle time is not specified.
*/
long DEFAULT_POOL_MAX_IDLE_TIME = Long.parseLong(System.getProperty(
ReactorNetty.POOL_MAX_IDLE_TIME,
"-1"));
그러므로 NLB에서 끊은 Connection을 가지고 Spring cloud gateway가 connection을 시도하면 이 에러가 발생하는 것 입니다.
해결책은 Spring cloud gateway에서 이미 끊어진 Connection을 사용하지 말아야하는 것 이었습니다.
방법은 과감하게 먼저 끊어버리는 것... 350초가 되기 전에 미리 끊어야하니, 300초로 idle timeout을 설정하고 테스트를 다시 해보기로 했습니다.
cloud:
gateway:
httpclient:
pool:
max-idle-time: 300000
다행이 문제가 더이상 발생하지 않음을 확인할 수 있었습니다.
당연히 적긴해도 꾸준히 간간히 데이터가 오가는 상황이었기에 idle timeout에 도달할 것이라고는 생각을 못했습니다. 이 뜻은 Connection pool 이 적어도 Round robbin으로 분배되는 것이 아니라는 의미라고 봐야할 것 같습니다.
오늘도 새로운 지식을 하나 얻었습니다!
'Network' 카테고리의 다른 글
커널 파라메터 tcp_tw_recycle 이슈 (0) | 2024.02.07 |
---|