[软件错误处理原则] 局部问题缩小,全局问题放大

    当一个错误出现以后,如果发现它是一个局部错误那应当采用缩小处理的原则;反之,如果是一个全局错误,那应当采用放大处理的原则。

    什么是局部和全局错误呢?局部错误就是错误的发生只影响系统的一部分,其它同类功能还能使用;反之,全局错误的出现将导致整个系统不能正常工作。这需要通过更为具体一点的例子来探讨,在此我们拿一个WiMAX系统的接入网关(ASN-GW)为例。一个接入网关可能支持20万个注册用户同时在线,显然,每一个用户会有不同的状态,读者可以想象到在接入网关中保存着每一个用户的信息数据(配置、运行状态等等),且各用户之间的信息数据是相互独立的。假设接入网关是一个单进程多线程的架构,且各线程都是采用状态机的设计方式进行业务逻辑处理。多个线程如果需要访问同一个用户的信息数据时,则需要考虑采用互斥的设计以保证用户信息在某一时刻最多只被一个线程访问。现在假设存在一个用户信息管理模块,其提供API给系统中的线程用于获取用户数据。当某线程收到一个外部消息需要更改一个用户的数据时,它需要先做一个checkout操作,在更新完了以后则需要做一个checkin操作。为了做到多线程对于各用户数据的互斥访问,一个用户的数据不可能同时被多个线程在同一时刻checkout成功。考虑到用户数量之大,程序在设计时在每一个用户数据中放置了一个标志域,用于表示这一用户的数据是否已经被某线程给checkout了,且对于这一标志域采用了加锁的方式进行互斥保护,因此这种设计可以认为是每一个用户数据都有一把“锁”,如果被checkout了的话,这一标志域就变成了true,反之则是false。如果一个线程想checkout一个用户数据,但却发现长时间(假设超过50毫秒)这一用户数据都被另外的线程给占用了(却标志域为true)。但是从设计需求来看不应当存在一个用户的消息在50毫秒钟内无法处理完(假设处理器负荷并不重),如此一来这显然就是一个错误,那这个错误是局部的、还是全局的呢?先分析一下,这种情况的发生一定是程序的设计出了错误,比如,在处理某一用户的消息时,由于进入了异常状态且这一异常状态的处理代码因为程序员的疏忽而忘记了对已checkout出来的用户数据进行checkin操作,因此造成这一用户的数据被虚假地checkout了,这类似于内存泄漏。如果checkout操作被设计为永久等待,即只有等到获取数据存取权才返回,则一个用户数据的无法正常checkout会造成所有用户消息都不能被处理,因为进行checkout操作的线程将被永久地挂起,这时是一个全局错误。反之,如果checkout操作被设计成具有超时功能,则一个用户的数据不能成功checkout(即出现超时)是可以做到不影响其它用户的,因为进行checkout操作的线程并不会被永久挂起,而且各用户数据是相互独立的。在这种情形下就成为了一个局部错误。再举一个例子,如果存在一些全局数据需要被接入网关中处理用户消息的多个线程同时使用,且这些数据采用了锁对其进行互斥存取保护,如果存在一个线程想去存取这一全局数据,但却因为保护锁没有最终被其它线程释放进而造成被永久挂起,这又是什么类型的错误?由于每个用户消息的处理都需要这几个共享全局数据的线程协同工作,也就是说,其中一个线程的永久挂起将导致所有的后续用户消息都不能被处理,因此,这是一个全局错误。

    什么又是对错误的缩小和放大处理呢?缩小处理是指对于错误所采取的处理方法,不会立即影响其它用户(或模块什么的,这与具体的应用有关,在这里的例子应当指WiMAX用户)。而放大就是指一种处理方式会立即影响其它的用户。对于前面提到的用户数据checkout的错误例子,设计方法可以使其成为全局错误或局部错误,在这种情形下,我们应当选择将其变成局部错误,即为用户数据信息的checkout操作设计超时功能以缩小错误范围,且当出现超时时,也只需记录一个错误日志。反之不能采用放大处理的方式,比如,不能采用永久等待的方式去checkout用户数据,更不能让整个系统因为某一用户数据不能checkout而重新启动。至于全局数据不能存取的例子,是不是也采用给全局共享数据锁加上超时功能这种方式呢?如果这样,那出现超时以后又该如何处理?如果超时后还对全局数据进行强行访问,就可能因为数据的不完整而造成其它莫名其妙的问题(这类问题更加可怕!)。对于这类全局错误通常无法通过设计绕过去,只能通过系统重启系统进行恢复,而这就是放大处理。当然这里的一个假设是,系统中存在检测线程健康的机制以发现某个线程无响应(或者通俗的说“死了”)从而进行重启系统流程。

    大部分错误,不论是局部还是全局,其根本原因都是软件缺陷所造成的。但对于这两类问题的处理应当运用不同的策略,因为不同的处理策略所造成的结果将完全不同。对于这里的WiMAX接入网关例子,由于这么大的系统通常都有热备份功能,即当一块处理器板卡出现错误重启时,另一个板卡会立即投入工作,且不会影响已在线和将要在线的用户,因此对于错误的缩小或放大处理从用户层面并不会造成很大的区别。但是,对于没有热备份的系统,采用不同的处理方式其结果却大相径庭。最后,作为一个错误处理原则,分清它是局部错误还是全局错误是至关重要的第一步。

你可能感兴趣的:(原则,出错,错误,处理,休闲)