# 在破坏之前先检查自己-鳄梨的建筑演进的 5 个早期阶段

> 原文： [http://highscalability.com/blog/2013/4/10/check-yourself-before-you-wreck-yourself-avocados-5-early-st.html](http://highscalability.com/blog/2013/4/10/check-yourself-before-you-wreck-yourself-avocados-5-early-st.html)

![](img/d02a7ba0dcd059b036ce353085ef0a44.png)在[中不要惊慌！ 这是如何快速扩展您的移动应用](http://venturebeat.com/2013/04/06/dont-panic-heres-how-to-quickly-scale-your-mobile-apps/)的方法。 [Mike Maelzer](http://www.linkedin.com/in/maelzer) 描绘了 [Avocado](https://avocado.io/) （一种用于连接情侣的移动应用程序）是如何发展的，可在几周内处理 30 倍的流量。 如果您只是入门，那么这是一个值得学习的好例子。

我喜欢的东西：写得很好，在一个很小的空间中包装了很多有用的信息； 它是由故障驱动的，显示了有目的的测试和生产经验所驱动的增量变化的过程； 它显示出对于重要的用户（对于他们而言）注册的意识； 使用副本设置进行测试，这是一个不错的云优势。

他们从中学到的最大的教训是一个很好的教训：

> 最好早得多开始扩展过程。 由于时间紧迫，我们不得不做出让步-例如放下四个媒体缩放器盒。 虽然在某些扩展问题上投入更多的硬件确实可以，但是这并不理想。

这是我对这篇文章的介绍：

## 进化一-使之工作

刚开始时，您只想完成工作，无论完成多少。 您如何确定需要解决的问题？ Avacodo 所做的是有目的地测试他们的软件，寻找弱点，修复它们，然后进行迭代。 一个非常明智的增量过程。 您可能会想，为什么不跳到最终结果，但是那永远不会真正解决。 敏捷/精益思维的所有观点都有很多真理。 每个大型系统都是从较小的系统演变而来的。

*   第一个问题：您真的需要扩展吗？ 为什么要经历所有这些努力？ Avocado 正在促销中，他们希望带来更多的流量，而他们负担不起那些潜在的新用户带来的不良体验。 因此，必须应对大量的流量高峰。
*   他们从典型的拥有每种功能设置的服务器开始：1 前端服务器（存储：API，Web 状态，socket.io，HAProxy，隧道/ SSL 加密）； 1 个 Redis 服务器; 1 个 MySQL 服务器； 1 个批处理服务器（正在运行其他守护程序）。
*   复制测试设置用于运行常见的方案，例如帐户创建。
*   在测试环境中使用较小的 EC2 实例可以节省资金，并且可以消除与资源相关的错误。
*   使用 [jmeter](http://jmeter.apache.org/) 构建的测试脚本每分钟模拟成千上万的用户注册。
*   测试旨在使用不同的场景来发现薄弱环节，例如添加第二台服务器并使用服务器上的所有 CPU。
*   通过数千个同时注册来提高性能：
    *   由于创建新的 Python 进程来发送电子邮件验证和调整个人资料图片的大小而导致的 CPU 高峰。
    *   所有这些都发生在一个盒子上。
    *   一些 MySQL 查询需要很长时间。
    *   SSL 是主要的 CPU 负载

## 进化二-测试驱动的变更

根据测试结果，他们：

*   添加了一些数据库索引以加快访问速度。 创建表时，您是否不应该知道要添加哪些索引？ 这不是很明显吗？ 有时是，有时不是。 让您的数据库告诉您哪些缓慢的方法也适用，尤其是在游戏初期。
*   重新编写电子邮件验证以使用 node.js 的异步功能，而不是每次都派生一个单独的 Python 进程。 吞吐量提高了 3 到 5 倍。 他们为什么首先使用 Python 方法？ 看来显然是浪费。 也许他们已经有了代码？ 也许他们知道如何用 Python 做到这一点？ 在较大的计算机上可能没有关系。 但这是明智的渐进式变化。 采取可行的措施，并在无法解决时进行修复。 尽管他们在这里仍然有巨大的失败漏洞。 如果进程终止，则用户注册状态机将停止。
*   SSL 已移至其自己的服务器。 同样，这很明显是一个问题，而更大的机器可能会成为一个问题，但是从一台机器上启动肯定更容易。
*   对于促销，分配了四个新实例来调整图像大小。 晋升后将其删除。 处理预期流量高峰的好策略。

## 进化三-生产驱动型变化

随着我们对生产经验的深入了解，我们可以看到问题的类型正在变为那些很难预测并且似乎只有修复的奇怪问题。

*   在促销监视期间，警报提示响应时间较慢，因此添加了第二台前端服务器。 因此要进行监控。 最终添加了 15 台服务器。
*   注意到在较大的 EC2 实例上，仅使用一个 CPU，node.js 是单处理器解决方案，并且 HAProxy 每个框仅路由到一个实例。 重新启动 HAProxy 以读取新配置以解决此问题花费了几秒钟，因此他们创建了冗余 HAProxy 服务器以减少停机时间。
*   ELB 用于将流量路由到两个 HAProxy 服务器并处理 SSL，从而减少了代理箱的数量并节省了资金。
*   这导致 socket.io 出现多服务器问题，因为用户需要与一台服务器维护一个会话。 因此，他们参加了粘性会议，需要做一些棘手的更改。
*   有趣的发现：Websockets 不能在所有的蜂窝网络上工作。 由于这是至关重要的移动应用程序。 另外，ELB 不支持 websocket。 因此他们使用了 XHR 轮询。 命运的惊人转折。
*   将 Socket.io 移动到具有 8 个 socket.io 服务器（每个 CPU 一个）的自己的盒子中，总共有 16 个 socket.io 服务器实例。
*   似乎很多套接字服务器。 为了减少数量，使用了数据库连接池。 最初，每个 socket.io 服务器都有一个数据库连接，该数据库连接将工作排队到数据库中，从而使 socket.io 使用了 8 个 CPU 中的 60％。 每个服务器实例使用 2 至 10 个数据库连接池将 CPU 使用率降至 3％，并显着缩短了响应时间。
*   为什么不从一开始就使用连接池？ 这是很标准的。 他们没有，我感到很惊讶，但是会出现各种各样的问题，重点不是他们是哪个问题，而是您找到并解决这些问题。

## 进化四-走向全球

*   移动对夫妇遍布世界各地，因此他们也通过在全球范围内启动服务器进行调整，以指导亚马逊按时进行路由。 注意这有多疯狂。 一次国际发行本来是一笔大买卖。 现在，这只是您要做的另一件事。
*   他们应该早些时候走向全球吗？ 毕竟，移动性能是应用的关键。 但这太疯狂了，您必须具有系统使用经验，然后才能前往多个位置。

## 进化五-现在使它更好地工作

*   在处理了最初的促销任务，了解了其系统的工作原理并解决了问题之后，现在该考虑自动化和自动部署策略了。 慢慢来，这样您就可以一次担心一种问题。 从一开始就进行自动化将使事情变得非常复杂，因为您甚至在不知道应该如何工作的情况下尝试进行自动化。 更好的渐进式思维。

我读了“ CPU”，但我怀疑很多时候它应该是 CPU“线程”。 在体系结构规模上迭代的一个很好的例子，并且不会感到被堆栈的任何特定部分所束缚。