i.am.developer

AWS EC2에선 왜 WebSocket 연결이 60초 후 끊길까 본문

프로그래밍/트러블슈팅

AWS EC2에선 왜 WebSocket 연결이 60초 후 끊길까

jongwow 2021. 3. 20. 00:40

문제

React Native에서 WebRTC 모듈을 개발해서 ION-SFU서버 통신하는 데모앱을 만들었는데, 로컬에선 계속 작동하던 앱이 AWS EC2에 서버를 올려 통신하자 60초 이후 통신이 끊겼다...

로그를 확인해보니까 Websocket 연결이 60초정도만 지나도 그냥 끊겨버리는 문제가 있었다. 특이한 에러메시지가 뜨면 찾아보기라도 할텐데 난데없이 에러가 나서 원인을 찾느라 조금 헤맸다.

 

설명

IonSFU에선 JsonRPC와 gRPC를 제공해서 클라이언트와 통신을 가능하게한다. 난 jsonRPC를 이용했는데 이 jsonRPC는 아래 모듈을 이용한다.

* github.com/sourcegraph/jsonrpc2

 

sourcegraph/jsonrpc2

Package jsonrpc2 provides a client and server implementation of JSON-RPC 2.0 (http://www.jsonrpc.org/specification) - sourcegraph/jsonrpc2

github.com

이 모듈은 내부적으로 gorilla Websocket을 사용한다. (golang에선 gorilla가 제일 쓸만한 것 같다.)

React Native 앱에서도 동일하게 Websocket을 이용한다.

 

결국 Client와 Server 모두 WebSocket을 이용하는데 로컬에선 계속 연결이 되던 WebSocket이 왜 서버에선 접속 종료가 됐을까?

 

원인은 물론 AWS였다. AWS에 올라간 EC2는 ELB, 그 중 ALB(L7 load balancer)에 물려있다. 이것때문에 ION-SFU에서 Websocket가 말썽이었다. 참고로 이렇게 인스턴스를 ALB에 물려서 route해주는 경우 NAT설정도 추가적으로 해줘야한다.

ALB를 이용하는 경우, 각 request마다 client는 load balancer를 거치면서 서버에 갈 때 2개의 연결이 생긴다. Client <-> LB, LB <-> EC2. LB 입장에선 당연히 연결을 갖고 있단건 자원을 소모하고 있는 것이기 때문에 정해진 Idle timeout 동안 아무런 데이터가 송수신되지 않으면 해당 연결을 끊어버린다. 기본으로 설정된 idle timeout은 60초이다. 그래서 Websocket이 60초만 유지됐던 이유이다. 참고로 HTTP 통신은 keepalive를 따로 해주면 연결이 끊기지 않는다고 한다.

 

해결방법?

대충 원인을 알았으니 해결이 필요하다. Websocket이 TCP이긴해도 HTTP keepalive를 쓸 수 있을것같진 않아보인다. 그래서 3가지 정도 해결책을 생각해봤따.

 

1. 60초 이전에 Ping/Pong 송수신. 

- 제일 이해가 가는 해결책이다. 서버단에서 구현하면 된다. 근데 jsonrpc2를 사용하고 있는데 이 모듈을 뒤집어까내서 pingpong을 구현해야한다는게 조금 흠이다. 아마 모바일 환경을 생각한다면 가끔 통신이 끊기는 경우가 발생할 수 있기 때문에 pingpong으로 하는게 좋을 것 같다. 링크: https://github.com/gorilla/websocket/tree/master/examples/chat

 

2. timeout 늘리기.

- ALB에서 idle timeout 값을 조정한다. 1초에서 4000초까지 가능하다고하는데, 설마 4000초동안 아무런 통신을 안하면 그건 그냥 통신 끊는게 맞지...ㅎ. 이 방법은 이 링크에 나와있따.

 

3. ELB를 L7(ALB)가 아닌 L4(NLB)에 물리기.

- 확실하진 않은데, L4에선 안나지 않을까... L7이니까 stateful해서 자원을 반환해주려고 저렇게 연결을 끊는 것 같은데...

- 예전에 전산실에 있을 땐 L4, L3 스위치만지면서 Load Balancer가 뭔지 대충 이해는 했지만 L7는 접할 기회가 없어서 이번에 조금 살펴본 것 같다. 직접 써봐야 더 알 수 있을거라 생각한다..

 

참고 링크

github.com/eclipse-theia/theia/issues/1410

stackoverflow.com/questions/48757522/websocket-closing-after-60-seconds-of-being-idle-while-connection-node-server-us

docs.aws.amazon.com/elasticloadbalancing/latest/application/application-load-balancers.html#connection-idle-timeout

 

'프로그래밍 > 트러블슈팅' 카테고리의 다른 글

Timestamp를 PK로 쓰는건 피하자  (0) 2021.03.25