开发者学堂课程【高校精品课-上海交通大学-企业级应用体系架构:Clustering】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/75/detail/15837
Clustering(一)
内容介绍:
一、 建立集群的作用及目的
二、 建立集群的可靠性、可用性及可服务性
三、 集群可靠性的概率计算
四、 服务器状态维护及 httpsession 对象的寻找
五、 ngin x 的使用
六、 全文搜索的概念
一、建立集群的作用及目的
缓存可以建立集群,后端的应用服务器或者数据库服务器都可以做集群,建立集群的目的是让更多的并发的用户能够访问系统。这些用户可能是在不同的地方,所以看到的系统可能是该系统的镜像,因为在一些骨干城市,比如上海、北京、广州,所有的用户都是就近存储,访问的。
在处理的过程中,使用的网站可能不是全国性的网站,但是数据并发数据量会很大,比如上海交大,很多人都会有感受,就是在交作业的时候 Canvas 就会有问题,甚至出现作业交不上去的情况。也就是每秒钟到完成的交易的数量会非常大。所以可能没有太多的能力去处理,所以要增加计算机的数量,也就是要建立一个社群。
二、建立集群的可靠性、可用性及可服务性
当系统的压力变得很大的时候,建立集群可以提高系统的可靠性和可用性。
当一台机器因为某些原因出现故障,仍然可以去使用它,这就体现了可用性。比如说发起拒绝分布式、拒绝服务攻击。攻击集群的时候,因为里面有很多的服务器。它们可能处在不同的位置,可以往外提供这种服务,以致系统不至于瘫痪。
可用性是指只要一直提供服务器就可以,可靠性是指不但要提供服务,并且提供的服务要能使用。比如在可用性面前,可以做一个策略,当用户数量非常多的时候,不把404或者500这样的错误抛出去,可以告诉系统它很忙,稍后再试,这就是一种可用性。也就是不会把异常直接抛在前段给用户去看。
但可靠性就是说不是以400、500一行,一捕获不给它抛出来看,而是必须提高提供可靠的服务,也就是不能告诉系统它很忙,只要访问就必须服务,所以它的要求也更高一点。
可服务性就是提供的服务,它能够提供质量连续的,一致的服务出去。一会儿因为数据量多,所以提供的数据精度下降了,一会儿提供的数据精度有上升了,其服务质量没有一致性。
可扩展性是指的系统的处理能力,包括存储、处理器、网络能力随着增加新硬件的同时,它就几乎可以呈线性增长。意思是说一台服务器如果能服务100个并发用户,如果两个实际上就只能服务190个。三个,就只有270个。
它不会是完全线性,如果线性度越好,就说明客观性越好。如果线性度很差,比如说两台只能提120个,说明这系统当中一定存在瓶颈,集群就会要求添加硬件资源上来之后,处理能力达到最好能够限制增长,要求系统当中不能有很明显的一个瓶颈。建立集群的时候,内部会有很多风险,但是对用户来说,他们应该看到的就是一台机器,不用去管这个机器有多少台,也就是他们只需访问一个域名,比如说访问新浪的门户网站就会发现它肯定不是在全球只有一台服务器,还有很多人来支持。在访问的时候究竟访问,但是用户不用去理会这件事情,也就是用户只需要一个域名就能够自动访问到,把请求转发到一个离他最近的服务器上,不需要它自己去处理需要访问哪一台具体的服务器,这就是集群的一个特点,集群里面所有的计算机就是集群的一个节点。
当客户端发送请求过来的时候,就像新浪网站,它会有一个主服务器做了负载均衡,并且在集群的节点里面,会依照某个原则把请求转发到某一台机器上。比如按照最新的负载原则,如果有5个或者3个、4个请求正在处理,那么该服务器就会把请求转发到三台机器上面来做,这是最基本的原理。也就是根据负载均衡的策略,把用户的请求调度到某一台机器上,这就是集群,可以发挥其作用。当处理完之后,请求就会发回客户端。
假如上海交大的IP地址前面是202.120.40,这些机器分别是1、2、3、4、5、6。当进行访问时,请求就被转发到1这台机器上,并且1会根据其负载均衡的策略调度到第二台机器上。第二台机器收到请求之后也会把请求返给谁,并且处理完请求之后,不会再经过负载均衡器。负载均衡器工作量不大,它只是拿到请求之后决定五个节点当中的某一个,按照一定的策略机会,然后就会把请求转发过去,由服务器处理后把结果返回给客户端。
反过来是不需要让负载均衡器把请求通过转发,所以其压力会变得比较小。在集群里为什么可靠性会提高。实际上,因为集群就是建立一种形式的冗余。这时候就可以看到系统当中没有单一故障的节点,就是说所有的服务器全部都瘫痪之后,才有可能说这个集群没有办法向外提供服务。
三,集群可靠性的概率计算
可靠性=1-(1-f%)ⁿ,f 指的是好的几率为99.8%,(1-f%)ⁿ指的是机器出故障的概率,也就是(0.2%)ⁿ。有这么大的概率所有的机器都坏。只要有一台机器是好的,这个服务仍然可提供。
1 指的是所有的几率100% ,100%减去所以机器坏掉的概率是整个集群可以使用的概率。小于1的数字它的n次方就会越来越小,集群数量越多整个的可能性就越大。所以这是通过建立冗余的方式来提高系统的可靠性,这就是通过集群怎么来提高系统的可靠的一个方案方法以及原理。
那么可服务性和可扩展性,尤其是可扩展性,增加额外的服务器之后,它就可以去向外提供,比如说,基本成线性服务能力的一个扩展,但在真正在做负载均衡的时候,会有一个很麻烦的事情,这个事情就叫做由于会话的粘滞性带来的。
四、服务器状态维护及 httpsession 对象的寻找
1. httpsession 对象的使用
session 该词提到过,比如说 httpsession ,由于htt 这个协议是无状态的,所以导致客户端和浏览器之间,客户端浏览器和服务器之间在以多个请求发了一个响应,然后连接断掉,但是在第一个请求,第二个请求已经到第三个请求之间如何知道是同一个人?就是靠httpsession 对象来维护, httpsession 对象是在服务器的一端。在 cookie 里面存了 http 对象,也就是跟客户端相关的 ID 。会话粘滞性是指如果在做负载均衡时,有一些方法且要有一些原则或者是基准。比如说对称去发、随机发或者轮流发,这样可以保证每个机器传递过去的这个请求数是一样多的,但是请求有长有短,所以如果碰巧遇上的全是场景球,那么压力就会很大,所以也可以去实时动态的去看。
当前三台服务器里面哪一个负载最轻就把新的请求转发给,无论用哪种策略,都会发现好像这两种策略里面的客户端。比如一个是 a 一个是 b, a 客户端发一个请求来,如果是锦标赛,假设a给了1,紧接着 a 在发一个请求过来的时候,可能碰巧给2或者3就不在1上。如果是随机的一个转发的话,那么再发个请求过来的时候,可能碰巧就会转发给2或者3,就不在1上。如果是随机转发,那么把最小最复杂的来做,更不能保证 a 发过去的两个请求被调度到同一台机器上。如果不能满足这个条件,这就是会话粘制性被破坏。比如 a 的第一个请求来了,被调度到第一台机器上,不管是对称方式、锦标赛方式还是随机调度方式,比如说用负载最轻的方式去决定 a 应该给谁。因为某种原因 a 调不到1上,由之前写的代码可知在 request 上面去 get httpsession 。有两种可能,一是第一次来请求,那么得到的是空,于是它就创建了一个新的 http session 对象,该对象显然就在这台机器上。
2. httpsession 对象的寻找
用画一个圆圈的a来表示a的 http session 对象。当下一次请求如果调度到了该机器上 httpsession 就不为空,就会把 a 取出来,然后在其基础上去继续做是没问题的。问题是,如果第二次请求被转发时,因为是锦标赛方式,或者是负载最轻的方式,假设说被调度到了2这台机器上,如果再执行 get httpsession 的话,只能在2这台服务器上去找。如果找不到1服务器上的 httpsession 对象,有两个选择。第一,新创建一个。为了有区别与新创建的对象,可把新建的对象称为 a’ , a 上面的会话对象在它本身和 a’ 这两台服务器都有,显得浪费,并且也用不到。
第二,a 得不到时会在集群里面广播一下谁有。第1台机器就会显示拥有,然后它拥有两个策略,第一,把 a 的 httpsession 对象从1传输给2,然后在2上执行。第二,如果该请求2不做了,就给1做,不管哪一个平台都不太好。2不做,给1做,那么负载均衡是有情况的,如果1把 a 的 session 对象想要传过来。首先,需要广播一下才知道 a 有session 对象,其次传送过程会浪费时间。如果第三次请求传到了第三台机器上, 1和2都会提示已经有了 a ,那么第三台机器会判断谁是最新的,然后不把它传过来。
这种方式是因为会话的粘滞性带来的,所以就会出现第三种策略,除了锦标赛方式或者负载最轻的方式。还有一种策略,比如用用户的 IP 去做hash, hash 在哪台机上就在哪台机器上,比如其 hash 的计算方法是其IP的四段值加起来除以3得到一个余数。 0就在1上,1就在2上,余数2就在3上。以这种方式存储,那么只要是用户来请求,都会被转发到一台机器上。所以其会话状态就能够拿到,这就是负载均衡里面的 ip-hash 的方式,该方式就是为了去解决会话粘滞性的问题。
3.服务器状态的维护
在前面第二节课中讲到会话状态非常重要,因为会话状态带来了很多的麻烦。
如果会话状态能够推到服务器端,这重复起上推到客户端,服务器端完全是无状态的,那很多问题都解决了。包括在第一节课中提到要创建多少个对象以及这里讲的会话的粘滞性问题都可以解决,所以现在看到的很多的应用都在把状态往客户端去处理。因为客户端现在除了 cookie 还有 local story 这样的对象,也就是在H3~5 里面,开放 local story 这样的对象,如果把状态能够加密一下,存储到这里,让用户不能轻易的解开,然后去修改。那么就可以来保证服务器的状态,一旦服务器的状态像之前提到的很多跟客户端状态维护相关的问题都可以解决。如果发送一个请求过来之后,调度给了某一台机器,结果该台机器崩溃了。
解决方法一种是把请求重新转发一下,这就是请求级别的容错。在整个系统里面,请求是会话的一部分。如果请求失败了,并且整个会话都会出错,就意味着不但要把这个请求重发。还得把会话状态和请求一起重发给接手去管理的服务器,所以在进行容错的时候,会有请求级别的容错和会话级别的容错两个级别。也就是会话状态必须在又给转发过去的。
比如说二崩溃的状态,转发给三,原来会话状态是在二上面,像刚才所提到的 ip-hash 的方式,这个客户端其请求都在二上,所以二会有一个session对象。 当二崩溃时,光把那个请求转发是没有用的。这个请求转发是没有用的。要把 a 的会话状态给重建出来,再把当前请求转发才有意义。如果要做到该级别的容错就会更复杂一点。容错就是依靠冗余来实现的,也就是未来a这个对象的客户端的httpsession 对象,除了该平台图像存储之外,其还会找另外一台服务器去做备份。这样的话就可以做到在会话状态崩溃掉的时候,可以去重建。
4.幂等操作的理解
http协议有get、put、post等重建方法。当时所讲的方法叫做幂等,所谓幂等就是如果该请求调用方法被转发了多次。那么每一次去调用,只要用相同的参数去调用,就会得到相同的结果。比如说 get 就是要获取某一个网页。那 get 一次,两次,十次都是该网页,只要这个 URL 不发生变化所得到的结果都是一样。如果页面里面大量操作都是 get类型,幂等的操作就不会有什么问题。如果把整个请求给它转发到另外一台机上,或者说这个请求失败了,重发一次,会不会带来不良的影响?
与 get 形成对比的,比如 put就不是,put 对应的意思是去写,在 write 协议里面, put 对应的就是insert, 很显然, insert 一次和两次是不一样的,所以 put 就不是一个幂等的操作,可知这是 http 的方法。如果自己写的一些方法让客户端去掉最好能实现幂等这个动作。当然不是说所有方法都可以是幂等,put 不可能是一个幂等,应该让幂等的方法尽量的多不是逆等方法尽量的少。
5.请求失败的解决办法
如果一个请求失败了,它的时间点,有三个不同的时间点。第一,请求已经产生了。在请求产生之后,在方法调用在开始执行之前,该请求发生了失败,比如说因为网络问题,请求发出去了,但是没到服务器端或者到服务器端正在排队,还没有办法执行。
因为要去访问数据库,结果数据库加锁了,这种时候如果发生失败,就是比较容易去容错的,只要重发一次即可。如果该服务器已经开始执行,但是没有执行结束,请求发生了故障,这时候较麻烦一点,所以需要决定该操作是要从头开始执行,还是在这里面设置一些断点checkpoint ,将来可以回滚到之前的某个状态去。这就是在设计代码时要考虑的。如果有一个方法在执行,里面尽量用 transaction, 其提供一种像 checkpoint 的功能,其执行到某个地方,如果需要可以回滚到原来的某个状态去。还有一种是已处理的服务器端,其响应没有传输到客户端之前去请求失败会如何?
比如因为服务器端已经处理完,请求想要发回去的时候网络断掉。这时该服务器不能再执行一遍这个方法,应该把该请求给缓存。然后到通的时候把它发出去。这也是之前为什么要讲消息通信,可以看到消息通信在应用这种局面的时候比较方便其可以把返回的结果给它存储到一个消息队列里。然后不断地尝试去转发直到执行完毕。如果还没有把响应发回到客户端之前网络出现了故障或者因为其他的原因,无法发送成功,客户端没有收到。这时容错较容易出现。