当前位置: 首页 > 网站架构 > 正文

构建高可用系统之故障篇的常用方法

1 星2 星3 星4 星5 星 (3 次投票, 评分: 5.00, 总分: 5)
Loading ... Loading ...
baidu_share

对于构建高可用的系统而言,都希望尽可能的避免故障,但通常来说故障是不可避免的,要尽可能做到的应该是在故障出现时能快速的屏蔽故障对核心功能的影响或快速修复,在这篇blog中,来分析下该如何更好的面对程序故障(这里就不讨论人工操作造成的状况),保障系统的高可用,由于这些更多的来自自己对厂内的经验的总结,必然会有一定的狭隘性,希望大家多多拍砖。

所有的系统必然都有其核心功能,我们把核心功能相关的操作称为关键路径,其他的功能称为非关键路径,对于系统而言,通常只有关键路径故障了,我们才认为其不可用,以下为造成关键路径不可用的一些场景和我们的应对方法:

1、非关键路径的故障
非关键路径的故障为什么会造成关键路径的故障呢,我们看看一些典型的场景:

Case I
A、B两个系统为非关键路径的系统,C为关键路径的系统,A、B、C都依赖了D系统,A系统出现故障,导致了对D系统的访问太多,由于D系统的总体处理能力是有限的,导致D系统处理不过来C系统的请求了,从而出现故障。

Solution
对于这样的状况,我们选择的方法是在部署期间通过路由将关键路径的系统和非关键路径的系统隔离开,例如A/B访问的是D集群中的一组机器,C访问的是D集群中的另外一组机器。
同时还提供了D关闭某访问者的功能的支持,这样可以在未做隔离的情况下,一旦出现故障,可以考虑先将资源都提供给关键路径的系统使用,从而临时避免故障。
可能有些同学会提到干脆把提供给A/B的不同接口拆分出了做单独的系统得了,这在很多时候是不太好做的,一方面会带来很高的维护成本,另一方面很多时候有互相依赖的问题。

Case II
还是上面的场景,不同的是B系统调用D系统时,D系统在处理B的请求时需要消耗较多的资源,这样当B系统对D系统的访问稍微多一点后就导致了D系统处理C系统的请求的资源必然也将下降,从而出现故障。

Solution
对于这样的状况,我们选择的方法同样是通过路由来进行隔离。

Case III
E系统上同时有关键路径的功能和非关键路径的功能,出现了非关键路径耗资源导致关键路径资源不够用,从而出现故障,例如一个web应用,用于处理请求的线程数必然是有限的,如果非关键路径处理慢了,导致线程消耗多了,这样关键路径能用来处理的线程数必然也就少了,因此就故障了,另外的例子还有连接池、CPU、Memory、IO等资源。

Solution
对于这样的状况,我们选择的方法是采用开关的方式来控制非关键路径,例如一旦非关键路径处理慢并影响到关键路径了,我们就关闭此非关键路径的功能,实现方式其实非常土,但非常有效,就是提供一个servlet,通过传入一些参数来打开或关闭某些功能,这招在很多时候都非常有效,也就是James Hamilton在他那篇著名的论文中说到的Graceful Degrade。

还有一种在大型系统里也很容易出现,就是你认为的非关键路径其实成为了关键路径,这种现象就很杯具了,对于这种现象,只能说必须管理好依赖,一旦没管理好,就将会出现看似一个不相关的系统出问题,核心功能也受影响了,另外一方面就是要简化系统,尽可能让关键路径不要出现太多的依赖,否则就意味着关键路径的稳定性取决于众多的依赖,那就痛苦了。

由于非关键路径不是系统的核心功能,因此我们应该尽可能做到非关键路径不影响到关键路径。

2、关键路径上的故障
关键路径上的故障同样也分成很多种,有些是只能通过修改代码来fix的,例如程序bug导致关键路径执行出错等,对于这类故障通常来说只能靠提高代码质量来保证,在此就不讨论了,而有些关键路径上的故障还是有办法来应对的,来看看一些典型的场景:

Case I
关键路径的系统部署在一台机器上,机器出现故障后(硬件、网络等)导致核心功能出现故障。

Solution
对于这种状况,要么采取冷备,要么就是集群了。

Case II
关键路径的系统部署在一个机房,当机房出现故障后导致核心功能出现故障。

Solution
对于这种状况,就需要做多机房的容灾了,当然,这会带来其他很多的技术挑战。

Case III
A/B两系统均为关键路径,A需要调用B系统,B系统处理变慢,导致A系统请求处理线程耗光,从而出现严重故障,类似的状况还有连接池,A系统依赖数据库,数据库的访问突然变慢,导致A系统很多请求在等待连接池,有些时候可能会因此导致启动的线程太多,最终内存消耗完毕,进程退出,这是最悲惨的状况,这是典型的慢现象造成的严重后果。

Solution
对于这种状况,我们选择的方法是一方面是超时时间设置的不会太长,另外一方面是在能不等待的情况就不等待,而直接拒绝,但像连接池这类的情况,通常也不太好直接采用拒绝的方式,因此我们选择的是控制等待的线程个数,避免影响太多线程,当然,这不一定能挽救故障,但对恢复而言会有很大的帮助。

Case IV
请求的流量超过了系统所能支撑的量,从而导致故障。

Solution
对于这种状况,我们选择的方法一方面是控制请求的数量,另一方面是容量规划,评估好系统能够支撑的极限量,但接近极限量时即进行扩容或启动保护措施。

集群场景中还会出现个别很高危的应用,例如A访问集群B时,必然要走中间的硬件负载设备或通过地址列表的方式去访问,这时如中间这个高危点出现故障,就得有一些简单有效的挽救方法。

本文固定链接: http://www.chepoo.com/part-of-the-failure-to-build-a-highly-available-system-common-method.html | IT技术精华网

构建高可用系统之故障篇的常用方法:等您坐沙发呢!

发表评论