# BuddyPoke 如何使用 Google App Engine 在 Facebook 上扩展

> 原文： [http://highscalability.com/blog/2010/1/22/how-buddypoke-scales-on-facebook-using-google-app-engine.html](http://highscalability.com/blog/2010/1/22/how-buddypoke-scales-on-facebook-using-google-app-engine.html)

![](img/451edc7f930a797797870dc54ca1af27.png)您如何扩展一个病毒式 Facebook 应用，该应用激增至令人难以置信的 6500 万次安装（法国人口）？ 那是 [BuddyPoke](http://www.buddypoke.com/) 的共同创始人 Dave Westwood 遇到的问题，他在周三的 [Facebook Meetup](http://www.meetup.com/facebookmeetup/calendar/12179578/) 上谈到了他的解决方案。 完整演讲的幻灯片在此处。 对于那些不太确定 BuddyPoke 是什么的人，它是一个社交网络应用程序，它使用户可以通过在线头像来显示自己的心情，拥抱，亲吻和戳朋友。

在许多方面，BuddyPoke 是典型的现代 Web 应用程序。 它繁荣发展了社交网络驱动的生态系统。 游戏的机制，病毒循环和创造性的获利策略都是其日常概念化的一部分。 它将不同的技术融合在一起，而不是以黑暗的科学怪人方式，而是以一种聪明的方式获得最大的收益。 它的一部分在 Facebook 服务器上运行（免费）。 它的一部分在浏览器中的 Flash 上​​运行（免费）。 它的一部分在存储云上运行（成本更高）。 并且部分运行在平台即服务环境（GAE）上（低成本）。 它还与 PayPal 等其他服务紧密集成。 通过出售可在戳中兑换的虚拟商品，例如[金币](http://www.humanexperience.nl/wp-content/uploads/2009/06/buddypoke.png)，可以赚取真实的$$$。 用户还可以将他们的化身制作成玩偶，T 恤和其他由 Zazzle 提供动力的礼物。

这确实是一个了不起的企业，在现代环境下只能说出最愚蠢的感觉。 我只能想象革命时代的农民会怎样做。 BuddyPoke 甚至可以成为十年前存在的东西吗？ 我要问的原因是要处理所有这些用户，BuddyPoke 需要以非常低的成本实现巨大的扩展规模。 如果您必须在数据中心中构建自己的 colo 站点，那么 BuddyPoke 是否可以经济地运作？ 他会得到资金进行扩建吗？

BuddyPoke 通过非常巧妙的策略和服务组合来工作。 通过戴夫的讲话可以明显看出，这些都是非常有意识的策略。 Dave 谈论了很多有关在功能上转移到不同位置以最小化成本，选择技术以最小化成本，同时又保持足够高的性能以使用户可以继续戳的技术。

## 一般经验教训

在获得 GAE 的具体建议之前，戴夫做了一些有趣的一般观察：

1.  BuddyPoke 的 GAE 成本很低。 我试图找出实际成本是多少，因为有些人报告的成本高于预期，而我想知道他的经验表明了什么。 没有人会回答这些类型的问题，戴夫也不例外。 他确实说过，他为每个客户支付的费用不到一美分，但是我不确定这些单位。 每年一分钱？ 每次手术？ 没有意见 ：-）
2.  GAE 的持久性即服务模型的吸引力在于它的简单性。 Dave 说他是 3D 图形人员，而不是基础架构人员，因此他不想弄乱系统的那部分。 这是 GAE 的最佳选择。
3.  BuddyPoke 的大部分成本用于内容交付。 BuddyPoke 的主要应用是必须提供 Flash 文件。 这些成本远远高于运行实际应用程序的成本。 Dave 正在研究 Rackspace 的文件服务。 GAE 对于访问内容具有较高的故障率，这在返回化身时是可以接受的，但对于加载初始图像而言并不是很好。
4.  您不能天真地为 GAE 编码。 为了获得性能，您必须选择最适合 GAE 工作方式的策略。

## Google App Engine 课程

以下是 BuddyPoke 用于在 Facebook 和 Google App Engine 上扩展的一些策略：

1.  使用浏览器的 CPU。 这些 CPU 周期是免费的，而您可以在 GAE 中付费。 对于 BuddyPoke，这意味着：1）在 Flash 客户端中执行计算 2）等待客户端中的 Facebook 操作，而不是 GAE。
2.  设置最大值。 而不是允许用户上传大量图标，例如，最多设置六个左右，否则数据存储和您的成本将爆炸。
3.  [Memcache](http://code.google.com/appengine/articles/scaling/memcache.html) 一切都是为了解决数据存储问题。
4.  将[分片计数器](http://code.google.com/appengine/articles/sharding_counters.html)用于安装计数之类的统计信息。 否则，争用问题将使一切陷入困境，并激增您的配额。
5.  发送大量[电子邮件](http://code.google.com/appengine/docs/java/mail/)会占用大量 CPU。 使用任务队列或 cron 作业对它们进行批处理。
6.  将多个 [appspot](http://code.google.com/appengine/docs/whatisgoogleappengine.html) 应用程序用于不同功能，而不是一个大型应用程序。 例如，错误将发送到特定的错误应用程序。 这样可以使日志和其他统计信息按功能分开。
7.  将表分为两部分：主模型和附加信息模型。 数据存储看跌期权是您最大的成本，因此您需要尽一切可能使成本最小化。 在主模型中，仅使用键控访问，不使用索引，并且不保留其他字段。 获得将很快而认沽将变得便宜。 编写额外的字段会浪费时间和金钱。 因此，用户模型的“加入日期”字段不属于主表。 它不经常使用，因此将这种数据放入附加的信息模型中。 将您的索引放在该模型上并对其执行查询。 因为附加信息模型具有索引，所以它将导致更多的同步写入，这将花费更多，更慢，并且如果您需要频繁编写此模型，则可以备份处理。
8.  为了最大程度地减少数据存储跳，请使用批处理获取和放置。

从表面上看，BuddyPoke 看起来很简单，但是在引擎盖下却存在着一些复杂的策略。 在使其规模和性能最大化的同时将成本最小化并不明显。 谁在做什么，何时，为什么以及如何做让人费解。 当然，这是越来越多的应用程序将来会发现自己使用的一种方法。

## 相关文章

1.  [谈话的 Ustream 视频](http://www.ustream.tv/recorded/4118948)
2.  [在 App Engine](http://code.google.com/events/io/2009/sessions/BuildingScalableComplexApps.html) 上构建可扩展的复杂应用程序，作者 Brett Slatkin
3.  [Google App Engine-再看](http://highscalability.com/blog/2009/2/21/google-appengine-a-second-look.html)
4.  [Google App Engine](http://www.youtube.com/watch?v=0zz-oSrWfj0) 上的 BuddyPoke

我要补充一点，使用 Guido 的新 AppStats 库可以使您获得有关数据存储性能的真实数字，等等。没有这种自省，这实际上只是一个猜测游戏。 内省还可以让您找到那些地方-哎呀！ -您不小心从 for 循环或其他一些容易解决的问题中调用数据库。

TOS 允许第 6 点吗？ 好像没有

http://code.google.com/appengine/terms.html

4.4。 您不得开发多个应用程序来模拟或充当单个应用程序，或以避免产生费用的方式访问服务。

我也想知道西尔万，但是我猜是因为他们是分开的服务，所以还可以。 Google 家伙就在那儿，因此一定不能违规。

我会问这点给 Google（freenode chat）
对我来说，TOS 很清楚：不同的服务，但最后只有一个应用程序：禁止使用。

否则，创建多个应用程序太容易了，或者我们可以将它们称为“服务” :)
-图像的“一项服务”
-CSS，js，...的“一项服务”
-503、404，...的“一项服务”
-发送邮件的“一项服务”
-计算...的“一项服务” ...
-等，...

并最终低于配额。

我认为 BuddyPoke 可以，因为它是主要的应用程序，显示“成功”很重要。

不错的提示，我将其中一些应用到我的应用中。 很快，我还将发布一些有关应用程序可扩展性的新技巧。 但是，GAE 错误级别如此之高...

>我试图找出实际成本是多少，因为有些人报告的成本高于预期，并且我想知道他的经验如何。 没有人会回答这些类型的问题，戴夫也不例外。

我从来不明白这一点。 我将自由地告诉任何询问每月运行 reddit 的费用的人。

杰里米，每个月运行 Reddit 多少钱？

我也对运行 Reddit 花费多少感兴趣。 请告诉我，杰里米。

哦...看来杰里米从未回答...