问题 使用Heroku构建可扩展分析后端的最佳方法是什么?


我需要构建一个简单的分析后端来捕获用户行为。这将通过网页上的Javascript代码段捕获,就像Google Analytics或Mixpanel数据一样。

系统需要捕获接近实时的浏览器数据(页面的滚动位置,鼠标位置等)。它将每5秒记录一次用户页面的状态。每次测量只有三个属性,但必须经常使用。

数据不一定需要每5秒发送一次,它可能不那么频繁地加速,但是当用户在页面上时我必须获得所有数据。即我不能每分钟一次公共汽车,并且在119秒后离开的人丢失了最后59秒的数据。

如果可能的话,我想构建一个在可预见的未来可扩展的系统,这意味着它可以为10,000个站点工作,每个站点有100个并发访问者,即100,000个并发用户,每个用户每5秒发送一个事件。

我并不担心查询数据,可以使用单独的系统来完成。我最感兴趣的是如何处理数据本身的捕获。

要求

根据上述预算,系统需要处理来自100,000个用户的每秒20,000个事件。

我想在Heroku上托管这项服务,但是当我使用Rails做了很多工作时,我对高吞吐量系统完全不熟悉(除了知道你不使用Rails处理它们)。

问题

  1. 是否有商业系统可以做到这一点(如Pusher,但数据捕获和分发)?
  2. 我应该使用HTTP请求还是websockets来做这件事?
  3. node.js是正确的选择还是时尚?
  4. 如果我选择基于套接字的解决方案,Heroku上的dyno可以为每个网络服务器处理多少个套接字
  5. 在Mongo / Reddis等之间进行选择以进行存储有哪些相关的考虑因素
  6. 这是一种实际需要两种解决方案的问题 - 第一种是让您快速,低成本地达到合理的规模,第二种是在降低增量成本的情况下超越这种规模,但需要提前进行更多的开发工作?

5755
2018-06-22 17:48


起源

建议两种解决方案是烹饪不足。查看Rackspace的CTO题为“扩展Web应用程序的7个阶段”的这个(简短)演示文稿 slideshare.net/davemitz/7-stages-of-scaling-web-applications - Richard Marr
我的建议是考虑你的前10个站点,并在尝试设计10,000之前更多地学习问题域 - Richard Marr


答案:


我对你的高级评论是建立你的系统 12因素 设计,然后担心客户到达时的扩展。我对Node.js和npm生态系统感到非常兴奋,但我也认为你可以用Rails构建一个完全可以接受的平台。如果使用3个dynos来支持100个并发用户并使用Rails加倍,那么使用Rails可能会更好,如果你对Ruby的安慰让你上市3个月更快。无论如何,假设你使用Node,这是我的答案:

  1. 这里有一些 备择方案 对Pusher来说可能适合你并且讨论 Pusher vs. Pubnub。另见 干练
  2. 使用 socket.io。它主要是标准,因为它使用可用的最佳传输,并从WebSockets回退到HTTP方法。
  3. Node是一个很棒的选择,也很新潮(参见模块 增长率)。我怀疑你可以让你的系统在Node,Rails或其他几个框架中正常工作。
  4. Heroku dyno应该能够支持数以万计的并发连接,具体取决于你使用RAM的效率。具有16 GB RAM的服务器能够支持a 百万 并发连接。假设您受RAM限制,具有512 MB RAM的Heroku dyno应该能够支持~30 K连接。
  5. 您可能希望选择两个不同的系统,一个用于存储和处理数据,另一个用于缓存。这是一个伟大的 岗位 关于从Instagram的创建者那里挑选你的核心数据平台。对于核心数据,我推荐使用Sequelize ORM的Postgres(在Heroku上)。但是,使用SOLR进行搜索的Mongo可能也可以正常工作。请注意,Postgres 9.2可用作NoSQL数据存储区,如果这是您想要的方式。对于缓存系统,我强烈推荐Redis。
  6. 不,我会尽量避免扔掉工程。相反,构建一些有效的东西,并期望每当你达到一个数量级的更多流量时,系统的某些部分将会中断并需要被替换。但是,如果您遵循12因素原则,那么在投资替换时,您应该处于良好状态以横向扩展。

祝你好运。


8
2018-06-26 10:49



嗨丹。感谢您的回答,非常有用和非常有用的链接 - Peter Nixey


  1. 套接字有很多服务,但Pusher和Pubnub似乎是这个领域的市场领导者。无论你做什么,都不要像socket.io那样托管自己的东西 heroku超时请求更长时间 超过30秒,包括websockets。因此,除非您计划每隔几秒钟关闭并重新打开套接字,否则托管套接字肯定是不可能的。
  2. 如果您使用像Pusher这样的套接字服务,那么您将需要为该服务实现一个http端点,无论如何都要向您发送数据。所以我只是把中间人剪掉,直接用http请求。当然,您需要收集持续的用户交互,但这些交互都可以记录在JavaScript客户端上并定期发送回应用程序 CORS XHR或跟踪图像。
  3. node是一个很好的选择,它很轻,很容易设置,npm库可以提供你开始使用所需的一切。 Rails也可以非常迅速,特别是如果你切掉你不需要的东西。有一个很棒的 railscast 关于这个问题。重要的是保持尽可能简单。也许将它分成两个应用程序;一个用于收集数据,另一个用于分析/处理数据。通过这种方式,您可以收集节点中的数据,因为它很快并且可以在轨道中分析/处理它,因为它很容易。
  4. 正如我在1.套接字中提到的那样,套接字不会在heroku中工作,即使你使用pusher,你仍然需要支持相同数量的http请求,因为当推送器收到数据时它将直接发送它给你。至于你需要多少个dynos,这将是一个容易测试的东西,但不是我能估计的东西。它完全取决于收集数据的代码的效率。使用您期望的加载和并发性的简单Apache AB测试将为您提供所需内容的良好指示。 Node带有它自己的并发性,但是如果你使用rails来收集数据,那么使用unicorn或puma作为你的服务器,因为它们支持并发。 Apache AB测试时也尝试不同的配置; heroku现在提供2x dynos,它是1024mb而不是512,这将允许你更多的并发
  5. 这个stackoverflow线程 建议redis越快越快,你想要收集数据。虽然在收集它之后,您可能希望处理它并将其存储在一个键值存储中。 Mongo是一个很好的选择,但我会选择图形数据库 Neo4j的 因为分析有复杂的连接。
  6. 如果你在这里进入新的领域,那么你将无法在第一时间做到正确,你会发现自己在迭代它以获得最佳性能和最准确的数据。最终你可能会删除它并重新开始使用新架构,循环将继续。保持数据收集和分析分离意味着您可以专注于分别获得每个位。

我想提到的一些附加点是使用CDN来分发JavaScript客户端,或者更好的是,提供从页面提供的完整JS。无论哪种方式,加载速度和异步加载。这听起来像一个有趣的项目。祝你好运!

编辑 在另一个Universe中,您不必使用heroku,websockets将是一个很棒的解决方案。


3
2018-06-26 18:20



马克,这非常有帮助,谢谢。您是否知道单个heroku dyno与节点和Reddis结合的处理能力是什么 - 有关每秒有多少http请求和写入可以处理的任何想法? - Peter Nixey
不幸的是,在我的用例中,我有一个类似的情况,我在heroku上使用mongodb(mongohq)有一个减少版本的rails。 2x大(1024)dynos,每个共有6个并发= 12个,每天大约有400,000次点击,没有任何问题,还有很多爆破空间。内存使用率很低,因此我可以进一步提高并发性。至于有形的替补标记,我现在手边还没有。 - Marc Greenstock
尽管如此,这是一个有用的数字 - 干杯 - Peter Nixey