介绍
balancer是一个支持http和https的7层负载均衡器,也是一个实现负载均衡算法的go库。
目前支持的负载均衡算法有
round-robin
random
power of 2 random choice
consistent hash
consistent hash with bounded
ip-hash
least-load
快速图解
(偷下懒借用张师傅的图片🤣,顺带推荐下 张师傅的tcp小册,讲解的通俗易通,知识点丰富,链接 https://s.juejin.cn/ds/irJbCpd2/)
功能分解
健康检查
负责根据健康检查规则对后端服务进行检查,剔除不健康的节点,加入健康节点
负载均衡
从一组负载均衡节点中根据负载均衡策略选择节点实例
代码赏析
HTTP Proxy 反向代理核心结构
路由匹配
因为原生的 HTTP 没有办法动态设置 路由,该项目使用 mux 项目设置路由匹配,当然mux的性能 相较于前缀树差了很多,可以参考下 https://yushuanhsieh.github.io/post/2020-01-21-golang-router ,能够相差几十倍
负载均衡策略
接下来来看几个比较有代表性的负载均衡算法策略
random
策略描述
特点
每次新连接,随机选择一个节点进行处理
代码
ip-hash
策略描述
根据原ip选择对应的节点
特点
同一客户ip发起的连接在健康检查都ok的情况下,会被分配至同一节点
代码
least load
策略描述
选择当前处理连接最少的节点
特点
可以根据后端节点的连接处理数量,合理的将新连接配置至后端节点
代码
使用了 FibonacciHeap (斐波那契堆)可以快速排序,获取当前连接数最少的节点,开源库 https://github.com/starwander/GoFibonacciHeap
健康检查代码
可以看到就是针对节点的端口进行tcp探活
可以对比下kubernetes的TCP探活代码对比下
可以看到 kubernetes 对于http/ tcp 的健康检查进行了特殊处理,开启了 Linger 特性,并设置超时为 1s,在超时后会直接reset连接,相较于默认的 默认timewait是60s,当节点上的kubelet会频繁进行健康检查,很可能会导致,很多资源比如 socket, ephemeral port, conntrack entry 等等会被占用,这样的话,会导致影响其他请求,相关issue 可以参考
https://github.com/kubernetes/kubernetes/pull/115143
再次感概下 细节决定成败
总结
- 一个基本的负载均衡由 负载均衡算法 和 健康检查组成
- 常见的负载均衡算法有 轮询,iphash,least connect 以及如何编写
- 一个常见的tcp健康检查探针如何编写,已经如何优化http/tcp探测
- linger socket选项 开启后,可以设置 socket.close 的超时时间,如果超过时间,不会进入timewait阶段,会直接reset掉连接
- 斐波那契堆如何在项目中使用
- 常见的路由框架与性能比较