실시간으로 값을 밀어 주는 스트림을 만들었는데 화면이 멈춘다는 제보가 왔다. 값이 안 바뀌는 상태로 계속 남아 있었다.
Table of contents
Open Table of contents
데이터 없음과 연결 끊김
값이 안 오는 이유는 변화가 없는 것과 연결이 끊긴 것 둘이다. 앞은 정상이고 뒤는 고장인데 받는 쪽에서는 둘 다 아무것도 안 오는 상태로 같다.
전송 계층도 데이터를 안 보내는 동안에는 끊김을 감지하지 못한다. 중간의 프록시가 유휴 연결을 정리해도 양쪽이 한동안 모르는 구간이 생긴다.
의미 없는 바이트를 주기적으로
해결은 변화가 없어도 주기적으로 무언가를 보내는 것이었다. 클라이언트가 무시하는 주석 줄을 보내면 화면에는 아무 영향이 없고 바이트만 흘러간다.
연결이 유지되고 그것마저 안 오면 끊겼다는 판단 근거가 된다. 주기는 중간 계층의 유휴 시간 제한보다 짧게 잡아야 정리되기 전에 신호가 지나간다.
클라이언트도 판단하게 한다
서버가 보내는 것만으로는 부족해서 받는 쪽이 마지막 수신 시각을 기록하게 했다. 일정 시간 이상 아무것도 안 오면 스스로 끊고 다시 붙는다.
보내는 쪽만 신호를 만들고 받는 쪽이 그것을 판단하지 않으면 신호가 있어도 아무 일도 안 일어난다. 주석 줄도 수신으로 치므로 조용한 시간에도 판단 근거가 갱신된다.
재연결이 몰리는 자리
서버를 재시작하면 모든 클라이언트가 동시에 재연결을 시도해서 서버가 다시 죽는 문제가 생겼다. 그러면 또 동시에 재연결하는 순환이 만들어진다.
시도할수록 간격이 늘어나는 방식에 무작위 지연을 함께 넣었다. 간격만 늘리면 모두가 같은 간격으로 늘어나 여전히 같은 순간에 몰리므로 무작위가 필요했다.
순번과 버퍼 지표
재연결하면 그동안의 변화를 놓치는데 최신값만 필요한 것은 상관없지만 하나도 빠지면 안 되는 것이 있었다. 각 메시지에 순번을 붙이고 재연결할 때 마지막 순번을 보내 그다음부터 받게 했다.
서버가 최근 몇 개를 버퍼에 갖고 있어야 이것이 성립하고 너무 오래 끊겼으면 전체 상태를 다시 받는다. 버퍼를 넘어 전체를 다시 보낸 횟수를 지표로 재니 감으로 정했던 버퍼 크기를 근거를 갖고 조정할 수 있었다.
정리
- 스트림에서 데이터 없음과 연결 끊김이 구분되지 않는다
- 전송 계층도 조용한 동안에는 끊김을 감지하지 못한다
- 변화가 없어도 주기적으로 무의미한 바이트를 보낸다
- 주기는 중간 계층의 유휴 시간 제한보다 짧게 잡는다
- 받는 쪽이 마지막 수신 시각을 보고 스스로 재연결한다
- 재연결에 간격 증가와 무작위 지연을 함께 넣는다
- 빠지면 안 되는 메시지는 순번을 붙여 이어받는다
- 버퍼 초과 횟수를 재면 버퍼 크기를 근거 있게 정한다