让服务端定期结束长连接有什么好处?到期时线上发生什么?在途的长流会怎样?会不会引起失败或延迟抖动?这篇用抓包代理和持续负载把它们都看一遍。
1.053 秒:S→C GOAWAY 最后流 2147483647,错误码 NO_ERROR,附加数据 "max_age" TCP 连接数 1;客户端状态 IDLE
年龄到期时服务端发 GOAWAY(附加数据 max_age),不再接受新流;客户端之后遇到调用会重新建连,而不是继续用这条连接。
观察到 30 个连接的第一个 GOAWAY:最早 1.87 秒、最晚 2.21 秒、平均 2.05 秒(MaxConnectionAge = 2 秒)
服务端给年龄加 ±10% 的随机抖动,避免所有连接同时重建。
宽限默认(无限) 客户端 4.02 秒时结束、收到 8 条消息(服务端共发 8 条),结束时:io.EOF(流正常结束,状态为 OK);服务端发送一直成功 宽限 1 秒 客户端 3.07 秒时结束、收到 5 条消息(服务端共发 8 条),结束时:code=Unavailable message="closing transport due to: connection error: desc = \"error reading from server: E…";服务端第一次发送失败在 2.50 秒
宽限(MaxConnectionAgeGrace)默认是无限,在途的流不受影响;设了宽限,到期加宽限之后连接被强制关闭,长流会被打断。
没有设置 总调用 142588;失败 0;TCP 连接共 1 条;p50 210 µs、p99 418 µs、最慢 34211 µs MaxConnectionAge 500 ms 总调用 144272;失败 0;TCP 连接共 8 条;p50 209 µs、p99 395 µs、最慢 29301 µs
本机回环上频繁更换连接没有造成失败或可见的延迟变差;真实网络里要加上重建连接的握手成本。
MaxConnectionIdle = 300 ms 4 次调用(间隔 1 秒):失败 0;TCP 连接共 4 条;最后的客户端状态 IDLE MaxConnectionAge = 1.5 秒 4 次调用(间隔 1 秒):失败 0;TCP 连接共 2 条;最后的客户端状态 IDLE
MaxConnectionIdle 只回收空闲连接,MaxConnectionAge 不管忙闲都定期更换,常用来重新做负载均衡、让新证书或新后端生效。