Cloudflare承认了一个编程错误,该错误涉及React useEffect钩子的使用不当,导致其平台仪表板和多个API出现超过一小时的服务中断。
这次故障发生在9月12日,持续了一个多小时。据工程副总裁Tom Lianza介绍,故障由仪表板中的一个错误触发,该错误导致"对租户服务API的重复、不必要调用"。这个API是API请求授权逻辑的一部分,因此影响了其他API的正常运行。
问题的排查过程相当困难,因为表面上看起来是API可用性问题,掩盖了实际上是仪表板过载API的事实。
Lianza表示,核心问题出在React useEffect钩子中,其"依赖数组中包含一个有问题的对象"。useEffect钩子是一个包含多个参数的函数,包括返回清理函数的设置函数和可选的依赖项列表。每当依赖项发生变化时,设置函数就会运行。
在Cloudflare的这个案例中,该函数会调用租户服务API,而其中一个依赖项是一个"在每次状态或属性变化时都会重新创建"的对象。结果是,在仪表板的单次渲染过程中,该钩子反复运行,而原本设计只运行一次。函数运行频率过高,导致API过载,引发服务中断。
useEffect钩子功能强大但经常被过度使用。相关文档充满了关于误用和常见错误的警告,并鼓励在可能的情况下使用其他方法。useEffect的性能陷阱很常见。
这一事件在社区中引发了关于useEffect利弊的讨论。一位开发者在Reddit上表示,对useEffect的抱怨太多了,它是React的重要组成部分,"认为使用它是坏事的想法很愚蠢"。不过,另一种反应是"消息还没有被接收到。我认识的几乎每个人都继续无缘无故地到处放置大量useEffect"。
还有人评论道:"真正的问题是API因过量API调用而宕机...在一家拥有专门服务来防止DDoS(分布式拒绝服务)攻击的公司中。"
Lianza表示,租户服务没有分配足够的容量来"处理这样的负载峰值",现在已经为其分配了更多资源,并改进了监控。此外,从仪表板发出的API调用中添加了新信息,以区分重试和新请求,因为如果团队知道看到的是"大量新请求,就更容易将问题识别为仪表板中的循环"。
Q&A
Q1:什么是React useEffect钩子?为什么会导致问题?
A:React useEffect钩子是一个包含设置函数和依赖项列表的函数,每当依赖项变化时就会运行。在Cloudflare的案例中,依赖数组中的对象在每次状态变化时都被重新创建,导致钩子在单次渲染中反复运行,原本只应运行一次。
Q2:Cloudflare的这次故障具体是怎么发生的?
A:故障是由仪表板中的useEffect钩子错误引起的,该钩子对租户服务API进行了重复、不必要的调用。由于API调用频率过高,导致API过载,进而影响了其他依赖该API的服务,造成超过一小时的服务中断。
Q3:Cloudflare采取了哪些措施来防止类似问题再次发生?
A:Cloudflare为租户服务分配了更多资源以处理负载峰值,改进了监控系统,并在仪表板的API调用中添加了新信息来区分重试和新请求,这样可以更容易识别仪表板中的循环问题。