建议
读过本章的案例之后,你肯定会觉得在达到Google的规模之前不需要进行任何自动化。这是不正确的,有以下两个原因:自动化提供的不仅仅是对时间的节省,所以在单纯的时间花费和时间节省的计算之外也值得实施。但是,最有效的方法其实在设计阶段:更快地交付和更快地迭代可能会帮助你更快地实现功能,但是却很难形成一个有弹性的系统。对足够大的系统来说,进行改造时加入自主行为是很难的,但软件工程的良好标准的做法将会有很大的帮助:解耦子系统,引入API,最大限度地减少副作用等。
自动化:允许大规模故障发生
Google运行十几个自有的大型数据中心,但是我们也依赖很多运行在第三方托管设施(或“colo”)内的机器。这些colo中的机器是用来终止大部分传入的连接的,或是作为自己的内容分发网络的缓存,以降低用户的等待时间。在任何一个时间点,都有很多机架被安装或被退役;这两个过程大部分都是自动化的。拆除中的一个步骤包括覆写机架上所有机器的磁盘的全部内容,同时一个独立的系统随后会验证机器被成功擦除。我们称这个过程为“磁盘擦除”(diskerase)。
很久以前,负责某个特定机架退役的自动化系统出现了问题,但只有磁盘擦除步骤已经成功完成。随后,清退过程被重启,以调试为什么失败。在这次操作中,当该程序试图给磁盘清除系统发送机架中的机器列表时,代码得出需要进行清空的机器列表是(正确的)空的。不幸的是,空列表有着特殊含义,它被解释为“所有”。这意味着自动化系统几乎将colo中的所有机器都送去进行磁盘清除了。
几分钟内,高效的磁盘清除程序擦除了我们的CDN上所有机器的磁盘,这些机器再也不能终止用户连接了(或做任何有用的事情)。我们仍然可以从我们自己的数据中心来服务全体用户,事实上几分钟后对外部的唯一影响就是会有轻微的延迟增加。据我们所知,由于良好的容量规划,很少有用户注意到这个问题(至少我们这一点做得不错!)。接下来,我们花费了大概两天时间重装受影响的colo机架上的机器;然后我们又将接下来的几周时间用来进行代码审计,在我们的自动化系统中添加更多的合理性检查,包括速率限制,以及使整个退役流程具有幂等性。