事故发生10天之后,微软于3/9/2012对Windows Azure Service Down掉给出了总结,具体见这里:http://blogs.msdn.com/b/windowsazure/archive/2012/03/10/summary-of-windows-azure-service-disruption-on-feb-29th-2012.aspx
从中可以看到事件的大概过程:
1. Application VM guest agent因为闰年bug无法产生certificate
2. Host OS agent发现VM guest agent无法重启成功,会重试3次去启动VM
3. 3次重试之后,Host OS 发现VM还是无法启动成功
4. Host OS agent没有收到VM guest agent发出的任何有意义的错误报告,于是其认为机器hardware出问题了
5. Host OS 上报Fabric Controller,认为该台机器已经无法使用,需要人工检修
6. Fabric Controller将VM的创建转交给其他机器,上述的流程在每个机器上重现,于是很快所有的机器都被认为是hardware出问题
7. 当所有机器都被Fabric Controller认为有问题之后,整个集群甚至数据中心都无法提供服务了
从上述事件发生的chain来看,至少有两点是设计时候应该考虑的:
1. 一个机器是否应该被移除的条件:上面Host OS仅仅重试三次无法初始化VM,就认为机器hareware有问题,这是有些粗暴的,没有考虑到VM本身的bug或者Application对VM的攻击。
2. 机器在短时间内大批量被认为hardware有问题进而导致下线,Fabric Controller没有迅速报警:上面的summary里面提到了当可用机器减少70%的时候,Fabric Controller会报警,这个值显然太高了,而且没有将时间的因素考虑进去,如果按照单位时间内机器下线率计算,我认为5%的机器出问题就足以报警了。
上述事件看起来就像一个状态机一样,在设定的状态下转到下一个状态,并作出相应的动作,我想如果在设计的时候清晰的描绘出这样的状态机,那么开发人员能否意识到“在一个状态机中,某些状态是比另外的状态更加重要的,某些路径的代价是比另外的路径的代价更大的?”,这样的话,也许上面的bug在开发review的阶段能够被发现。
推此即彼,编程也是一样的,一个程序从main开始执行就在做状态转换,那么我们是否能将其中比较high level的状态转换清晰的画出来并且仔细甄别哪些状态更重要?哪些路径要更加小心?也许这样,是降低大bug的一个很好的办法。