IT/Java

javax.net.ssl.SSLException: Connection reset 해결하기

yeTi 2022. 5. 12. 21:57

안녕하세요. yeTi입니다.
오늘은 RestTemplate 으로 외부 연계시 간헐적으로 javax.net.ssl.SSLException 이 발생한 현상을 해결한 방법을 공유하고자 합니다.

증상

외부 서비스에 RestTemplate 으로 HTTP 요청시 대략 5건에 한건정도 아래와 같이 오류가 발생했습니다.

javax.net.ssl.SSLException: Connection reset
    at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:127)
    at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:349)
...
Caused by: java.net.SocketException: Connection reset
    at java.base/java.net.SocketInputStream.read(SocketInputStream.java:186)
    at java.base/java.net.SocketInputStream.read(SocketInputStream.java:140)
    at java.base/sun.security.ssl.SSLSocketInputRecord.read(SSLSocketInputRecord.java:478)
...

원인 분석

javax.net.ssl.SSLException: Connection reset 관련하여 구글링 결과 요청을 받은 SSL 서버에서 SSL 메세지를 해석하지 못할때 발생하는 이슈라고 인식했습니다. (https://bugs.openjdk.java.net/browse/JDK-8268965, 하단에 보면 TLSv1.2TLSv1.3 을 사용하면 된다고 했지만 무슨말인지 몰랐습니다..ㅜ)

하지만 왜 SSL 메세지를 간헐적으로 해석하지 못하는지 이해가 되지 않았습니다.

계속해서 비슷한 케이스의 이슈를 발견했지만 TLS 이슈라는 것만 짐작할 뿐 원인이 짐작가지 않았습니다.(https://developer.apple.com/forums/thread/130556)

그래서 네트워크쪽에서 근거를 찾을 수 없을까라는 고민으로 조치를 하기 시작했습니다.

조치

인프라에서 조치

인프라 엔지니어가 LB 단에서 http connection 관련 옵션을 수정해본다는 피드백을 받았지만 이후 모니터링상 개선된 지표가 보이지 않았습니다.

RestTemplate 커넥션 수 조절

인프라에서 원인을 찾지 못하여 혹시나 하는 마음으로 커넥션 수timeout 시간을 늘려보는 조치를 취해봤습니다.

HttpClientMaxConnTotal, MaxConnPerRoute, ReadTimeout, ConnectTimeout 을 기본값보다 여유롭게 설정 후 일주일간 모니터링을 했지만 증상이 개선되지 않았습니다.

Connection을 재사용하지 않도록 수정

이후 구글링 결과 Connection을 재사용하지 않도록 수정 하여 개선됬다는 글을 발견하여 동일하게 조치해보기로 합니다.

HttpClientConnectionReuseStrategyNoConnectionReuseStrategy.INSTANCE 로 설정했더니 오류 발생 건수가 크게 개선되어 하루기준 몇건정도가 발생하는 수준으로 줄었습니다.

Request 실패시 재시도하도록 설정 추가

남은 잔여건에 대한 오류를 해결하기 위해 실패시 재시도하도록 보완해 봅니다.

HTTP Request가 실패했을 때, 재시도하도록 설정을 추가했습니다.
@Retryable(value = SSLException.class, maxAttempts = 2, backoff = @Backoff(delay = 1000))

일주일간 모니터링결과 더이상 javax.net.ssl.SSLException: Connection reset 이 발생하지 않는것을 확인하고 최종적으로 이슈가 해결되었다고 판단했습니다.

다른 지식

HttpClient의 sslcontext설정에서 TLS -> TLSv1.2로 변경후 문제가 해결되었다는 자료가 있습니다.
지금까지의 자료를 종합해보면 가장 근본적으로 해결할 수 있는 방법이라고 생각됩니다.

이 후 기회가 된다면 해당 방법으로 조치해보는게 좋아보입니다.