前言:
关于集群调度有几种类型,我想大家都清楚 . 主流的方案还是基于proxy代理层的方案, 具体点说不管是4层的TCP LVS,7层的Nginx, Haproxy都是在代理层面实现的调度。 这样最大的优点是入口统一,规则统一,那么最后调度也就统一了。
该文章写的有些乱,欢迎来喷 ! 另外文章后续不断更新中,请到原文地址查看更新. http://xiaorui.cc/?p=3792
集群调度的方式有那么几种:
- RR轮询,轮询调度算法的原理是每一次把来自用户的请求轮流分配给内部中的服务器,从1开始,直到N(内部服务器个数),然后重新开始循环。算法的优点是其简洁性,它无需记录当前所有连接的状态,所以它是一种无状态调度。
- 权重轮询,根据后端主机的能力不同,或特定需求来配置调度主机的权重。 (特定需求是啥,最简单的来说 我新上线了一个主机的代码,肯定是希望最初的调度权重要少一点。 )
- 最少连接,最少连接调度算法是把新的连接请求分配到当前连接数最小的服务器,最小连接调度是一种动态调度短算法,它通过服务器当前所活跃的连接数来估计服务器的负载均衡,调度器需要记录各个服务器已建立连接的数目,当一个请求被调度到某台服务器,其连接数加1,当连接中止或超时,其连接数减一,在系统实现时,我们也引入当服务器的权值为0时,表示该服务器不可用而不被调度。
- 加权最少连接,最少连接算法和加权算法的效果.
- 源地址散列,这样可以实现会话绑定,主机前后都会命中一台服务器,但这配置带来的问题是负载不均衡了…
- 目的地址散列, 自己想去吧…
- more…
那么像7层的nginx、haproxy又有什么新奇的调度方式? 毕竟是7层代理服务,可以解析到http协议层.
cookie负载调度,顾名思义安居cookie来命中后端主机.
根据URL Hash调度,一般多用在cdn服务器上.
巴拉巴拉….
对于代理层面的均衡描述的还是有点粗,更多的信息大家可以自搜。 动态权重和过载保护又是什么呢?
静态权重算法我们都熟知,就是用静态的方式来标识某个主机的调度百分比,也就是权重比例。
# xiaorui.cc upstream backend { server b1.xiaorui.cc weight=5; server b2.xiaorui.cc weight=3; server b3.xiaorui.cc weight=1; }
静态权重 vs 动态权重
我们虽然可以提前来标识这些主机的调度权重,根据每个主机的性能情况. 但问题我们不能这么乐观, 比如 b1.xiaorui.cc 的权重是5 ,该主机本身的硬软能力是很好,但由于各种原因导致某个请求的消耗资源比较大,另外该主机权重比较大,这就造成了后面的更多请求被陆续阻塞。
总的来说,动态权重比静态权重更加切近于后端服务的状态… b1 主机的权重是5 ,但因为各种原因出现了timeout超时 ,我们可以针对这些状态进行不计算。
我曾经用python和golang都实现过动态权重的调度服务, 实现原理有个入门到深入的过程 O(∩_∩)O~ … 最一开始的方式是所有主机权重默认为50,调度的限制是0-100 , 也就是说,一开始的时候权重都是50,如果访问成功,那么权重加 1,如果发现timeout,那就减1 . 这时候一定要考虑好边界的问题, 权重到100后为止,如果被减到0 ,该记录会放到一个监控队列里,一个定时器线程重试这些后端主机.
后来又继续改进了这种动态权重的方法, 以前的调度服务单纯根据timeout来动态配置权重的方法还是不够精细… 我们可以通过后端节点上报,或者代理服务主动去获取的方法来得知主机的状态. 这样更有利于分配权重…. 当你的能力还不足以驾驭这么精细调度服务的时候,我还是推荐大家直接用静态的配置,动态权重的边界条件还是蛮复杂的.
服务发现模式
到现在为止,动态权重调度算法说的差不多了. 接着后面要讲述服务发现,对于后端的可用性方面,所谓的动态权重调度跟服务发现有些相像的。 然而服务发现模式更适合微服务架构, 在我接触的业务场景下会出现频繁的上下线,上线的服务会自个就绪通知给调度服务开始工作。
先要明确一点, 后端主机会上报自己的状态到一个调度服务里. 这个调度服务不会做反向代理 ,只是提供调度信息. 最一开始服务发现是让后端节点注册上来,但随着架构的改进,我们不单单要求他能上报心跳,还会要求后端节点上报自己的状态,负载程度… 这样一个更加简单的调度服务就出现了. 在微服务架构下,很多主机的调度不单单非要有代理层,更多人会选择服务发现模式,这个是现在微服务部署下相当流行的调度方案。
我们可以使用etcd、consul 来做调度服务… 还可以使用skydns来实现… 我更喜欢skydns,他的性能要比consul要好 . 那么这样的访问流程是,client 向 consul 要一个可用调度地址,然后去访问后端。 后端服务会跟consul做状态机制的交互,而不会做反向代理的访问交互。 另外为了避免consul的访问压力,我们也会在client层做一层缓存。
过载保护又是什么?
调度服务知道自己的能力是多少,所以超过一定阈值的访问就不再接受。 这是很明智的方法,像微信过年抢红包,热点的在线直播都会做一些过载保护。 你会发现,a,b先后脚放到一个服务,a没有问题,b因为超过访问阈值不能正常的访问。 这里就不多描述了,在一个热点系统下适当配置过载过户很有必要,这样最少能让部分请求无问题。
尽量多优化自己的架构吧… 见过有些服务设计的很恶,加机器都没法解决,这是由于没有设计好可分布式扩展.
文章还没有写完,待续中 xiaorui.cc
…