写点什么

如何为从 1 到 10 万用户的应用程序,设计不同的扩展方案?

2020 年 3 月 26 日

如何为从1到10万用户的应用程序,设计不同的扩展方案?

对于创业公司来说,有用户注册是好事情,但是当用户从零扩展到成千上万之后,Web 应用程序又该如何支持呢?


通常来说,这种情况的解决方案要么是来自突然爆发的紧急事件,要么是系统出现瓶颈进行升级改造。虽然方式不同,但是我们也发现了,一个边缘项目发展成高度可扩展项目,其升级方案是有一些普适的“公式”可以套用,本文以 Graminsta 为例,为大家介绍当用户从 1 位发展到 10 万,应用程序如何扩展?


1 位用户:1 台机器

无论是网站还是移动应用,应用程序几乎都包括这三个关键组件:API、数据库和客户端,其中数据库用来存储持久数据,API 服务于数据及与其有关的请求,而客户端负责将数据呈现给用户。


在现代应用程序开发中,客户端往往会被视为一个独立于 API 的实体,这样一来就可以更轻松地扩展应用程序了。


当刚开始构建应用程序时,可以让这三个组件都运行在一个服务器上,类似于我们的开发环境,一位工程师在同一台计算机上运行数据库、API 和客户端。


当然,理论上我们可以把它部署到云上的单个 DigitalOcean Droplet 或 AWS EC2 实例上,如下所示:



但是,当我们的用户未来不止 1 个的时候,其实刚开始就应该考虑是否要将数据层拆分出来。


10 个用户:拆分数据层

拆分数据层,并将其作为一个类似于 Amazon 的 RDS 或 Digital Ocean 的托管数据库的托管服务。这样做的话,虽然成本会比在一台机器上或 EC2 实例上自托管高一些,但是我们可以获得很多现成且方便的东西,例如多区域冗余、只读副本、自动备份等等。


Graminsta 现在的系统如下所示:



100 个用户:拆分客户端

当网站流量变得稳定之后,就到了拆分客户端的时候了。


需要注意的是,拆分实体是构建可扩展应用程序的关键所在。当系统中的某一部分获得了更多流量,那么就应该把它拆分出来,根据其自身的特定流量模式来处理服务的扩展。这也是我会把客户端和 API 看作是相互独立的组件的原因,这样,我们就可以轻松为多平台构建产品,例如 web、移动 web、iOS、Android、桌面应用、第三方服务等,它们都是使用相同 API 的客户端。


现在,Graminsta 的系统如下所示:



1000 个用户:负载均衡器

当新用户越来越多,如果只有一个 API 实例可能满意满足所有的流量,这时我们需要更多的计算能力。


这时,负载均衡器该上场了,我们在 API 前面添加一个负载均衡器,它会把流量路由到该服务的一个实例上,我们就可以进行水平扩展(通过添加更多运行相同代码的服务器来增加可以处理的请求数量)。


我们在 web 端和 API 前面添加了一个独立的负载均衡器,这意味着我们拥有了多个运行 API 和 web 客户端代码的实例。该负载均衡器会把请求路由到任何一个流量最小的实例上。并且,我们还可以从中得到冗余,当一个实例宕机(过载或崩溃)时,其他实例还可以继续运行,响应传入的请求,而不是整个系统宕机。


负载均衡器还支持自动扩展,在流量高峰时可以增加实例的数量,当流量低谷时,减少实例数量。借助负载均衡器,API 层实际上可以无限扩展,如果请求增加,我们只需要不断增加实例就可以了。



编者注:到目前为止,我们拥有的产品和 PaaS 公司(如 Heroku 或 AWS 的 Elastic Beanstalk)提供的开箱即用产品非常类似。Heroku 把数据库托管在单独的主机上,用自动扩展来管理负载均衡器,并允许我们把 API 和 web 客户端分开托管。对于早期初创企业来说,使用 Heroku 等服务来做项目是一个不错的选择,所有必需的、基本的东西都是开箱即用。


10000 个用户:CDN

对于 Graminsta 来说,处理和上传图像为服务器带来了很大的负担。所以,Graminsta 选择了使用云存储服务来托管静态内容,例如图像、视频等(AWS 的 S3 或 Digital Ocean 的 Spaces),而 API 应该避免图像处理和图像等业务。


另外,使用云存储服务,我们还可以使用 CDN,可以在遍布全球不同的数据中心自动缓存图像。我们的主数据中心可能托管在


我们从云存储服务得到的另一样东西是 CDN(在 AWS,这是一个被称为 Cloudfront 的插件,但是很多云存储服务都以开箱即用的方式提供它)。CDN 将在遍布全球不同的数据中心自动缓存我们的图像。


虽然我们的主数据中心可能托管在俄亥俄州,如果有人在日本对图像发出了请求,那么云供应商就会进行复制,将其存储在位于日本的数据中心,下一个请求该图像的日本用户就会很快收到图像。



10 万个用户:扩展数据层

负载均衡器在环境中添加了 10 个 API 实例,使得 API 的 CPU 和内存消耗都很低,CDN 帮助我们解决了世界各地图像请求的问题。但是现在,我们有一个问题需要解决,那就是请求延迟。


通过研究,我们发现数据库 CPU 的消耗占比达到了 80%-90%,因此扩展数据层成为了当务之急。数据层的扩展是一件很棘手的事情,虽然对于服务无状态请求的 API 服务器来说,只需要添加更多实例即可,但是对于大多数数据库系统来说,却不是这样。


缓存

要从数据库获得更多信息的最简单方法之一是给系统引入一个新的组件:缓存层。实现缓存最常用的方法是使用内存中的键值存储(如 Redis 或 Memcached),且大多数云厂商都会提供数据库服务的托管版本。


当该服务正在进行对数据库相同信息的大量重复调用时,就是缓存大显身手的时候了。当我们访问数据库一次时,缓存就会保存信息,之后再进行相同请求时,就不必再访问数据库了。


例如,如果有人想在 Graminsta 中访问 Mavid Mobrick 的个人资料页面时,我们把从数据库中得到的结果,缓存在 Redis 中关键字 user:id 下,到期时间为 30 秒。之后,每当有人访问 Mavid Mobrick 的个人资料时,我们会首先查看 Redis,如果存在相关资料,那就直接从 Redis 提供数据。


大多数缓存服务的另一个优点是,与数据库相比,更容易扩展。Redis 有个内建的 Redis 集群(Redis Cluster)模式,用的是跟负载均衡器类似的方式,可以把我们的 Redis 缓存分布到多台机器上 。


所有高度扩展的应用程序几乎都充分利用了缓存的优势,缓存是构建快速 API 不可或缺的部分,可以提供更好的查询和更高效的代码,如果没有缓存,我们可能很难扩展到数百万用户的规模。


只读副本

由于对数据库的访问相当多,因此我们需要在数据库管理系统来添加只读副本。借助上面提到的托管服务,只需要点击一下就可以完成。只读副本将和主数据库保持一致,并且能够用于 SELECT 语句。



未来展望

随着应用的不断扩展,我们会把重点放在拆分独立扩展的服务。例如,如果我们使用了 websockets,那么会把 websockets 处理代码抽取出来,放在新的实例上,同时安装负载均衡器。该负载均衡器可以根据 websocket 连接打开或关闭的数量来上下扩展,与我们收到的 HTTP 请求数量无关。


如果未来还会遇到数据层的限制,我们就会对数据库进行分区和分片。


我们会使用 New Relic 或 Datadog 等服务安装监控程序,并通过监控程序发现比较慢的请求,改进它。同时,随着扩展的不断进行,我们希望能够发现更多的瓶颈并解决它。


原文链接:


https://alexpareto.com/scalability/systems/2020/02/03/scaling-100k.html


2020 年 3 月 26 日 09:262675

评论 3 条评论

发布
用户头像
这个对于一般的应用基本够用了,不过10万用户还得说说活跃用户及可以支持的并发访问数量,毕竟僵尸用户也很多
2020 年 03 月 30 日 10:53
回复
用户头像
清晰易懂,我这个做客户端的都能明白。
2020 年 03 月 26 日 15:14
回复
有点类似于“扩展公式”,希望有用^_^
2020 年 03 月 26 日 16:28
回复
没有更多了
发现更多内容

泰山版震撼来袭!阿里巴巴Java面试参考权威指南四月版开源

Java架构追梦

Java 阿里巴巴 架构 面试 面试参考指南

Flink中的状态编程

大数据技术指南

flink 4月日更

架构实战营模块1作业指导

华仔

#架构实战营

如何在云中构建数字核心

浪潮云

云计算

Adobe国际认证,Photoshop软件向多图层图像中添加更多图像,官方教程

Adobe国际认证

Adobe国际认证 Photoshop软件

计算机原理学习笔记 Day10

穿过生命散发芬芳

计算机原理 4月日更

知乎万赞回答:程序员面试为什么被要求造航母,而工作拧螺丝?

Java架构师迁哥

这个GItHub上的Java项目开源了 2021最全的Java架构面试复习指南

比伯

Java 编程 架构 面试 程序人生

趣题与算法(1)

架构与源码

色字头上一把刀:某站点色诱套路分析

Machine Gun

网络安全 WEB安全 诈骗

如何提高Linux水平

cdhqyj

最新分享:如何避免线程安全的坑?看这一篇就够了

学Java关注我

Java 编程 程序员 架构 计算机

推进智慧城市建设 博睿数据亮相长三角城市数字化转型高峰论坛

博睿数据

数字化转型高峰论坛

专访阿里巴巴研究员吴翰清:白帽子的网络安全世界观

五分钟学大数据

网络安全 采访

开源 1 年半 star 破 1.2 万的 Dapr 是如何在阿里落地的?

阿里巴巴云原生

Java 微服务 云原生 中间件 API

【全球年青人召集令】Hello World,Hello 2050

阿里巴巴云原生

容器 开发者 云原生 活动

架构思维

无心

架构

华为云AI论文精读会2021第一期:高效语义分割模型Fast-SCNN分享

华为云开发者社区

AI 华为云

Linux free 命令

一个大红包

linux命令 4月日更

来了来了!阿里内部面试参考指南(泰山版)限时开源分享,差距不止一点点!

程序员小毕

Java 程序员 架构 面试 阿里

未来已来,HarmonyOS 开发者日全记录

清秋

华为 开发 物联网 新闻 HarmonyOS

方寸之间,书写天地

石云升

4月日更 1 周年盛典 我和写作平台的故事 InfoQ 写作平台 1 周年

量化策略交易系统开发app,量化马丁策略交易平台搭建

WX13823153201

量化策略交易系统开发

欢迎参与 KubeVela 官方文档翻译活动

阿里巴巴云原生

容器 云原生 开发工具 OAM 资源调度

IPFS矿机投资靠谱吗?IPFS挖矿可靠吗?

投资矿机v:IPFS1234

IPFS矿机投资靠谱吗 IPFS挖矿可靠吗

那些打不垮你的,终究使你更强大

小天同学

读书 励志 个人感悟 4月日更

Flink的基石

五分钟学大数据

flink 4月日更

不为人知的网络编程(十二):彻底搞懂TCP协议层的KeepAlive保活机制

JackJiang

TCP 即时通讯 IM

GitHub面试题库+阿里巴巴2021年Java岗面试26大核心专题,成功助我砍下7家大厂Offer

Java架构追梦

Java 阿里巴巴 架构 面试 面试题总结

ipfs矿机一台多少钱?ipfs矿机一天挖多少币?ipfs矿池节点怎么查询?

v:IPFS456

数字货币 IPFS Filecoin IPFS节点怎么看 IPFS怎么挖矿

架构实战营作业2

冷酷小绵羊

如何为从1到10万用户的应用程序,设计不同的扩展方案?-InfoQ