.NET에서는 HttpClient를 통해 HTTP 통신을 많이 합니다. 물론 RestSharp도 많이 쓰지만요. 포트관리가 디테일하게 어떻게 되는지 모르겠어서 쓰지 않고 있습니다.
HTTP 통신 프로세스 중 TCP를 이용한 프로세스를 보면 소켓을 닫을 때 CLOSE_WAIT 상태로 Hang이 걸려서 더 이상 프로세스가 진행이 되지 않는 경우를 종종 볼 수 있습니다. 저도 현재 가끔 겪고 있습니다. 저의 경우는 클라이언트 콘솔 프로젝트에서 가끔 겪고 있어서, 이 경우 그냥 모니터링하고 있다가 netstat을 CMD에 쳐보고 CLOSE_WAIT이 다수의 포트에 걸려 있을 경우 프로그램을 종료하고 2분 정도 후에 프로그램을 다시 시작하곤 합니다.
하지만 이런 행위의 작업은 추후 docker 이미지로 빌드해서 컨테이너로 동작할 때는 자동화 되지 않은 방법이라 사용할 수 없기에 이 경우 어떻게 reset 해야하나 고민입니다. 반복적으로 CLOSE_WAIT 상태에 있다면 코드에 어떤 문제가 있어서 네트워크 통신이 중지되는 것 일텐데 발생할 때도 있고 발생하지 않을 때도 있습니다.
CLOSE_WAIT이 걸리지 않는 노하우나, CLOSE_WAIT을 감지했을 때 프로세스를 재시작하는 방법이 따로 있을까요?
추가적으로, 이것이 TCP일 때 생기는 문제점인데 곧 출시될 QUIC은 UDP 방식이니까 이런 현상이 없어질까요?
저또한 QUIC의 스팩을 뚫고 있지는 않으므로 모르지만, 아마도… CLOSE_WAIT 문제는 왕왕 벌어질 수 있는, 어쩌면 TCP 설계상의 문제라고도 할 수 있는 문제로 보이니, QUIC의 연결상태에서는 개선되지 않았을까 하는 추측을 해봅니다.
어쨌든, TCP나 UDP나 물리적 단선은 감지하지 못해요. 결국에는 heartbeat에 의해 의도치 않은 끊어짐을 감지할텐데, 재밌는건 QUIC는 심지어 IP가 변경되어도 잘 연결을 유지한다 합니다. 연결을 식별하는게 IP가 아니라 연결 ID라고 해요. 해서 QUIC와 홀펀칭과 궁합이 잘 맞을것이라는 기대감이 있습니다.
재미있는 문제군요. 혹시 HttpClient를 전역으로 정적 인스턴스를 만들어 쓰시나요? 아니면 사용할 때마다 생성해서 쓰시나요?
그리고, 원래 CLOSE_WAIT은 명백히 응용 프로그램의 버그 수준으로 봐야 합니다. 이것이 발생하는 것은, 위에서 @dimohy 님이 올려주신 4-way handshake 다이어그램에도 나오지만 상대측에서는 소켓 close를 했지만 우리 측에서는 명시적으로 소켓 close를 하지 않은 것입니다.
내용 정정: CLOSE_WAIT은 우리 측에서 close를 하지 않으면 (윈도우의 경우) 2분 정도 후에 제거됩니다. ^^;
Console App에서 Generic Host & IHttpClientFactory를 통해 사용 중입니다. 물론 HttpClient 통신할때마다 객체를 새로 만들어서 사용하지는 않고, Base Uri이 여러개 필요한 경우가 있어 최초 생성자에서 5개만 생성해서 각자 역할에 맞게 실행됩니다. 위의 설명에서 가끔씩 Hand이 걸린다는 것은 그 5개 중 HttpClient 1개를 사용했을 때 생기는 문제입니다. 매번 발생하지는 않습니다…
HTTP 통신에 관심이 많아서 검색하다보니 정성태님 블로그 글도 보게 되었니다. 질문 글에 2분 후에 다시 시작한다는 것도 정성태님 블로그 글에서 보고 그렇게 수행했던 것입니다 ㅎㅎ 유익한 정보 감사드립니다!!
정보 공유 목적으로, 제가 보고 .NET HTTP 이해에 대해 도움이 되었던 글을 링크하겠습니다.