Slow Clients and Lost Connections
Come Back After a Drop
The server now survives a slow viewer and drops a dead one. This lesson looks at the other end of the connection: the viewer’s program, after its connection is gone. It may have been dropped by
The obvious way is to try again at once, and again if that fails, as fast as the program can. That is harmful. When a server restarts, every one of its viewers loses its connection at the same moment, and if they all retry at once, the server comes back to a flood of
Double the wait, up to a cap, with jitter
The usual answer has three parts. Wait before each new attempt, and double the wait after each failure: half a second, then one, then two. Stop doubling at a cap, so a long outage does not leave a client waiting an hour once the server is back. And do not wait exactly that long: pick a random time between zero and the ceiling, which is called jitter. Two clients that lost the server at the same moment then pick different times and spread out. RFC 6455 itself recommends this, in section 7.2.3: after an abnormal closure a client SHOULD delay its first attempt by a random amount of time and then back off, doubling the delay up to a limit.
The program below computes one client’s schedule. A real client takes its jitter from a random source; here a fixed
It prints six lines, from attempt 1: wait up to 0.5 s, this time 0.31 s to attempt 6: wait up to 8.0 s, this time 2.64 s. The ceiling doubles from 0.5 to 8.0 and then stays at the cap. The waits jump around underneath it: attempt 4 waits 1.6 s although its ceiling is 4.0. In a real client, each wait would be a sleep, followed by a new connect; a successful connection resets the attempt count to 1.
The arithmetic for attempt 5 alone. What does this print?
print(0.5 * 2 ** 4, round(8.0 * 0.97, 2))
Resync needs no history
Once the viewer is connected again, it has missed every score that happened while it was away. It does not need to ask for them. The server’s first message to every viewer is the join snapshot, the whole board, so one message brings a returning viewer up to date.
The viewer needs one rule to go with it: keep the version of the last snapshot it showed, and ignore any snapshot whose version is not newer. A snapshot with the same version would only show the same board again, and an older one would make the scores go backwards, which can happen when a client briefly holds two connections or reads a late message from the connection it was leaving. The program below applies the rule to four snapshots arriving after the viewer showed version 4:
It prints version 3: ignored, version 5: shown, version 5: ignored and version 6: shown.
A client last showed version 9 and, after reconnecting, receives a snapshot with version 9. What does it do?
Where this lives
The staleness rule is part of the scoreboard’s contract, and the capstone’s client applies it. A full reconnect connect calls and its random source, is something to recognize and not something this course builds: once you know the three parts, you can read one in any client library’s documentation and check that it doubles, caps and jitters.
Why add jitter to the backoff?
Lesson 6 proves scoreboard v2 with tests of your own and runs it with a slowed viewer and a dead one.