上周分享的一篇《仅需这一篇,吃透「负载均衡」妥妥的》相信大家看完后对负载均衡的策略有了一些了解。这篇主要阐述负载均衡在实施的时候一些主流的解决方案。
为什么没有 DNS?
再翻出第一篇中放出的一张图来回顾一下。
之前也有小伙伴问到,为什么没有列出 DNS?我认为,DNS 的本质是解决「domain name --> ip」的问题。
虽然 DNS 除了在公网运用的之外,还会运用于做内网的自定义 domain name 解析,但是在程序里单靠它来做负载均衡的话,还是太勉强了。
当然,基于 DNS 的“智能解析”功能可以做到 IP 的动态返回,也算起到了负载均衡的作用。
但是,由于其本身是一个工作在 L3(网络层)的解决方案,所以无法对“端口”进行工作。
而一般我们程序之间的通讯很多都会涉及到端口,因此我们本篇先不讨论 DNS。
如何实施?
在清楚了我们应该在哪些环节考虑做负载均衡之后,接下去就是思考如何能够循序渐进的进行。
古时候军队打仗的时候一般都是拿盾的扛在前面,顶住攻击。而负载均衡解决方案从某种角度来说也是一个类似盾一般的防御性设施,因为前提就是要能承载上游过来的流量。
因此,越往“前”做负载均衡解决方案,效果肯定会越好,因为受保护的应用范围越广。
如果说,系统之前没有运用过负载均衡,现在开始第一次做,该如何选择呢?下面我根据心目当中的优先级来和大家聊一下。
硬件负载均衡
硬件这块名气最大的还属 F5(根据 ZOL 的数据,其在市场占有率 51.44%),大大盖过了其他几家硬件商的风头。
此类硬件负载均衡器的特点是“壕”,毕竟是纯商业化的东西,投入的资源和精力自然是众多开源软件负载均衡所无法比拟的,所以功能非常强大。
它们包含访问加速、压缩、安全等等负载均衡之外的许多附加功能。
题外话:如果用 F5 组网的话,有两种结构,串行结构和并行结构,也称为直连模式和旁路模式。
前者的优势在对硬件产生压力较小、且天然安全性高,而后者对原网络架构的改动较小、且扩展性较好。大家在实际的使用中结合自身情况来部署。
“壕”物能够同时支持 L2~L7 的转发,所以上图中的每一个标注点都可以用硬件来做负载均衡。
因此,如果在经济允许的情况下,直接上 F5 能解决很多原本需要花更多时间去解决的问题。所以当“时间”的重要度大于“金钱”的时候,建议优先采用硬件方案。
软件负载均衡(L7)
当“金钱”的重要程度大于“时间”的时候,我们可以通过软件来达到我们要的效果。相应的,也增加了一些运维成本。
一般情况下,只要对数据库不滥用,往往我们从「单应用 + 单库」组合最先需要突破的是应用,变成「多应用 + 单库」。
那么针对 Web 应用的 L7 负载均衡,比较主流的产品是 2 个 Nginx、HAProxy。
在 L7 做负载均衡,最大的特点就是灵活,请求的 URL、Header 都是我们可以去掌控的,所以我们可以利用其中的任何信息为负载均衡策略所用。
这一类就是前面图中的「反向代理」。作为「客户端」和「Web 应用」、「前端」和「后端」之间的桥梁。
实际操作中主要做两步:
- 在公网的域名解析中,配置解析到「反向代理」。记录类型是「A」,记录值是「反向代理」的 IP。
- 配置真实提供服务的 Web 应用 IP 和端口,和负载均衡策略。上图中的配置是 Nginx 中的示例,负载均衡策略的缺省值是轮询。
软件负载均衡(L4)
当「Web 应用」所依赖的 TCP 协议的「服务」需要横向扩展,或者需要做「数据库」、「分布式缓存」的多主、主从集群时,那么就需要一个支持 L4 的负载均衡软件。
这里最知名的就属 LVS 了,1998 年 5 月由章文嵩博士建立,2004 年底被纳入 Linux 内核。
也正因为它是内核态的程序,所以相比用 Nginx、HAProxy 来做 L4 的负载均衡,在性能、资源的消耗上会更优一些。
实际运用中的操作步骤主要也是两步:
- 在 LVS 中添加一个 IP 虚拟服务(IPVS),并指定它的 IP、端口和负载均衡策略。
- 将 IP 虚拟服务关联到真实的服务上,并指定模式和权重的信息。(做 L4 的负载均衡可以使用 NAT 或者 FULLNAT 模式)
题外话:LVS 的模式一共有四种,除了 NAT 和 FULLNAT(NAT 的增强版)模式外,它的 TUN 模式可以在 L3 做负载均衡,DR 模式可以在 L2 做负载均衡,到这个层面其实就和做硬件同处于一个层次了。
并且,随着层次的深入,虽然对功能性上有所弱化,但是如果不考虑端口的话,单从 IP 层面的负载均衡来说,用 DR 模式做,则对数据包的加工介入度会降到最低,因此也是通过软件做负载均衡能够达到的性能极致。
另外,LVS 中运用的虚拟 IP 概念,本质上和 Nginx 中的“Server”概念一样,定义了一个统一入口,作用上并没有差别。
将 Nginx中的 upstream 关联到 Server,就如 LVS 操作步骤第 2 点中的关联一般。
这些每个具体的解决方案的使用教程网上比较多,就不展开了,大家实际用到的时候自行查阅一下,当然尽量优先看官方的。
优缺点
做了一个苦差事,把所有同类型的产品都整合了一下优缺点和使用场景。不过,其中有不少是我没用过的,所以仅供大家参考。
顺手将一些网上到处充斥的一些过时结论做了更新,如:Nginx 不支持 Session Sticky 等。
我们可以看到,不同的解决方案有不同的侧重点。因此在单个解决方案已经无法满足的情况下,我们可以组合使用,各尽所长。
负载均衡这个领域还是以高可用和性能为两个最重要因素,下面是我推荐的一种组合方式,也是在系统量级达到每小时上亿 PV 之后最被广泛使用的一种。
理论上,利用第一步 DNS 的域名解析所带的负载均衡效果,只要复制多套 LVS 主备出来,绑上多个不同的虚 IP,可以做到无限横向扩展,以支撑不断增长的流量。
用到的 3 个软件目前都是开源产品,LVS+Keepalived 负责做 Nginx 的负载均衡,而 Nginx 负责分发实际的请求到 HTTP 和 TCP 协议的应用上。
关于 LVS 的模式选择,如果在同网段内的话优先使用 DR 模式进行 L2 转发,性能最好。否则使用 TUN 模式进行 L3 分发。
与此同时,在 L4、L7 的分发上使用 Nginx 来做,可以发挥其灵活易扩展的特点以及其他的一些额外特性如缓存等,也算是物尽其用。
云时代,Service Mesh 风兴起。以 Sidecar 模式为核心的后起之秀 Linkerd、Conduit、NginMesh、Istio 等软件除了满足负载均衡之外,还为高可用相关的做了众多的考量。
结语
有些事,并不需要做到一步到位,做技术也是这样。其实大部分情况下,在以上方案中选择一个,做一层转发就够了。行远自迩,避免给自己添不必要的麻烦。