Long Polling and HTTP Keep-Alive: 长轮询与连接复用

客户端想"一有新消息就知道",但只能由客户端主动发请求(比如它在内网里,服务端连不进来),常用的办法是长轮询。这篇记录长轮询怎么工作,以及它底下的 HTTP 连接复用(keep-alive)是怎么回事。起因是给 homelab 配 GitHub Actions 自托管 runner 时,想弄清楚 runner 在内网里是怎么及时拿到任务的。 短轮询和长轮询 短轮询:客户端每隔固定时间问一次"有没有新消息",服务端立刻回答,有就给,没有就回空。 间隔设短了,大部分请求都是空跑,浪费流量和服务端资源 间隔设长了,消息要等到下一次轮询才能拿到,延迟最多一个间隔 长轮询:客户端发出请求后,服务端先不回答,把请求挂住: 挂住期间来了消息,立刻在这个请求上返回 一直没有消息,等到约定的时间(比如 50 秒)返回一个空响应 客户端收到响应(不管有没有消息)后马上发下一个请求 client server |---- GET /messages (wait up to 50s) ---->| | | no message yet, hold the request | | ... 12s later a message arrives |<--------- 200 [message] ----------------| |---- GET /messages (wait up to 50s) ---->| sent again immediately | | nothing for 50s |<--------- 200 [] (empty) ---------------| |---- GET /messages (wait up to 50s) ---->| 所以长轮询几乎任何时候都有一个请求挂在服务端,消息一到就能送出去,延迟接近实时;没有消息时每 50 秒才一个请求,空跑也很少。消息在两次请求之间到达也不会丢:服务端先把它放进队列,下一个请求一到就取走。 ...

Created 20206-10-20 · Updated 20206-10-20 · 2 min · 310 words · -