单个服务器扩展到百万用户的系统

原文地址:https://arcentry.com/blog/scaling-webapps-for-newbs-and-non-techies/

你开发了一个网站(例如网上商店、社交网站或者其他任何东西),之后你把它发布到了网上,网站运行良好,每天有几百的访问量,能快速地相响应用户的请求。

但是有一天,不知道什么原因,你的网站出名了!

每分每秒都有成千上万的用户蜂拥而至,你的网站变得越来越慢……

对你来讲,这是个好消息,但是对你的Web应用来说这是个坏消息。因为现在它需要扩展了,你的应用需要为全球用户提供7*24不宕机服务。

如何进行扩展?

几年前,我讨论过水平扩展与垂直扩展。简而言之, 垂直扩展意味着在性能更强的计算机上运行同样的服务,而水平扩展是并行地运行多个服务。

如今,几乎没有人说垂直扩展了。原因很简单:

  • 随着计算机性能的增长,其价格会成倍增长
  • 单台计算机的性能是有上限的,不可能无限制地垂直扩展
  • 多核CPU意味着即使是单台计算机也可以并行的。那么,为什么不一开始就并行化呢?

现在我们水平扩展服务。需要哪些步骤呢?

1、单台服务器 + 数据库

上图可能是你后端服务最初的样子。有一个执行业务逻辑的应用服务器(Application Server)和保存数据的数据库。

看上去很不错。但是这样的配置,满足更高要求的唯一方法是在性能更强的计算机上运行,这点不是很好。

2、增加一个反向代理

成为大规模服务架构的第一步是添加反向代理。类似于酒店大堂的接待处。

你也可以让客人直接去他们的客房。但是实际上,你需要一个中间人他去检查是否允许客人进入, 如果客房没有开放,得有人告诉客人,而不是让客人处于尴尬的境地。这些事情正是反向代理需要做的。

通常,代理是一个接收和转发请求的过程。正常情况下,「正向代理」代理的对象是客户端,「反向代理」代理的对象是服务端,它完成这些功能:

  • 健康检查功能,确保我们的服务器是一直处于运行状态的
  • 路由转发功能,把请求转发到正确的服务路径上
  • 认证功能,确保用户有权限访问后端服务器
  • 防火墙功能,确保用户只能访问允许使用的网络部分等等

3、引入负载均衡器

大多数反向代理还有另外一个功能:他们也可以充当负载均衡器。

负载均衡器是个简单概念,想象下有一百个用户在一分钟之内在你的网店里付款。遗憾的是,你的付款服务器在一分钟内只能处理50笔付款。这怎么办呢?同时运行两个付款服务器就行了。

负载均衡器的功能就是把付款请求分发到两台付款服务器上。用户1往左,用户2往右,用户3再往左。。。以此类推。

如果一次有500个用户需要立刻付款,这该怎么解决呢?确切地说,你可以扩展到十台付款服务器,之后让负载均衡器分发请求到这十台服务器上。

4、扩展数据库

负载均衡器的使用使得我们可以在多个服务器之间分配负载。但是你发现问题了吗?尽管我们可以用成百上千台服务器处理请求,但是他们都是用同一个数据库存储和检索数据。

那么,我们不能以同样的方式来扩展数据库吗?很遗憾,这里有个一致性的问题。

系统使用的所有服务需要就他们使用的数据达成一致。数据不一致会导致各种问题,如订单被多次处理,从一个余额只有100元的账户中扣除两笔90元的付款等等......那么我们在扩展数据库的时候如何确保一致性呢?

我们需要做的第一件事是把数据库分成多个部分。一部分专门负责接收并存储数据,其他部分负责检索数据。这个方案有时称为主从模式或者单实例写多副本读。这里假设是从数据库读的频率高于写的频率。这个方案的好处是保证了一致性,因为数据只能被单实例写入,之后把写入数据同步到其他部分即可。缺点是我们仍然只有一个写数据库实例。

这对于中小型的Web应用来说没问题, 但是像Facebook这样的则不会这样做了。我们会在第九节中研究扩展数据库的步骤。

5、微服务

到目前为止,我们的付款、订单、库存、用户管理等等这些功能都在一台服务器上。

这也不是坏事,单个服务器同时意味着更低的复杂性。随着规模的增加,事情会变得复杂和低效:

  • 开发团队随着应用的发展而增长。但是随着越来越多的开发人员工作在同一台服务器上,发生冲突的可能性很大。
  • 仅有一台服务器,意味着每当我们发布新版本时,必须要等所有工作完成后才能发布。当一个团队想快速地发布而另外一个团队只完成了一半工作的时候,这种互相依赖性很危险。

对于这些问题的解决方案是一个新的架构范式:微服务, 它已经在开发人员中掀起了风暴。

  • 每个服务都可以单独扩展,更好地适应需求
  • 开发团队之间相互独立,每个团队都负责自己的微服务生命周期(创建,部署,更新等)
  • 每个微服务都有自己的资源,比如数据库,进一步缓解了第4节中的问题。

6、缓存和内容分发网络(CDN)

有什么方式能使服务更高效? 网络应用的很大一部由静态资源构成,如图片、CSS样式文件、JavaScript脚本以及一些针对特定产品提前渲染好的页面等等。

我们使用缓存而不是对每个请求都重新处理,缓存用于记住最后一次的结果并交由其他服务或者客户端,这样就不用每次都请求后端服务了。

缓存的加强版叫内容分发网络(Content Delivery Network),遍布全球的大量缓存。这使得用户可以从物理上靠近他们的地方来获取网页内容,而不是每次都把数据从源头搬到用户那里。

7、消息队列

你去过游乐园吗?你是否走到售票柜台去买票?也许不是这样,可能是排队等候。政府机构、邮局、游乐园入口都属于并行概念的例子,多个售票亭同时售票,但似乎也永远不足以为每个人立即服务,于是队列形成了。

队列同样也是用于大型Web应用。每分钟都有成千上万的图片上传到Instagram、Facebook每个图片都需要处理,调整大小,分析与打标签,这些都是耗时的处理过程。

因此,不要让用户等到完成所有步骤,图片接收服务只需要做以下三件事:

  • 存储原始的、未处理的图片
  • 向用户确认图片已经上传
  • 创建一个待办的任务

这个待办事项列表中的任务可以被其他任意数量服务接收,每个服务完成其中一个任务,直到所有的待办事项完成。管理这些“待办事项列表”的称为消息队列。使用这样的队列有许多优点:

  • 解耦了任务和处理过程。有时需要处理大量的图片,有时很少。有时有大量服务可用,有时很少可用。简单地把任务添加到待办事项而不是直接处理它们,这确保了系统保持响应并且任务也不会丢失。
  • 可以按需扩展。启动大量的服务比较耗时,所以当有大量用户上传图片时再去启动服务,这已经太晚了。我们把任务添加到队列中,我们可以推迟提供额外的处理能力。

好了,如果按照我们上面的所有步骤操作下来,我们的系统已经做好提供大流量服务的准备了。但是如果还想提供更大量的,该怎么做呢?还有一些可以做:

8、分片,分片,还是分片

什么是分片?好吧,深呼吸一下,准备好了吗?我们看下定义:

"Sharding is a technique of parallelizing an application‘s stacks by separating them into multiple units, each responsible for a certain key or namespace"

哎呦...... 分片究竟是是什么意思呢?

其实也很简单:Facebook上需要为20亿用户提供个人资料, 可以把你的应用架构分解为 26个mini-Facebook, 用户名如果以A开头,会被mini-facebook A处理, 用户名如果以B开头,会被mini-facebook B来处理……

分片不一定按字母顺序,根据业务需要,你可以基于任何数量的因素,比如位置、使用频率(特权用户被路由到好的硬件)等等。你可以根据需要以这种方式切分服务器、数据库或其他方面。

9、对负载均衡器进行负载均衡

到目前为止,我们一直使用一个负载均衡器,即使你购买的一些功能强悍(且其价格极其昂贵)的硬件负载均衡器,但是他们可以处理的请求量也存在硬件限制。

幸运地是,我们可以有一个全球性、分散且稳定的层,用于在请求达到负载均衡器之前对请求负载均衡。最棒的地方是免费,这是域名系统或简称DNS。DNS将域名(如arcentry.com)映射到IP,143.204.47.77。DNS允许我们为域名指定多个IP,每个IP都会解析到不同的负载均衡器。

你看,扩展Web应用确实需要考虑很多东西,感谢你和我们一起待了这么久。我希望这篇文章能给你一些有用的东西。但是如果你做任何IT领域相关的工作,你在阅读本文的时候,可能有个问题一直萦绕在你的脑海:"云服务是怎样的呢?"

Cloud Computing / Serverless

但是云服务如何呢?确实,它是上面许多问题最有效的解决方案。

你无需解决这些难题。相反,这些难题留给了云厂商,他们为我们提供一个系统,可以根据需求进行扩展,而不用担心错综复杂的问题。

例如。Arcentry网站不会执行上述讨论的任何操作(除了数据库的读写分离),而只是把这些难题留给Amazon Web Service Lambda函数处理了,用户省去了烦恼。

但是,并不是说你使用了云服务以后(如 Amazon Web Service Lambda),所有的问题都解决了,它随之而来的是一系列挑战和权衡。

原文地址:https://www.cnblogs.com/oxspirt/p/10783566.html

时间: 2024-11-05 18:32:30

单个服务器扩展到百万用户的系统的相关文章

百万用户时尚分享网站feed系统扩展实践

Fashiolista是一个在线的时尚交流网站,用户可以在上面建立自己的档案,和他人分享自己的以及在浏览网页时看到的时尚物品.目前,Fashiolista的用户来自于全球100多个国家,用户达百万级,每日分享的时尚物品超过500万.作为一个以社交.分享的网站,feed系统占据了网站的核心架构,Fashiolista的创始人兼CTO Thierry Schellenbach撰写了一篇博客,分享了自家网站feed系统建设的经验,译文如下: Fashiolista最初是我们作为兴趣在业余时间开发的一个

设计一个可扩展的用户登录系统

在Web系统中,用户登录是最基本的功能.如何设计一个可扩展的用户登录系统呢?本文结合实际案例对用户登录系统设计进行多维度的讲解,帮助各设计者在应用中将复杂变得简单. 来源:廖雪峰的官方网站,作者:廖雪峰. [一] 在Web系统中,用户登录是最基本的功能.要实现用户名+密码登录,很多同学的第一想法就是直接创建一个Users表,包含username和password两列,这样,就可以实现登录了: id | username | password | name等其他字段 ----+----------

支撑日活百万用户的高并发系统,应该如何设计其数据库架构?

目录: 用一个创业公司的发展作为背景引入 用多台服务器来分库支撑高并发读写 大量分表来保证海量数据下查询性能 读写分离来支撑按需扩容及性能提升 高并发下的数据库架构设计总结 " 这篇文章,我们来聊一下对于一个支撑日活百万用户的高并系统,他的数据库架构应该如何设计? 看到这个题目,很多人第一反应就是: 分库分表啊! 但是实际上,数据库层面的分库分表到底是用来干什么的,他的不同的作用如何应对不同的场景,我觉得很多同学可能都没搞清楚. (1)用一个创业公司的发展作为背景引入 假如我们现在是一个小创业公

基于 Laravel (5.1) & Ember.js (1.13.0) 的用户授权系统

Laravel 本身提供了完整的用户授权解决方案,对于由 PHP 驱动的多页面应用,Laravel 能够完美解决用户授权问题.但是在 SPA 中,laravel 退化成一个 API server,页面路由和表单提交完全由前端框架控制,此时面临2个问题: 如何在前端实现页面访问权限控制? 如何对 ajax 请求做授权? 如何在前端实现页面访问权限控制? Ember.js 1.13.0 没有提供 authentication 功能,我使用了一个名为 ember-simple-auth 的第三方扩展.

我用爬虫一天时间“偷了”知乎一百万用户,只为证明PHP是世界上最好的语言

我用爬虫一天时间“偷了”知乎一百万用户,只为证明PHP是世界上最好的语言 2015-08-06 猿圈 我用爬虫一天时间“偷了”知乎一百万用户 只为证明PHP是世界上最好的语言 看了不少朋友圈里推荐的Python爬虫文章, 都觉得太小儿科,处理内容本来就是PHP的强项,Python唯一的好处估计也就天生的Linux自带,和Perl一样,这点觉得挺不够意思的 Linux,还是Mac厚道,天生就自带了Python.Perl.PHP.Ruby,当然我也很讨厌讨论一门语言的好坏,每门语言存在就一定有它的道

Django实战之用户认证系统

详情请交流  QQ  709639943 00.Python 从入门到精通 78节.2000多分钟.36小时的高质量.精品.1080P高清视频教程!包括标准库.socket网络编程.多线程.多进程和协程. 00.Django实战之用户认证系统 00.Django实战之企业级博客 00.深入浅出Netty源码剖析 00.NIO+Netty5各种RPC架构实战演练 00.JMeter 深入进阶性能测试体系 各领域企业实战 00.30天搞定大数据爬虫项目 00.零基础实战机器学学习 00.企业级实战

Linux服务器中限制FTP用户访问方式

FTP(File Transfer Protocol)协议:是一个用于在计算机间上传.下载文件的协议. FTP工作在客户端/服务器端的模式中. FTP服务器持续监听来自远处客户端的FTP需求,在收到远处客户端的需求后,它负责管理登陆及建立连接.建立会话期间,执行FTP客户端发过来的命令.进入FTP服务器可以用匿名或者鉴权两种方式来管理.出于安全考虑,LINUX中的大部分系统,会考虑采用鉴权模式,即进入/访问FTP服务器,必须用用户名或密码的方式. 因为FTP不是一个安全协议,所以必须尽量被限制.

MySQL用户和系统变量

--MySQL用户和系统变量-----------------------------2014/05/19用户变量可以先在用户变量中保存值然后在以后引用它:这样可以将值从一个语句传递到另一个语句.用户变量与连接有关.也就是说,一个客户端定义的变量不能被其它客户端看到或使用.当客户端退出时,该客户端连接的所有变量将自动释放.用户变量的形式为@var_name,其中变量名var_name可以由当前字符集的文字数字字符.'.'.'_'和'$'组成. 默认字符集是cp1252 (Latin1).可以用m

如何配置报表服务器扩展部署(Reporting Services 配置)

Reporting Services 支持扩展部署模式.该模式允许运行共享单个报表服务器数据库的多个报表服务器实例. 若要创建扩展部署,请使用安装程序和 Reporting Services 配置工具: 使用安装程序安装将与扩展部署联接的每个报表服务器实例. 使用 Reporting Services 配置工具将每个报表服务器连接到共享数据库.您一次只能连接并配置一台报表服务器. 使用 Reporting Services 配置工具将新的报表服务器实例联接到已经与报表服务器数据库连接的第一个报表