외부 서버 간 http 통신 시 Socket timeout 이슈

이동욱·2023년 8월 21일

TroubleShooting

목록 보기
2/9

외부 서버 간 http 통신 시 Socket timeout 이슈

1. 개요


프로젝트 진행 중 이전에 같은 고객사에서 진행했던 프로젝트에서 버그가 해결이 안되고 있다고 들어 잠깐 봐준적이 있었다.
해당 프로젝트의 시스템 구성은 dmz에 proxy 역할의 web server 두 대가 이중화 되어있고 내부망에 was가 이중화 되어 있는 구성이었다. web was로는 webtob, jeus를 사용했다.

2. 증상


was에서 외부 서버에 http rest api 통신을 할 때 간헐적으로 발생했는데 was 서버 내 로그에는 아무 에러로그가 안찍히고 jeus 내에 SocketInputStream.readSocket0 에러로그가 나오다가 결국 서비스가 멈춰 한 두달 정도 주기로 재기동을 시켜주고 있었다고 한다.

3. 예상원인


일단 처음에 들었을 때 위 개요 부분에서 말한 시스템구성이 무언가 잘못 구성되어 발생한거 같다는 얘기를 들어 시스템 구성확인, web & was 설정 확인 등등 infra 적인 부분을 확인해봤는데 아무 이상이 없었다.

그래서 일단 jeus 로그는 SocketInputStream.readSocket0이란 에러로그니까 내가 예상한 원인은 외부 서버에 http 통신할 때 socket을 생성했지만 해당 socket에서 read하는 상황에 계속 걸려있어 해당 socket이 포함된 thread가 중단되는 상태가 지속되어 이러한 증상이 반복되기 때문에 was server 내 thread pool에서 점유할 thread가 없어 발생하는 것으로 생각했다.

4. 조치


서비스 내 코드에서 외부서버로 http 통신을 하는 부분에서 SocketConfig에서 해당 socket으로 요청을 보내고 응답을 받기까지의 timeout 설정을 추가해줬다. (SocketInputStream에서 계속 read하려는 상태에 걸려있으니깐 응답을 못받기 때문이라 예상 ...)

5. 결과


위 조치를 한 이후 같은 증상은 나오지 않았고 서비스를 재기동하는 일도 없다고 했다. 그런데 근본적으로 왜 socket input stream에서 read에 걸려있었을까 ...
예상하기로는 외부 서버의 불안정성이나 해당 요청의 장기 transaction, 네트워크 문제 등등 생각이 나지만 일단 해당 요청이 장기 transaction일만큼 그리 복잡한 요청은 아니었기 때문에 그 외적인걸 봐야하는데 내가 확인할 수 없는 영역이라 일단 이렇게 마무리 지어야할 것 같다.

6. 참고


이 버그를 tomcat 등 다른 was 서버를 사용하는 경우엔 보지 못한 버그사항이라 jeus 내에서의 thread 관련 공식 가이드도 봤는데 jeus 자체 내에 timeout을 통해 해당 thread를 block 상태로 만들고 해당 thread 삭제 후 새로운 thread를 생성하는 config가 있다고 한다. 하지만 소켓통신인 경우 timeout으로 block 상태가 되고 interrupt 신호를 보내 block 상태의 thread를 삭제하는 exception이 쉽게 발생하지 않는다고 한다.

위에 설명한 부분이 뭔가 관련이 있는거 같은데 내가 jeus 코드 등 하나하나 다 뜯어볼 순 없으니 ...

7. 고찰


해당 버그를 통해 timeout 설정 등 처음부터 구체적인 개발을 해야할 필요성을 느꼈다. 사소한거라고 생각되기 쉬운만큼 나중에 버그가 발생했을 때 찾아내기가 참 어렵다는 걸 이번에 몸소 느꼈기 때문에 ... ㅠㅠ

profile
lduk 웹 개발자(back)

0개의 댓글