如何从单个服务器扩展到百万用户的系统?( 二 )


这对于中小型的 Web 应用来说没问题,但是像 Facebook 这样的则不会这样做了 。
微服务
 

如何从单个服务器扩展到百万用户的系统?

文章插图
 
 
到目前为止,我们的付款、订单、库存、用户管理等等这些功能都在一台服务器上 。
这也不是坏事,单个服务器同时意味着更低的复杂性 。随着规模的增加,事情会变得复杂和低效:
  • 开发团队随着应用的发展而增长 。但是随着越来越多的开发人员工作在同一台服务器上,发生冲突的可能性很大 。
  • 仅有一台服务器,意味着每当我们发布新版本时,必须要等所有工作完成后才能发布 。
当一个团队想快速地发布而另外一个团队只完成了一半工作的时候,这种互相依赖性很危险 。
对于这些问题的解决方案是一个新的架构范式,微服务 。它已经在开发人员中掀起了风暴:
  • 每个服务都可以单独扩展,更好地适应需求 。
  • 开发团队之间相互独立,每个团队都负责自己的微服务生命周期(创建,部署,更新等) 。
  • 每个微服务都有自己的资源,比如数据库,进一步缓解了第 4 节中的问题 。
缓存和内容分发网络(CDN)
 
如何从单个服务器扩展到百万用户的系统?

文章插图
 
 
有什么方式能使服务更高效? 网络应用的很大一部由静态资源构成,如图片、css 样式文件、JAVAScript 脚本以及一些针对特定产品提前渲染好的页面等等 。
我们使用缓存而不是对每个请求都重新处理,缓存用于记住最后一次的结果并交由其他服务或者客户端,这样就不用每次都请求后端服务了 。
缓存的加强版叫内容分发网络(Content Delivery Network),遍布全球的大量缓存 。
这使得用户可以从物理上靠近他们的地方来获取网页内容,而不是每次都把数据从源头搬到用户那里 。
消息队列
 
如何从单个服务器扩展到百万用户的系统?

文章插图
 
 
你去过游乐园吗?你是否走到售票柜台去买票?也许不是这样,可能是排队等候 。
政府机构、邮局、游乐园入口都属于并行概念的例子,多个售票亭同时售票,但似乎也永远不足以为每个人立即服务,于是队列形成了 。
队列同样也是用于大型 Web 应用 。每分钟都有成千上万的图片上传到 Instagram、Facebook 每个图片都需要处理,调整大小,分析与打标签,这些都是耗时的处理过程 。
因此,不要让用户等到完成所有步骤,图片接收服务只需要做以下三件事:
  • 存储原始的、未处理的图片 。
  • 向用户确认图片已经上传 。
  • 创建一个待办的任务 。
这个待办事项列表中的任务可以被其他任意数量服务接收,每个服务完成其中一个任务,直到所有的待办事项完成 。管理这些“待办事项列表”的称为消息队列 。
使用这样的队列有许多优点:
  • 解耦了任务和处理过程 。有时需要处理大量的图片,有时很少 。有时有大量服务可用,有时很少可用 。简单地把任务添加到待办事项而不是直接处理它们,这确保了系统保持响应并且任务也不会丢失 。
  • 可以按需扩展 。启动大量的服务比较耗时,所以当有大量用户上传图片时再去启动服务,这已经太晚了 。我们把任务添加到队列中,我们可以推迟提供额外的处理能力 。
好了,如果按照我们上面的所有步骤操作下来,我们的系统已经做好提供大流量服务的准备了 。
但是如果还想提供更大量的,该怎么做呢?还有一些可以做 。
分片,分片,还是分片
 
如何从单个服务器扩展到百万用户的系统?

文章插图
 
 
什么是分片?好吧,深呼吸一下,准备好了吗?我们看下定义:
"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 来处理……
分片不一定按字母顺序,根据业务需要,你可以基于任何数量的因素,比如位置、使用频率(特权用户被路由到好的硬件)等等 。你可以根据需要以这种方式切分服务器、数据库或其他方面 。


推荐阅读