高可用的一些思考和理解
本文来源公众号:匠心零度
在目前的互联网大时代,在高并发等冲击下,还必须保证服务高可用,如果服务不高可用那么意味着:
- 系统不是7*24小时提供服务,那么用户体验就特别差了,可能用户下次不用了,留不住用户。
- 当系统不可用的时候,对公司的形象是有所影响的,BAT类似这种技术都是象征的。
- 最重要的一点,当系统不可用的时候,直接损失就是金钱!!!基本都是秒算损失的,依稀记得2015年5月28日携程网瘫痪事件,按照携程一季度财报公布的数据,携程宕机的损失为平均每小时106.48万美元。
高可用是非常复杂的,自己水平有限,并不能涵盖那么多,只能说是自己对高可用的一些思考和理解。
那么怎么使系统高可用呢?
我们不能让服务器不挂,让服务不挂,那么怎么样让这种必败的局面不会有问题呢,就是可以挂,服务可以坏,那么怎么让系统还可以提供服务呢?
首先如果机器有很多,服务有很多,就算坏了一部分也没有问题啊,必败的局面得到的解决。下面进行一步一步剖析,如果机器里面存储了特定值,那么就不能扩展,必须是用挂的那台机器,那么这个是不行的,机器问题好解决,相同的配置替代是容易的,那么应用服务也是类似,应用服务可以不存储状态有关的值在任何机器而自己内部不会有存储一些特定的特征数据,如果有就没办法很容易的扩展,只有当每个主件都是一样的时候,无任何差异,我们才好替换,容易扩展,那么这个就叫着服务的无状态化。
假如目前服务已经是无状态化了,那么如何让系统动态的感知到服务挂了呢?不然请求还是回去到挂的那台机器,怎么转移到新的机器呢?那么可能就需要服务发现与注册了。
如果达到了上面的情况,应对一般的情况基本已经够了,但是互联网是复杂的,刚刚说的机器坏,服务坏了的问题,那么如果网络出现短暂不通因为怎么办呢?
所以服务之间应该有心跳的检测,来定期看看是否可通(机器坏了,服务挂了,网络不通了)反正就是不可达了。这种情况通过服务注册与发现即可解决,但是有时候网络是闪断下那么在那种特定的情况呢?比如刚刚a服务已经把请求发送给了b服务,b服务已经接收到请求了,那么这个时候忽然网络断了,但是b服务进行把逻辑处理做完成了,但是a服务反应的就是没有响应,前台超时了,那么再一次触发下,那么如果b服务把之前的逻辑再做一遍是否存在问题呢? 比如支付,已经付款200元,难道再付款200元吗?这里需要提到一个幂等性的设计概念,什么是幂等呢,就是多次执行结果都一样,如果有幂等性设计那么就不怕这种情况了,在没有得到反馈情况重试即可,也不会出现问题。
达到上面说的这些就是应对机器坏了,服务挂了,网络不通或者闪断等情况已经基本没有什么大问题了,那么目前互联网都是高并发,那么在高并发的情况,如何来提高系统的能力的?
就和搬东西一样,一个人慢,可以多来点人一起帮东西,由于上面的架构是可以添加机器,服务的,那么很容易想到的就是多来点机器和服务。那么这样一定比机器少要快的,比如有5台机器,那么很多请求过来了,用什么策略让他们分摊到不同的机器呢?通过设备,通过一些软件层面,但是其中一定有服务发现注册,不然没办法动态知道节点变化,还有就是对一些信息的控制,黑白名单,访问频率等。很多时候,加机器可能看起来比较low,但是有时候的确比较有效,但是也不能一味的加机器,有些情况加机器是解决不了的了。
机器多了的确快了,如果在服务里面有一个阻塞方法,那么就算服务在多也没用,所以必须注意关于服务超时的问题,由于服务是幂等的,就算再次执行也没有任何关系,有了超时就不会卡很久影响到后面的服务了(下游服务宕机了,线程死锁了,下游服务忙等等)。
关于同步,异步的一些设计模式,在有些必须顺序执行的业务场景就必须要使用同步了,在非必须的这种场景那么用异步一定比同步处理的并发量要大(由于中间件经历很多步骤,所以从单个请求的总时间来看并不一定有同步的快,但是从一个宏观的角度来看提高并发的请求会大很多了)。简单聊聊异步,在一个服务内部,异步那么就需要提到多线程了,多线程很多有点提高cpu利用率,提高系统性能,但是实现成本要高很多了,那么不同服务直接的如何异步呢,消息中间件了,(消息中间件很难,第一要保证真异步,第二需要保证不重不漏,就这2点真的很难,特别是在大数据情况下),特别是网络I/O需要重点考虑异步模型,不过Netty封装的挺好了。
由于每个机器,或者服务都是有上限的,如果量一下泄洪式的过来并且不是他的能力可以处理的,那么该如果解决呢?
该问题在生活中到处可见,刚刚好国庆回家、出去玩,随处可见该事项体现,比如过安检的时候,有一个保安专门拿一个牌看人差不多了,让后面的人等,等处理的查不多了,在让后面的人进行,之后类似在等。,但是如果有级别高的,或者车快发车了,一般让他们先过,在软件架构里面应该叫限流、服务降级,一般有两种控制策略(1,拒绝部分请求,2,关闭部分服务)可能之前的时候都提到了关闭部分服务,不过现在不推荐了(毕竟也是公司技术实力的体现),目前重点说的是关于拒绝部分请求,关于这块的控制在那里添加?就是那块需要控制,应该每层都需要加下该控制。
依稀记得行业里面有句话,高并发、高可用三大法宝:限流、降级、缓存,关于缓存,大家应该接触的最多,互联网业务特点就是读多写少,那么就非常适合使用缓存了。
由于所以请求在一个服务,扩展还是不好扩展,而且统一服务里面有些调用特别多,有些调用就比较少,因为继续划分,继续拆,这样还是可以再次提高并发。
微服务了,微服务概念很多,首先提到的就是搞垂直拆分,很容易理解,之后垂直业务可能也很多,还需要继续水平拆分,(这里一切的拆分依据都是根据自己公司的业务,理解越深才的越好)。
通过上面的这些,服务可以挂,机器可以坏,网络不通或者闪断的问题都解决了,并且可以提高并发,尽最大努力来让服务高可用。那么由于这么做带来了很多问题,所以需要把这些修改带来的问题解决:
- 以前在一个服务里面,对于事务的控制很容易,那么微服务之后,事务的控制就显的特别重要了,很多时候我们不能强一致性,但是我们可以做到最终一致性就是可以的。
- 调用链监控也就显得特别重要了,一起的还有预警也特别重要了。
- 分布式日志也显得特别重要了。
- 高级的jstack、Btrace在真实环境就是特别重要的。
结束语
本人水平有限,难免会有一些理解偏差的地方,如果发现,欢迎各位积极指出,感谢!!!