极客时间已完结课程限时免费阅读

24 | 负载均衡架构:如何用10行代码实现一个负载均衡服务?

24 | 负载均衡架构:如何用10行代码实现一个负载均衡服务?-极客时间

24 | 负载均衡架构:如何用10行代码实现一个负载均衡服务?

讲述:李智慧

时长10:16大小8.23M

负载均衡是互联网系统架构中必不可少的一个技术。通过负载均衡,可以将高并发的用户请求分发到多台应用服务器组成的一个服务器集群上,利用更多的服务器资源处理高并发下的计算压力。
那么负载均衡是如何实现的,如何将不同的请求分发到不同的服务器上呢?
早期,实现负载均衡需要使用专门的负载均衡硬件设备,这些硬件通常比较昂贵。随着互联网的普及,越来越多的企业需要部署自己的互联网应用系统,而这些专用的负载均衡硬件对他们来说成本太高,于是出现了各种通过软件实现负载均衡的技术方案。

HTTP 重定向负载均衡

HTTP 重定向负载均衡是一种比较简单的负载均衡技术实现。来自用户的 HTTP 请求到达负载均衡服务器以后,负载均衡服务器根据某种负载均衡算法计算得到一个应用服务器的地址,通过 HTTP 状态码 302 重定向响应,将新的 IP 地址发送给用户浏览器,用户浏览器收到重定向响应以后,重新发送请求到真正的应用服务器,以此来实现负载均衡。
这种负载均衡实现方法比较简单,如果是用 Java 开发的话,只需要在 Servlet 代码中调用响应重定向方法就可以了。在简化的情况下,只需要不到十行代码就可以实现一个 HTTP 重定向负载均衡服务器。
HTTP 重定向负载均衡的优点是设计比较简单,但是它的缺点也比较明显,一方面用户完成一次访问,就需要请求两次数据中心,一次请求负载均衡服务器,一次是请求应用服务器,请求处理性能会受很大的影响。
另一个问题是因为响应要重定向到真正的应用服务器,所以需要把应用服务器的 IP 地址暴露给外部用户,这样可能会带来安全性的问题。负载均衡服务器通常不部署应用代码,也会关闭不必要的访问端口,设置比较严格的防火墙权限,通常安全性更好一点。因此,一个互联网系统通常只将负载均衡服务器的 IP 地址对外暴露,供用户访问,而应用服务器则只是用内网 IP,外部访问者无法直接连接应用服务器。但是使用 HTTP 重定向负载均衡,应用服务器不得不使用公网 IP,外部访问者可以直接连接到应用服务器,系统的安全性会降低。
因此 HTTP 重定向负载均衡在实践中很少使用。

DNS 负载均衡

另一种实现负载均衡的技术方案是 DNS 负载均衡。我们知道浏览器或者 App 应用访问数据中心的时候,通常是用域名进行访问,HTTP 协议则必须知道 IP 地址才能建立通信连接,那么域名是如何转换成 IP 地址的呢?就是通过 DNS 服务器来完成。当用户从浏览器发起 HTTP 请求的时候,首先要到 DNS 域名服务器进行域名解析,解析得到 IP 地址以后,用户才能够根据 IP 地址建立 HTTP 连接,访问真正的数据中心的应用服务器,这时候就可以在 DNS 域名解析的时候进行负载均衡,也就是说,不同的用户进行域名解析的时候,返回不同的 IP 地址,从而实现负载均衡。
从上面的架构图可以看到,DNS 负载均衡和 HTTP 重定向负载均衡似乎很像。那么 DNS 会不会有性能问题和安全性问题呢?
首先和 HTTP 重定向不同,用户不需要每次请求都进行 DNS 域名解析,第一次解析后,域名缓存在本机,后面较长一段时间都不会再进行域名解析了,因此性能方面不会是问题。
其次,如果如图中所示,域名解析直接得到应用服务器的 IP 地址,确实会存在安全性问题。但是大型互联网应用通常并不直接通过 DNS 解析得到应用服务器 IP 地址,而是解析得到负载均衡服务器的 IP 地址。也就是说,大型网互联网应用需要两次负载均衡,一次通过 DNS 负载均衡,用户请求访问数据中心负载均衡服务器集群的某台机器,然后这台负载均衡服务器再进行一次负载均衡,将用户请求分发到应用服务器集群的某台服务器上。通过这种方式,应用服务器不需要用公网 IP 将自己暴露给外部访问者,避免了安全性问题。
DNS 域名解析是域名服务商提供的一项基本服务,几乎所有的域名服务商都支持域名解析负载均衡,只需要在域名服务商的服务控制台进行一下配置,不需要开发代码进行部署,就可以拥有 DNS 负载均衡服务了。目前大型的互联网应用,淘宝、百度、Google 等全部使用 DNS 负载均衡。比如用不同的电脑 ping www.baidu.com就可以看到,不同电脑得到的 IP 地址是不同的。

反向代理负载均衡

我在第 22 篇,缓存架构中提到用户请求到达数据中心以后,最先到达的就是反向代理服务器。反向代理服务器查找本机是否有请求的资源,如果有就直接返回资源数据,如果没有,就将请求发送给后面的应用服务器继续处理。事实上,发送请求给应用服务器的时候,就可以进行负载均衡,将不同的用户请求分发到不同的服务器上面去。Nginx 这样的 HTTP 服务器就会同时提供反向代理与负载均衡功能。
反向代理服务器是工作在 HTTP 协议层之上的,所以它代理的也是 HTTP 的请求和响应。作为互联网应用层的一个协议,HTTP 协议相对说来比较重,效率比较低,所以反向代理负载均衡通常用在小规模的互联网系统上,只有几台或者十几台服务器的规模。

IP 负载均衡

反向代理负载均衡是工作在应用层网络协议上的负载均衡,因此也叫应用层负载均衡。应用层负载均衡之下的负载均衡方法是在 TCP/IP 协议的 IP 层进行负载均衡,IP 层是网络通讯协议的网络层,所以有时候叫网络层负载均衡。它的主要工作原理是当用户的请求到达负载均衡服务器以后,负载均衡服务器会对网络层的数据包的 IP 地址进行转换,修改 IP 地址,将其修改为应用服务器的 IP 地址,然后把数据包重新发送出去,请求数据就会到达应用服务器。
IP 负载均衡不需要在 HTTP 协议层工作,可以在操作系统内核直接修改 IP 数据包的地址,因此,效率比应用层的反向代理负载均衡高得多。但是它依然有一个缺陷,不管是请求还是响应的数据包,都要通过负载均衡服务器进行 IP 地址转换,才能够正确地把请求数据分发到应用服务器,或者正确地将响应数据包发送到用户端程序。请求的数据通常比较小,一个 URL 或者是一个简单的表单,但是响应的数据不管是 HTML 还是图片,或者是 JS、CSS 这样的资源文件通常都会比较大,因此负载均衡服务器会成为响应数据的流量瓶颈。

数据链路层负载均衡

数据链路层负载均衡可以解决响应数据量大而导致的负载均衡服务器输出带宽不足的问题。也就是说,负载均衡服务器并不修改数据包的 IP 地址,而是修改数据链路层里的网卡 mac 地址,在数据链路层实现负载均衡。而应用服务器和负载均衡服务器都使用相同的虚拟 IP 地址,这样 IP 路由就不会受到影响,但是网卡会根据自己的 mac 地址,选择负载均衡服务器发送到自己网卡的数据包,交给对应的应用程序去处理,处理结束以后,当把响应的数据包发送到网络上的时候,因为 IP 地址没有修改过,所以这个响应会直接到达用户的浏览器,而不会再经过负载均衡服务器。
链路层负载均衡避免响应数据再经过负载均衡服务器,因而可以承受较大的数据传输压力,所以,目前大型互联网应用基本都使用链路层负载均衡。
Linux 上实现 IP 负载均衡和链路层负载均衡的技术是 LVS,目前 LVS 的功能已经集成到 Linux 中了,通过 Linux 可以直接配置实现这两种负载均衡。

小结

负载均衡技术在早期刚出现的时候,设备昂贵,使用复杂,只有大企业才用得起、用得上,但是到了今天,随着互联网技术的发展与普及,负载均衡已经是最常用的分布式技术之一了,使用也非常简单。如果使用云计算平台,只需要在控制台点击几下,就可以配置实现一个负载均衡了。即使是自己部署一个负载均衡服务器,不管是直接用 Linux 还是用 Nginx,也不是很复杂。
我在这里主要描述的是负载均衡的网络技术架构。事实上,实现一个负载均衡,还需要关注负载均衡的算法,也就是说,当一个请求到达负载均衡服务器的时候,负载均衡服务器该选择集群中的哪一台服务器将请求发送给它?
目前主要的负载均衡算法有轮询、随机、最少连接几种。轮询就是将请求轮流发给应用服务器,随机就是将请求随机发送给任一台应用服务器,最少连接则是根据应用服务器当前正在处理的连接数,将请求分发给最少连接的服务器。

思考题

利用 HTTP 重定向只需要很少代码就可以完成一个简化的负载均衡,你能否利用你熟悉的编程语言写一个简化的 HTTP 重定向负载均衡 demo?
欢迎你在评论区写下你的答案,我会和你一起交流,也欢迎把这篇文章分享给你的朋友或者同事,一起交流一下。
分享给需要的人,Ta购买本课程,你将得18
生成海报并分享

赞 10

提建议

上一篇
23 | 异步架构:如何避免互相依赖的系统间耦合?
下一篇
25 | 数据存储架构:如何改善系统的数据存储能力?
unpreview
 写留言

精选留言(15)

  • Paul Shan
    2020-03-01
    负载均衡是为了让不同服务器处理不同的请求,在服务器上平均分配任务,如何分配任务就成了不同解决方案本质所在。HTTP重定向是用专门的HTTP服务器来对每个请求分配服务器,这样每个请求需要两次HTTP访问,效率低下。DNS负载均衡是在IP地址和域名映射转化的地方做文章,效率明显提升。DNS只解决公网上的负载均衡,服务器集群内部也需要负载均衡。这项任务有三种解决方案,分别在HTTP层,IP层和数据链路层做文章。HTTP层属于高层协议,也就是所有协议都处理一遍才知道最终要去那个应用服务器,而且不在内核中处理,效率最差。IP层的路由分发效率高一点,因为不用打开HTTP层了,而且全在内核中解析。但是IP是服务器的全局地址,在这一层做分发,势必每个包的接和收都得分发。数据链路层的负载均衡效率更高,原因在于一方面不用再打开到IP层了,而且IP地址没改过,包回来的时候就不用再处理了,这样就大大减轻了负载均衡服务器的工作量。
    展开
    16
  • escray
    2020-10-07
    专栏好像没有提到硬件负载均衡 F5 或者 A10,虽然贵,但是性能强大,支持百万以上并发,并且还具备防火墙、防 DDoS 攻击等安全功能。 实现了 IP 负载均衡和链路层负载均衡的 LVS 是 4 层负载均衡,与协议无关,性能是十万级,传说可达 80 万/秒; 应用层负载均衡,Nginx 是 7 层负载均衡,可以支持 HTTP、E-mail 协议,性能大概是 5 万/秒。 大概一般的互联网平台,如果用户的地理分布比较广泛,那么先上 DNS 的地理级别负载均衡(域名商提供,一般免费); 如果流量正的很大,或者土豪,那么就在当地机房上集群级别的硬件负载均衡 F5,在我的印象里面,似乎维基百科也没有使用硬件负载均衡; 进入当地机房以后,可以再使用机器级别的负载均衡 Nginx 将用户请求发送给及群众的某台机器。 也可以采用级联的方式,一级用 F5,二级用 LVS,三级用 Nginx。我觉的一般人用不到这个方案。 参考《从零开始学架构》中有关高性能负载均衡的章节。
    展开
    12
  • 旅途
    2020-01-31
    智慧老师 问一个问题 mac负载均衡能直接返回客户端是因为 和负载均衡节点一样配置了外网ip吗?这块客户端和服务端的交互 感觉还是不太清晰 麻烦您再详细讲下

    作者回复: 是的,应用服务器和负载均衡服务器IP地址一样

    共 3 条评论
    4
  • 苏志辉
    2020-01-17
    IP层负载均衡为什么返回的不是网关地址而是200.10.10.1

    作者回复: 谢谢指正,尽快修正~

    2
  • 不要挑战自己的智商
    2022-09-30 来自美国
    1, HTTP 302 Redirection LB: the client app needs to send the requests twice to reach the target server. IP of application server is exposed to public, thus weaken the security. This method is rarely used. 2. DNS LB. Widly used. Configured at the DNS provider table. No coding. 3. reserse proxy: works on HTTP layer, needs to open and parse the HTTP protocol. Serves as a cache in front of the applicaiton server. 4. IP LB. More efficient than reverse proxy. By chaning the destination IP to a private IP, the request is forwarded to the target server. Meanwhile, all responses have to go through this LB, which adding more load to this single point. 5. Link layer LB: LB and server have same IP, different mac address. The responses would not need to pass through the LB, but going to client directly.
    展开
    1
  • 非同凡想
    2020-03-28
    nginx与lvs该怎么选,有不有什么原则?
    共 2 条评论
    1
  • 天天向上
    2020-01-31
    HTTP层比IP层多了处理环节,因此说HTTP 协议相对说来比较重?!

    作者回复: 可以这么说。主要是处理HTTP协议需要消耗更多的计算机资源。

    1
  • test
    2022-11-06 来自广东
    1. 硬件负载均衡:支持百万以上 2. 软件负载均衡: 2.1 HTTP重定向:访问HTTP重定向负载均衡服务器获得新的地址后访问 2.2 DNS负载均衡:访问DNS或者地址后访问 2.3 反向代理:反向代理有资源则返回,无资源则请求下游服务器。nginx,通过将请求分发来实现。性能是5 万级别 2.2 LVS:性能是十万级 2.2.1 IP层:请求到达负载均衡后,负载均衡服务器在操作系统内核修改IP地址 2.2.2 数据链路层负载均衡:解决响应数据量大而导致的负载均衡服务器输出带宽不足的问题。负载均衡服务器修改mac地址,而服务器和下游应用服务器共享相同的虚拟IP,所以应用服务器处理完之后不用再把response返回负载均衡服务器去修改IP以返回给客户端,而是直接返回给客户端。
    展开
  • 丶二月二
    2021-11-17
    请教下,写了一个简易的HTTP重定向负载均衡,发现客户端没有主动将body发给重定向后的url,有什么参数可以控制嘛?还是只能客户端内部做逻辑处理

    作者回复: 重定向是HTTP协议约定的,是由客户端发起的,需要客户端处理。

    共 3 条评论
  • 2021-02-04
    LVS工作在IP层和链路层,为什么常常被称作4层负载均衡呢?
    共 1 条评论
  • JRich
    2020-10-22
    老师,我不太理解网络层负载均衡修改了目标ip而源ip地址未改啊,应用服务器处理完不能直接给客户端响应吗?或者说客户端要校验响应的源ip和请求的目标ip是否一致吗?
    共 1 条评论
  • 吃饭睡觉打酱油
    2020-06-07
    老师,请问下,数据链路层负载均衡时,应用服务器集群里面的服务器在网络上也是对外暴露的么?
  • 探索无止境
    2020-03-02
    老师您好,目前lvs和nginx都可以实现第四层负载均衡,在技术选型上您是如何思考做权衡的?
    共 1 条评论
  • Frank
    2020-02-21
    咨询一个问题:数据链路层负载,应用服务器和负载均衡服务器都使用相同的虚拟 IP 地址,这样 IP 会不会发生冲突?
    共 3 条评论
  • 奔奔奔跑
    2020-01-18
    智慧老师,请问一个内核限流是什么技术?和Linux集成了LVS有一些联系吗?