对于服务端的开发者而言,“负载均衡”这个词听起来可能并不陌生,那么负载均衡是为了做什么的呢?这个负载均衡服务器最基本的功能就是要保证所有提供服务的机器要大概一样忙,不能让一台机器太忙,也不能让一台机器太闲,这样就能保证集群中的机器都物尽其用。
说起负载均衡,如果从戏里说来,我们可能要了解太多的网络原理里,咱们就简单的先把里面可能设计的知识点说下吧,负载均衡相关的,需要了解DNS协议(其中又会引申出来HTTPDNS等等只是内容),CDN,如果用的负载均衡啥的是“阿里云”啥的,那咱还需要了解下数据中心,云主机方面,NAT,openSwitch,VXLAN,GRE,容器相关知识Docker,Flannel,Calico等等,想想就可怕。好了,言归正传,今天咱们先简单了解下这其中的基本内容。
1.DNS做全局负载均衡
说起DNS,那DNS是做什么的呢?之前咱们知道每个服务器实际上对应着一个访问它的IP地址,但是对于用户直接去访问的时候,记IP实在是太困难了,于是就有了DNS,通过名称,来查看起具体的地址。注意的是,日常使用的时候访问网站都要经过它,那么它故障的话整个网络都要GG,所以它一定是高可用,高并发和分布式的,于是有树状层次结构如下。
知道了它的层次结构,那么DNS是如何解析的呢?
1.用户去访问 www.google.com这个网站,向本地DNS询问,这个域名对应的IP是什么?
2.本地DNS收到了用户的请求,就去找它自己的缓存,看看有没有www.google.com对应的ip地址,如果有的话就直接返回,没有的话,本地DNS会向根DNS发送一个请求,进行询问。
3.根DNS收到来自本地DNS的请求,看最后一层后缀是什么,然后给本地DNS返回对应顶级DNS的地址,供下一步询问。
4.本地DNS向顶级DNS进行询问,www.google.com的IP地址是什么?
5.顶级DNS收到请求后,返回权威DNS服务器的地址,供进一步的询问。
6.本地DNS向权威DNS服务器进行询问,www.google.com的IP是什么?
7.权威DNS将www.google.com的IP地址返回给本地DNS。
8.本地DNS将IP地址返回给用户,并在自己这里建立对应缓存,用户就可以和目标服务器建立连接了。
咱们了解了DNS了,那么如何做负载均衡呢?
1.DNS做内部负载均衡
我们知道的,一般服务端做的肯定是要连接数据库的,那么当配置数据库的时候要配置IP还是域名呢?如果配置域名的话就可以实现负载均衡了,每次连接,我都去按照一定的规则去返回数据库的ip。不过这样不太建议哈,只是举个例子,这个例子不太合适,暂时没想到更贴切的,哈哈。
2.全局负载均衡
现在应用为了保证高可用性,都是不实在多个机房的,每个地方对应的ip是不同的,为什么要这么做呢?道理很简单,就是某一处的机房挂了,从DNS服务器里面删除那个挂了的数据中心对应的ip,就能保证应用正常使用。另外,对于用户访问来说,我们肯定是想要让他访问更近的数据中心,访问速度会最快,经历路程最短。
但是有个问题需要注意的是,这其实存在问题,缓存问题,域名转发问题,出口NAT问题,域名更新。
1.从咱们解析过程看,如果有缓存的话,会直接吧缓存的ip直接返回给用户,那如果这个ip发生了变更了呢?
2.还有的运营商将某些静态页面直接缓存了,那么就不会去访问真实ip地址对应的实时内容,那么页面发生了改变呢?
3.本地DNS会缓存就近的ip,那么,上次是最近的,过了一阵后,这个ip还是最近的吗?可能不一定。
4.咱们知道,咱们最初的流量肯定会到运营商,但是某些运营商可能会将流量转发给另一个运营商在进行请求,那么这就产生了问题,当分配就近的IP的时候,返回的可能是针对与被转发的那个运营商的,而不是当前用户第一个运营上的,那么这就不是最近的了吧。
5.NAT在进行转换IP的时候,IP就变了,那么我实际到权威DNS的IP就没法去判断是否是原始的,没有转过的,那么可能就判断错了。
6.域名更新的时候,我们很多时候会等权威DNS进行变更,但是吧,刷新速度往往是不同的,那么有的时候可能反问的就是错的。
这么多问题,看起来就可怕,不过随着技术的更新迭代,又有牛人创造了HTTPDNS,其实解释起来也简单,就是不走传统的DNS解析,而是走自己搭建的基于HTTP的DNS服务器集群,就相当于走了自己的配置,自己控制主动权。不过这一般依赖于客户端SDK。
2.进一步的优化 CDN
CDN与DNS有相同点,都是分布在一个多区域,多运营商的分布式系统,去找边缘节点的思路也很是相同,都是通过层层解析。
1.在没有CDN的时候,用户输入www.google.com访问本地DNS,然后去找真实服务器的IP,访问这个网站。有了CDN之后呢,我们会在google.com这个权威服务器上设置一个CNAME的别名,指向另外一个域名,例如www.google.cdn.com,返回给本地的DNS。
2.本地DNS拿到这个新域名,在访问的时候就是去访问google.cdn.com的权威服务器了,在这个服务器上还是会设置一个CNAME别名,指向CDN网络的全局负载均衡器。
3.接下来,本地DNS服务器去请求CDN的全局负载均衡去解析域名,选择合适的服务器。
4.返回被选中的机器的IP返回给客户端,客户端就去这个地址去下载所需要的资源就行。一般缓存静态图片,网页啥资源,当然也是支持流媒体的
3.负载均衡
其实实现负载均衡的方式有很多,例如通过Linux内核的Netfilter框架,虚拟服务器LVS,Haproxy等均可以实现,接下来咱们还是讲讲Netfilter吧,因为我觉得这个的还可以顺便用iptable举例讲讲安全。
Netfilter是一个Linux内核框架,它可以在网络包进入本级以后解析的几个节点内插入Hook函数,也就是我们常说的钩子。这些函数可以截取数据包,并对数据包进行一定的干预。
这个可能比较难理解,根据这个特性咱们可以把它用在咱们内部的负载均衡上,根据咱们自己的一些逻辑,然后把请求分配给不同的机器处理。先说以下咱们网络包进来的几个节点吧。
在网络包进来以后,先拿下来MAC头,看看是不是自己的,是的话走进去咱们的几个节点。
1.PREROUTING:取下网络包的IP头,开始准备进行路有判断,路由判断前的那个节点就是这个。
2.INPUT: 取下IP头后,发现是我的,发给上面的传输层
3.FORWARD:取下IP头后,发现这个不是我的,转发出去
4.OUTPUT:上层处理完毕后,返回处理结果发送出去
5.POSTROUTING:最后节点
这个应用有个特别著名的程序,就是iptables,这个咱们很多时候用在防火墙。具体实现就是在那5个节点埋函数,功能主要分为连接跟踪,数据包过滤,网络地址转换,数据包修改几类。
其实这个负载均衡思路也很好想了,简单的而言,就是请求进来后,咱们转发的时候,去按照每台机器的情况,转发给比较闲的机器而已。