You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

76 lines
9.9 KiB
Markdown

2 years ago
# 24 | 负载均衡架构如何用10行代码实现一个负载均衡服务
负载均衡是互联网系统架构中必不可少的一个技术。通过负载均衡,可以将高并发的用户请求分发到多台应用服务器组成的一个服务器集群上,利用更多的服务器资源处理高并发下的计算压力。
那么负载均衡是如何实现的,如何将不同的请求分发到不同的服务器上呢?
早期,实现负载均衡需要使用专门的负载均衡硬件设备,这些硬件通常比较昂贵。随着互联网的普及,越来越多的企业需要部署自己的互联网应用系统,而这些专用的负载均衡硬件对他们来说成本太高,于是出现了各种通过软件实现负载均衡的技术方案。
## HTTP重定向负载均衡
HTTP重定向负载均衡是一种比较简单的负载均衡技术实现。来自用户的HTTP请求到达负载均衡服务器以后负载均衡服务器根据某种负载均衡算法计算得到一个应用服务器的地址通过HTTP状态码302重定向响应将新的IP地址发送给用户浏览器用户浏览器收到重定向响应以后重新发送请求到真正的应用服务器以此来实现负载均衡。
![](https://static001.geekbang.org/resource/image/74/4f/74d1a57c8d5b168501e15cc92da0034f.png)
这种负载均衡实现方法比较简单如果是用Java开发的话只需要在Servlet代码中调用响应重定向方法就可以了。在简化的情况下只需要不到十行代码就可以实现一个HTTP重定向负载均衡服务器。
HTTP重定向负载均衡的优点是设计比较简单但是它的缺点也比较明显一方面用户完成一次访问就需要请求两次数据中心一次请求负载均衡服务器一次是请求应用服务器请求处理性能会受很大的影响。
另一个问题是因为响应要重定向到真正的应用服务器所以需要把应用服务器的IP地址暴露给外部用户这样可能会带来安全性的问题。负载均衡服务器通常不部署应用代码也会关闭不必要的访问端口设置比较严格的防火墙权限通常安全性更好一点。因此一个互联网系统通常只将负载均衡服务器的IP地址对外暴露供用户访问而应用服务器则只是用内网IP外部访问者无法直接连接应用服务器。但是使用HTTP重定向负载均衡应用服务器不得不使用公网IP外部访问者可以直接连接到应用服务器系统的安全性会降低。
因此HTTP重定向负载均衡在实践中很少使用。
## DNS负载均衡
另一种实现负载均衡的技术方案是DNS负载均衡。我们知道浏览器或者App应用访问数据中心的时候通常是用域名进行访问HTTP协议则必须知道IP地址才能建立通信连接那么域名是如何转换成IP地址的呢就是通过DNS服务器来完成。当用户从浏览器发起HTTP请求的时候首先要到DNS域名服务器进行域名解析解析得到IP地址以后用户才能够根据IP地址建立HTTP连接访问真正的数据中心的应用服务器这时候就可以在DNS域名解析的时候进行负载均衡也就是说不同的用户进行域名解析的时候返回不同的IP地址从而实现负载均衡。
![](https://static001.geekbang.org/resource/image/6c/c7/6c504d347d9aa2bca5dedc3e9d750dc7.png)
从上面的架构图可以看到DNS负载均衡和HTTP重定向负载均衡似乎很像。那么DNS会不会有性能问题和安全性问题呢
首先和HTTP重定向不同用户不需要每次请求都进行DNS域名解析第一次解析后域名缓存在本机后面较长一段时间都不会再进行域名解析了因此性能方面不会是问题。
其次如果如图中所示域名解析直接得到应用服务器的IP地址确实会存在安全性问题。但是大型互联网应用通常并不直接通过DNS解析得到应用服务器IP地址而是解析得到负载均衡服务器的IP地址。也就是说大型网互联网应用需要两次负载均衡一次通过DNS负载均衡用户请求访问数据中心负载均衡服务器集群的某台机器然后这台负载均衡服务器再进行一次负载均衡将用户请求分发到应用服务器集群的某台服务器上。通过这种方式应用服务器不需要用公网IP将自己暴露给外部访问者避免了安全性问题。
DNS域名解析是域名服务商提供的一项基本服务几乎所有的域名服务商都支持域名解析负载均衡只需要在域名服务商的服务控制台进行一下配置不需要开发代码进行部署就可以拥有DNS负载均衡服务了。目前大型的互联网应用淘宝、百度、Google等全部使用DNS负载均衡。比如用不同的电脑ping [www.baidu.com](http://www.baidu.com)就可以看到不同电脑得到的IP地址是不同的。
## 反向代理负载均衡
我在[第22篇](https://time.geekbang.org/column/article/188667)缓存架构中提到用户请求到达数据中心以后最先到达的就是反向代理服务器。反向代理服务器查找本机是否有请求的资源如果有就直接返回资源数据如果没有就将请求发送给后面的应用服务器继续处理。事实上发送请求给应用服务器的时候就可以进行负载均衡将不同的用户请求分发到不同的服务器上面去。Nginx这样的HTTP服务器就会同时提供反向代理与负载均衡功能。
![](https://static001.geekbang.org/resource/image/d6/43/d656da82d725cb206dbcf7cebb420e43.png)
反向代理服务器是工作在HTTP协议层之上的所以它代理的也是HTTP的请求和响应。作为互联网应用层的一个协议HTTP协议相对说来比较重效率比较低所以反向代理负载均衡通常用在小规模的互联网系统上只有几台或者十几台服务器的规模。
## IP负载均衡
反向代理负载均衡是工作在应用层网络协议上的负载均衡因此也叫应用层负载均衡。应用层负载均衡之下的负载均衡方法是在TCP/IP协议的IP层进行负载均衡IP层是网络通讯协议的网络层所以有时候叫网络层负载均衡。它的主要工作原理是当用户的请求到达负载均衡服务器以后负载均衡服务器会对网络层的数据包的IP地址进行转换修改IP地址将其修改为应用服务器的IP地址然后把数据包重新发送出去请求数据就会到达应用服务器。
![](https://static001.geekbang.org/resource/image/a6/dc/a62e851bec43aac1a30cc45db11abbdc.png)
IP负载均衡不需要在HTTP协议层工作可以在操作系统内核直接修改IP数据包的地址因此效率比应用层的反向代理负载均衡高得多。但是它依然有一个缺陷不管是请求还是响应的数据包都要通过负载均衡服务器进行IP地址转换才能够正确地把请求数据分发到应用服务器或者正确地将响应数据包发送到用户端程序。请求的数据通常比较小一个URL或者是一个简单的表单但是响应的数据不管是HTML还是图片或者是JS、CSS这样的资源文件通常都会比较大因此负载均衡服务器会成为响应数据的流量瓶颈。
## 数据链路层负载均衡
数据链路层负载均衡可以解决响应数据量大而导致的负载均衡服务器输出带宽不足的问题。也就是说负载均衡服务器并不修改数据包的IP地址而是修改数据链路层里的网卡mac地址在数据链路层实现负载均衡。而应用服务器和负载均衡服务器都使用相同的虚拟IP地址这样IP路由就不会受到影响但是网卡会根据自己的mac地址选择负载均衡服务器发送到自己网卡的数据包交给对应的应用程序去处理处理结束以后当把响应的数据包发送到网络上的时候因为IP地址没有修改过所以这个响应会直接到达用户的浏览器而不会再经过负载均衡服务器。
![](https://static001.geekbang.org/resource/image/e4/4c/e4cc84d4c9f7d76082df4163ac8d414c.png)
链路层负载均衡避免响应数据再经过负载均衡服务器,因而可以承受较大的数据传输压力,所以,目前大型互联网应用基本都使用链路层负载均衡。
Linux上实现IP负载均衡和链路层负载均衡的技术是LVS目前LVS的功能已经集成到Linux中了通过Linux可以直接配置实现这两种负载均衡。
## 小结
负载均衡技术在早期刚出现的时候设备昂贵使用复杂只有大企业才用得起、用得上但是到了今天随着互联网技术的发展与普及负载均衡已经是最常用的分布式技术之一了使用也非常简单。如果使用云计算平台只需要在控制台点击几下就可以配置实现一个负载均衡了。即使是自己部署一个负载均衡服务器不管是直接用Linux还是用Nginx也不是很复杂。
我在这里主要描述的是负载均衡的网络技术架构。事实上,实现一个负载均衡,还需要关注负载均衡的算法,也就是说,当一个请求到达负载均衡服务器的时候,负载均衡服务器该选择集群中的哪一台服务器将请求发送给它?
目前主要的负载均衡算法有轮询、随机、最少连接几种。轮询就是将请求轮流发给应用服务器,随机就是将请求随机发送给任一台应用服务器,最少连接则是根据应用服务器当前正在处理的连接数,将请求分发给最少连接的服务器。
## 思考题
利用HTTP重定向只需要很少代码就可以完成一个简化的负载均衡你能否利用你熟悉的编程语言写一个简化的HTTP重定向负载均衡demo
欢迎你在评论区写下你的答案,我会和你一起交流,也欢迎把这篇文章分享给你的朋友或者同事,一起交流一下。