首页 > 代码库 > LB 负载均衡的层次结构

LB 负载均衡的层次结构

技术分享

作为后端应用的开发人员,我们常常开发、调试、測试完我们的应用并公布到生产环境。用户就能够直接訪问到我们的应用了。但对于互联网应用,在你的应用和用户之间还隔着一层低调的或厚或薄的负载均衡层软件,它们不显山不露水默默的发挥着关键的数据,以至于我们常常忽略了它们的存在。

由于负载均衡层通常不在一般开发人员的问题域内。并且它们一般都是现成且成熟的解决方式,以至于我们习惯性的忽略和认为乏善可陈。事实上不然,本文就写写我对负载均衡层次结构的认知和理解。

硬负载

所谓「硬负载」就是採用硬件设备来提供负载均衡。

在七、八年前那时我在做 Java 的企业软件开发。开发出来的企业级 Java 应用程序就部署在像 Weblogic 之类的应用容器中。而这类应用容器软件又跑在 Unix 的小型机上。把硬件和软件一体打包作为企业应用解决方式卖给客户。

这类应用部署的方案十分简单,层级也比較浅。为了保证可靠性,使用两套小型机上各部署一个 Weblogic Server,在应用服务前面使用像 F5 之类的硬件负载均衡器,例如以下图所看到的。

技术分享

由于小型机和前面的 F5 负载均衡硬件都比較贵,所以出于可靠性、可维护性和成本的综合考虑。一般应用部署两套跑在两台小型机上。在前面共享一个 F5 做负载均衡。而一般 F5 和小型机这类硬件设备都至少是 5 个 9 的可靠性保障。所以总体的系统可靠性基本有保障。

进入互联网时代后。应用开发拥抱开源,部署使用更便宜的 PC Server 和免费开源的应用容器。负载均衡也逐步从硬负载向软负载变迁。由于互联网应用的海量特性和部署规模的急剧膨胀。前端负载均衡也開始变得丰富起来。

软负载

进入互联网公司后,我们刚開始开发应用时。业务规模小用户量还不大,机器数量也少(<10)。所以一開始的负载均衡的结构也是非常easy的。相似硬负载仅仅是把硬件换成了免费的开源软件并跑在可用性是有 3 个 9 的便宜 PC Server 上。

技术分享

前面一个 LVS 后面跟着几个应用服务。后来为了方便做按域名的分流和适配切流量上线,中间又加了一层 Nginx。

技术分享

这样就变成了两层软负载结构了,LVS 负责 4 层。Nginx 负责 7 层。

但 Nginx 仅仅负责了单机内多实例的负载均衡,这里主要是由于当时 PC Server 是物理机,CPU 16/32 core。内存 32/64G 不等,为了更充分的利用资源。一台物理机上都部署了多个应用服务实例,而考虑到 Nginx 工作在 7 层的开销远高于 LVS/DR 模式。所以一般在一个 Nginx 后面挂的实例数也不会超过 10 个。

但随着业务发展和用户流量上升,机器规模也在不断扩张,导致一个网段内的 IP 都不够用了,这套负载结构又遇到了横向扩展的瓶颈,由于 LVS/DR 模式下跨不了网段。

所以后来又在 LVS 和 Nginx 之间加了一层 HAProxy,负载结构就变成了以下这样。

技术分享

事实上加了 HAProxy 之后,它也是工作在 7 层。这样 Nginx 这层看起来就不是非常有必要。但三层的负载结构能支撑更大规模的集群,而原本在 Nginx 层做了一套方便研发切流量上线的运维管理系统,所以牺牲一点性能换取如今的可维护性和将来扩展性。Nginx 这层就一直保留下来了。并且 Nginx 相比 HAProxy 不是纯粹的负载均衡器。它还能提供 cache 功能,对于某些 HTTP 请求实际仅仅走到 Nginx 这层就能够通过缓存命中而返回。

DNS负载

随着业务发展,公司開始了多个 IDC 的建设。考虑到 IDC 级别的容灾,集群開始部署到多个 IDC。跨 IDC 的负载均衡方案能够简单通过 DNS 轮询来实现,但可控性不好。所以我们没有採用这样的,而是採用一主加多子域名的方式来基于业务场景实现动态域名调度和负载。主域名下实际是一个动态流量调度器,跨多个 IDC 部署,对于 HTTP 请求基于重定向方式跳子域名,对于 TCP 方式每次建立长连接前请求分配实际连接的子域名,例如以下图所看到的。

技术分享

CDN负载

最后再加上互联网应用不可缺少的 CDN 将静态资源请求的负载分流。那么整个负载的层次结构就完整了。

SSL 带来的负载结构变化

随着互联网的普及。安全问题益发严重。原本早期仅仅有银行网银等使用 HTTPS 方式訪问,如今电商类站点也開始启用全站 HTTPS 了。

引入 SSL 后对负载结构带来了什么影响么?SSL 属于应用层的协议。所以仅仅能在 7 层上来做,而 HAProxy 也是支持 SSL 协议的,所以一种方式是仅仅需简单的让 HAProxy 开启 SSL 支持完毕对内解密对外加密的处理。

但 HAProxy 的作者不太赞同这样的方案。由于引入 SSL 处理是有额外的性能开销的。那么在承担确定流量的情况下。假设原本须要 M 台 HAProxy,在开启了 SSL 后可能须要 M + N 台 HAProxy。随着流量增长。这样的方式的横向扩展成本较高(毕竟 SSL 证书按服务器数量来收费的)。他给出的解决方式是再独立一层 SSL 代理缓存层,像以下这样。

技术分享

L4 和 L7 之间独立的 SSL 代理缓存层仅仅负责 SSL 协议的处理,把 HTTPS 转换成 HTTP。并检查本地缓存是否命中。

若未命中再转发请求到后端的 L7 层应用负载均衡层。这样的优点是每一个层次都能够依据流量来独立伸缩。并且 SSL 层显然能够跨多个应用共享。更节省成本。

假设按这个思路来又一次调整我们前面的负载均衡结构层次,将会演变成以下这样。

技术分享

事实上,这时我认为应用前面的那层 Nginx 可能就显得多余了点,没必要的。但假设现实这么演进下来非常可能就会有这么一层冗余的东西存在非常长一段时间,这就是理想和现实之间的差距吧。

总结

好了。本文到此为止。作为一名后台开发我事实上对上面提及的各类开源软件如何配置、调优和管理并不熟悉。这属于运维开发的问题域范畴。

但这并最好还是碍我去了解我所开发的应用所处的整个环境是如何的。多了解些你工作领域范围边界外的 What 和 Why。有时也能帮助我们更好的设计和解决自身问题域内的问题,别为自己设限而终于画地为牢。

本来以为负载均衡这个古老的课题已经定型了,在写本文时又看到新闻,在近日举办的第十三届网络系统设计与实现 USENIX 研讨会上,来自 Google 的project师又分享了其自研的 Maglev 负载均衡器。刚下了论文还没看,回头看了再来写写。

參考

[1] HAProxy Documentation. HAProxy Management Guide
[2] HAProxy Documentation. HAProxy Starter Guide
[3] Willy Tarreau. Making applications scalable with Load Balancing
[4] LVS wiki. Load balancing
[5] Wikipedia. Virtual Router Redundancy Protocol
[6] shuming. LVS 工作模式以及工作原理


写点文字,画点画儿,「瞬息之间」一切都变了。认为不错,可长按或扫描二维码关注。
技术分享

<script type="text/javascript"> $(function () { $(‘pre.prettyprint code‘).each(function () { var lines = $(this).text().split(‘\n‘).length; var $numbering = $(‘
    ‘).addClass(‘pre-numbering‘).hide(); $(this).addClass(‘has-numbering‘).parent().append($numbering); for (i = 1; i <= lines; i++) { $numbering.append($(‘
  • ‘).text(i)); }; $numbering.fadeIn(1700); }); }); </script>

LB 负载均衡的层次结构