java - 移动应用程序 API 扩展策略

标签 java mysql jetty netty quasar

我们的 API 是为支持一百万用户而开发的。由于我们在 4 个月内达到了 50 万大关,我们现在正在扩展它以支持我们计划在一年内达到的 1000 万用户。这些目标是现实的,因为我们现在将我们的核心数据处理/聚合逻辑作为 SDK 提供给其他应用。

当前的 API 是 HTTP post,其中正文是 JSON。当新用户注册时,他会从设备上传大约 200KB 的数据。以前我们过去常常在服务器端处理数据,但现在我们在设备本身上处理它。

此后,该应用每天将上传和下载大约 2KB 的数据。对于拥有多个移动设备的用户,这个数字要多一些,但仅占总用户群的 1%。

目前,我们的 API 服务器使用 Jetty+Jersey,平均并发连接数约为 200。它可以处理大约 500-1000 个并发连接(取决于请求的类型)。

每个 API 服务器(总共 4 个)有 120 个数据库连接。我们的工作负载是 80% 的写入和 20% 的读取,更新可以忽略不计。

现在 API 是同步的,我的意思是对于每个请求,我们存储/检索数据并将确认/数据发送回客户端。

一种扩展方法是(垂直和/或水平)扩展我们的 API 服务器并根据 userId 对数据库进行分片。完成数据库分片是因为我们的估计表明每百万用户需要 1TB 的数据存储。我们还计划迁移到 SSD,但这需要一些时间,因为我们有自己的数据中心并且迁移正在进行中。

我预见的主要挑战是在 SDK 推出流行应用程序时处理新用户的激增。我正在考虑一些方法:

1) 在写入请求期间,只需提取实体,推送到 KAFKA 并向客户端发送 ACK。消费者然后从队列中提取要保留的实体,然后批量插入它们。

2) 使用不同的读写服务器。对于读取,请使用现有的同步架构。对于写入请求,公开一个由 Netty 支持的不同 URL,它将提取实体以持久化并将它们推送到内存中的队列,向客户端发送 ACK。异步传输到 kafka 队列,然后最终传输到数据库。

3) 对每个请求使用异步服务器 Quasar+Comsat 和轻量级线程,让客户端等待确认(也获取持久化实体的自动增量 ID)。问题是 DB 连接数是瓶颈,允许许多并发的轻量级线程产生可能没有真正帮助。

任何有关指出这些方法的优点/缺点/改进的帮助或对新方法的建议都会有很大帮助。即使我们从 1000 万扩展到 10000 万,了解这些方法中哪些方法仍然有效也会有所帮助。我们没有 Web 界面,因此所有数据传输都是纯 json,在发展中国家,我们还必须支持 2G 设备和大量网络断开连接,因此也必须考虑到这一点。

最佳答案

注意:我是 Quasar/Comsat 团队的一员。

我不认为这些方法是相互排斥的,我只是建议不要普遍使用异步 API,因为它们会损害代码库的可读性/可维护性(因此, future ),而这正是 Quasar/Comsat 可以提供帮助的地方很多与他们的同步 API(但光纤而不是线程阻塞,因此与异步一样高效)。

如果您非常关心持久性,那么我也会尽可能少地将数据保存在 volatile 内存中。我不是 Kafka 专家,但我认为它可以处理大量负载并且有一个 Comsat integration in 0.6.0-SNAPSHOT .

是的,启动大量等待数据库池的纤程对您的吞吐量没有帮助。您需要一些 Kafka(或类似的)+ 异步传输摊销层或更快的数据库。

请记住,由于光纤非常便宜,如果您使用 Quasar 集成 API(或编写您的拥有,which is not difficult at all )。

最后我不确定您的 API 是单体还是微服务,尤其是在后一种情况下您可能对 this post of ours about Comsat VS. regular HTTP client performance 感兴趣.

关于java - 移动应用程序 API 扩展策略,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34379807/

相关文章:

java - 使用 Jetty Content Exchange 和 SSL 时是什么原因导致 "broken pipe"?

java - 可以将子域映射到标准 Java 应用程序服务器中的 Web 应用程序吗?

java - 如何删除JAVA中Set的Arraylist中存储的某个集合中的元素?

java - Java系统代码断点调试

java - Seam Quartz Dispatcher 未在给定 cron 表达式的秒和分钟字段上触发

android - 如何通过具有相同标题的多个列获取某些特定ID SQL ANDROID

php - bindParam 在哪里存储绑定(bind)?

mysql - 最常见的值

linux - 如何设置jetty服务启动

java - Spring Integration 2 - Splitter 仅返回第一个元素