Graceful Shutdown 의 오해

Kim Ju Young·2023년 11월 23일
0

네트워크

목록 보기
2/2
post-thumbnail

들어가기 전에

C++을 통해 버클리 소켓을 배우다 인터넷을 찾아보니 4 Way Handshake 인 Graceful Shutdown 이 오해하기가 쉬운 것 같아 그것을 다룰려고 한다.

C++ 소켓 함수

C++ TCP 소켓은 기본적으로 유닉스와 동일한 버클리 소켓을 사용할 수 있다. 그리고 소켓을 닫는 방법에 두가지가 있다.

shutdown()
closesocket()

보통 예제들에서도 closesocket 을 쓰기 때문에 shutdown 을 쓸 일이 없을 것처럼 보이지만 shutdown 이란 함수도 존재하긴 한다. shutdown 은 왜 쓰이고 있는 걸까?

shutdown 함수를 사용하면 우아하게 마칠(Graceful Shutdown) 수 있다. 아까부터 우아하게 종료한다고 하는데 우아하게 종료한다는 게 도대체 무엇일까?

우아한 종료(Graceful Shutdown)

우선 우아한 종료는 이번 글의 주제를 관통하는 글이다. 우아한 종료라는 말은 오해하기 쉬운 것 같다. 우선 정확한 개념으로 우아한 종료를 하는 까닭은 한 쪽에서 일방적으로 끊어낼 수 없게 하기 위해 4 Way Handshake 하기 때문에 우아한 종료라는 단어를 쓴다.

우선 여기서도 간단히 설명하겠다. A 와 B 는 서버-클라 구조에서 어느것이 되어도 상관없다. close 함수를 호출한 쪽에서 TCP 헤더의 FIN 비트를 1로 설정해서 보내준다.

그런데 여기서 마지막 FIN 을 받아야 하는 A의 소켓이 말소되어있다면 어떨까? 한 가지만 간단히 설명하겠다. 말소가 되었고 해당 포트로 새로운 소켓이 생성되었다고 해보자.

해당 포트로 FIN 이 들어와 새롭게 만들어준 소켓이 FIN을 받게되는 불상사가 일어날 수 있다. 그래서 A는 몇 분 동안 소켓이 말소되지 않고 기다린 후 소켓이 사라진다.

그런데 어떤 걸 오해한단 말인가?

위에서 설명한 것 같이 연결을 끊는 쪽(위에선 A)에서 우아한 종료를 통해 종료될 때 ACK, FIN 을 받기 전까지 소켓 말소가 안된다. 이걸 TIME_WAIT라고 하겠다. 해당 소켓 포트에서 TIME_WAIT 를 기다리게 되는데 이게 우아하지 않다고 생각할 수 있다. 이건 우아한 종료를 개념적으로 착각하는 것이다.

게다가 이 차이를 정확히 알고 있어야 한다. 왜냐하면 포트가 TIME_WAIT 으로 막히는 게 서버 입장에서 우아한 종료의 폐단이고 반드시 막아야할 점이기 때문이다.

closesocket 도 우아하게 종료한다고?

그럼 지금까지 말했던 shutdown 함수를 쓸 때만 우아한 종료가 일어나는가?

아니다.

closesocket 을 통해 닫아준 소켓도 Wireshark 를 관찰해보면 RST, 4Way Handshake 가 번갈아 나오든 절반정도로 나뉘어서 일어나는 걸 볼 수 있다.

이는 Linger 옵션을 통해 Time_wait 가 없도록 만들 수 있다.

그럼 Time_wait 에 걸리면 무엇이 안좋은가?

closesocket 을 해 준 순간 소켓은 말소는 되겠지만 TCP 연결 정보를 들고 있어야한다. 해당 연결 정보는 지속적으로 메모리를 차지하기 때문에 서버쪽에서 이 데이터를 들고 있다면 어떻게 될까? 밴할 유저가 많아져서 밴을 하고 다른 유저가 들어왔더니 time_wait 몇 십초동안 메모리가 더 늘어나게 되는 상황에 처하게 된다.

참조

shutdown() - MSDN 문서
closesocket() - MSDN 문서

profile
호호선생

0개의 댓글