gRPC 的一条 HTTP/2 连接可以复用很久。当连接在均衡器后面建立之后,新增的后端会不会分到流量?请求量不同的客户端会怎样?这篇用一个自己写的四层均衡器逐项验证。
2 个后端时,6 个客户端各发 100 次:各后端收到 [300 300];均衡器接受的连接 6 条 加入第 3 个后端后,原来的 6 个客户端再各发 100 次:各后端收到 [300 300 0];均衡器接受的连接仍是 6 条 再新建 3 个客户端各发 100 次:各后端收到 [100 100 100];均衡器接受的连接 9 条
HTTP/2 在一条连接上复用很多请求。四层均衡器只在建立连接时选后端,之后这条连接上所有请求都去同一个后端;新增后端后,只有新建的连接才会分到它,已有的连接继续待在原后端——扩容之后新后端闲着就是典型表现。
4 个客户端轮流被分到 2 个后端(每个后端 2 条连接),但请求数:各后端收到 [1100 200](后端 0 占 85%)
按连接均衡并不等于按请求均衡:一条连接上跑多少请求由客户端决定,忙的客户端把它所在的后端压垮,而别的后端很闲。
1000+100+100+100 次调用,各后端收到 [421 420 421]
客户端拿到全部后端地址、自己做 round_robin,则每个请求轮流发给各后端,与客户端忙闲无关。要求客户端能拿到地址列表并及时更新(第 15 篇)。
第 1 秒内各后端收到的次数 [135 135] 第 2 秒内各后端收到的次数 [133 131 0] 第 3 秒内各后端收到的次数 [100 94 82] 第 4 秒内各后端收到的次数 [87 88 89] 第 5 秒内各后端收到的次数 [89 91 90] 第 6 秒内各后端收到的次数 [90 89 91] 第 7 秒内各后端收到的次数 [89 87 88] 第 8 秒内各后端收到的次数 [91 91 88] 整个过程中失败的调用 0 个;均衡器共接受 49 条连接
服务端让连接活一段时间就发 GOAWAY 并关闭(带宽限期),客户端重新连接,均衡器重新分配。设置过短会增加建连开销,过长则恢复均衡慢;读源码时看到服务端给这个值加了 ±10% 的随机抖动,避免所有连接同时断开。