当前位置: 首页 > 后端技术 > Python

Python的一个list参数是如何拉垮网站的

时间:2023-03-26 01:36:56 Python

废话不多说,我们来看代码defadd_end(L=[]):L.append('END')returnL这段python代码有什么问题??好像没什么问题。L为列表形式的输入参数。如果没有通过,则有一个空列表作为默认值。将L的内容添加到业务体中,返回添加的L对象。业务很简单,就是这样一段看似无害的代码,让一个网站苦了一个月,同时流失了很多用户。让我们来看看经历过Digg的v4发布的人们的回忆:一种因需而生的乐观主义。不想看英文的同学可以翻译全文或阅读下面摘录的主要内容:背景:Digg是一个科技新闻网站。用户可以向digg提交新闻,新闻会通过首页的digg机制显示在digg上。十多年前的web2.0浪潮,巅峰时期月访问量3000W以上,2012年有所下滑,至今仍在运行。这件事发生在2018年,让这个糟糕的网站雪上加霜。2018年,Digg推出V4。从V3.5到V4,经过两年的不断发展。整个公司都希望通过V4让Digg重新回到互联网的第一梯队。他们甚至提前准备了庆祝香槟(中场香槟,传统表演)他们准备了升级计划,但没有回滚计划(这是一个标志,记住墨菲定律)升级后,网站没有按计划显示,但大多数由于后台负载高,页面无法加载。进行到一半,Digg团队观察到数据库(Cassandra)和缓存(memcache)负载偏高,扩容了一次,但问题还是没有完全解决。尤其是V4中最重要的MyNews页面,是这个版本最吸引眼球的功能,也是用户默认的页面,但是这个页面一直报错。Digg团队后来将初始页面改为TopNews,以确保用户不会至于我登录时看到的错误页面,但问题仍然没有解决。两天后,Digg团队将数据从Cassandra迁移到Redis,提高了数据库的访问性能。问题已经缓解,但仍然需要每4小时重启一次服务。一个月后,问题终于找到了。Digg的API服务是一个Python服务,类似于网关层。作为网关,需要查询用户信息。这个用户信息查询函数的参数形式就是上面的列表形式(当然具体代码长啥样我们也不知道,只知道形式),就是这个代码形式造成了这个月的问题OK,让我们执行一次上面的函数>>>add_end()['END']看起来没问题,然后执行另一个>>>add_end([1,2,3])[1,2,3,'END']带参数没问题,我们再执行一次>>>add_end()['END','END']>>>add_end()['END','END','END']不带参数?为什么?默认参数是[],但函数似乎“记住”了上次添加'END'后的列表。原因解释如下:Python函数定义时,会计算默认参数L的值,即[],因为默认参数L也是一个变量,指向对象[],每次函数被调用时,如果改变了L的内容,下次调用该函数时默认参数的内容会改变,而函数定义时不再是[],所以当大量用户访问Digg时,L中的defaultlist会越来越大,而且随着并发访问,这是多项式级增长两度以上,很快就会把内存填满,导致服务不可用代码和解释参考,这也说说怎么解决:廖雪峰:函数参数的问题确实很隐蔽,有时候是违反直觉的(可能对于不熟悉的人来说)。这时候,使用一些工具进行静态代码检查就显得尤为必要了。这些工具总结了许多其他人踩过的陷阱。即使他不能确定这一定是BUG,他也会给开发者一些危险编码方式的提示。