- 内容提要
- 前言
- 作者简介
- 封面简介
- 第1章 理解高性能 Python
- 第2章 通过性能分析找到瓶颈
- 2.1 高效地分析性能
- 2.2 Julia 集合的介绍
- 2.3 计算完整的 Julia 集合
- 2.4 计时的简单方法——打印和修饰
- 2.5 用 UNIX 的 time 命令进行简单的计时
- 2.6 使用 cProfile 模块
- 2.7 用 runsnakerun 对 cProfile 的输出进行可视化
- 2.8 用 line_profiler 进行逐行分析
- 2.9 用 memory_profiler 诊断内存的用量
- 2.10 用 heapy 调查堆上的对象
- 2.11 用 dowser 实时画出变量的实例
- 2.12 用 dis 模块检查 CPython 字节码
- 2.13 在优化期间进行单元测试保持代码的正确性
- 2.14 确保性能分析成功的策略
- 2.15 小结
- 第3章 列表和元组
- 第4章 字典和集合
- 第5章 迭代器和生成器
- 第6章 矩阵和矢量计算
- 第7章 编译成 C
- 第8章 并发
- 第9章 multiprocessing 模块
- 第10章 集群和工作队列
- 第11章 使用更少的 RAM
- 第12章 现场教训
12.6 在 Lanyrd.com 中的任务队列
Andrew Godwin (lanyrd.com)
Lanyrd是一家发现社交协会的网站——我们的客户登入后,我们使用来自社交网络的他们的好友图,以及其他类似于他们的工作行业或者地理位置之类的线索来建议相关的协会。
网站的主要工作就是提取出原始数据的精华,这样我们就能展现给用户——尤其是一个排序好的协会列表。我们必须要离线来做,因为我们每隔几天刷新推荐的协会列表,也因为我们遇到了通常较慢的外部API。我们也为其他花费较长时间的事情使用Celery任务队列,比如获取人们所提供的链接的缩略图以及发送电子邮件。每天在队列中通常有超过100 000个任务,有时会更多。
12.6.1 Python在Lanyrd中的角色
Lanyrd从一开始起就由Python和Django来构建,几乎它的每一部分都是用Python来写的——网站本身,离线处理,我们的统计和分析工具,我们的移动后端服务器以及部署系统。它是一种多用途和成熟的语言,相当容易快速用它来写代码,最感谢的就是大量可用的库以及语言良好的可读性和简洁的语法,这意味着容易更新和重构,并且一开始也容易编写。
当我们对任务队列的需求发生演进(很早就开始)时,Celery任务队列已经是一个成熟的项目了,Lanyrd的其余部分已经使用了Python,所以它自然就适应了。当我们规模变大时,有一个需求要改变支撑它的队列(最后用了Redis),但它一般有很好的扩展性。
作为一个初创公司,为了取得进展,我们不得不欠下一些已知的技术债——这只是你不得已做的,当问题可能浮现时,只要你知道它们是什么问题,就不一定是坏事。Python在这方面的灵活性非常棒,它一般鼓励组件之间的松耦合,这意味着发布一些“足够好”的实现常常是容易的,然后将来轻易地重构出一个更好的实现。
任何关键性的东西,例如付款代码,要有完整的单元测试覆盖率,但是对于网站的其他部分和任务队列流(尤其和显示相关的代码),往往前进得太快,让单元测试变得没有价值(它们太脆弱)。取而代之的是,我们采用了一个非常敏捷的方法,具有一个短达2分钟的部署时间以及优秀的错误追踪。如果出现错误,我们常常能够修复它,并在5分钟内完成部署。
12.6.2 使任务队列变高性能
任务队列的主要问题是吞吐量。如果它有任务积压,那么网站继续工作但是开始变得有些不可思议的延时——列表没有更新,页面内容是错的,电子邮件几小时都没发送出去。
然而,幸运的是,任务队列也鼓励非常具有扩展性的设计,只要你的消息中心服务器(在我们的案例中是Redis)能够处理任务请求和响应的消息开销,对于实际的处理而言,你可以运转任意数量的守护工作进程来应对负载。
12.6.3 报告、监控、调试和部署
我们有跟踪队列长度的监控,如果它开始变长,我们只要部署另一台有更多守护工作进程的服务器即可。Celery让这样做变得很容易。我们的部署系统有钩子,通过它,我们能够在盒子上增加工作线程的数量(如果我们的CPU利用率不是最优的),并且能够在30分钟内轻易地把一台全新的服务器转变成一个Celery工作者。它和降到最低水平的网站响应时间不一样——如果你的任务队列突然得到一个负载高峰,你有一些时间来实现一个修复,如果你留下了足够的冗余容量,通常它能平滑下来。
12.6.4 对开发者同行的建议
我的主要建议将会是尽可能快速地把尽量多的任务塞到任务队列中去(或者一个类似的松耦合的架构)。它在初始阶段要花费一些工程方面的努力,但是当你规模扩大时,曾经要花半秒时间做的操作可能增大到半分钟才能完成,你会高兴于它们没有阻塞你的主渲染线程。一旦你走到了这一步,要确保你紧密监控你的平均队列延迟(一个任务从提交到完成需要花多久),并且确保当你的负载增加时,还有一些冗余的容量。
最后,要注意为多个不同优先级的任务配置多个任务队列是有意义的。发送电子邮件不具有很高的优先级,人们习惯于电子邮件过几分钟才到达。无论如何,如果你在后台渲染缩略图并且当你正在做时,显示一个旋转图标,你想要让这种工作成为高优先级,因为如果不是这样的话,你会产生糟糕的用户体验。你不想在接下来的20分钟内在你的网站上让100000人的邮件广告全都延迟显示缩略图。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论