这个系列文章翻译自 Jonathan Fulton 的 Web Architecture 101 The basic architecture concepts I wish I knew when I was getting started as a web developer 。原文较长,在此拆分成几个部分。
如今的大型网站架构越来越复杂,早就不只是简单的前端后端数据库能概括的。这篇文章以作者自家的网站 Storyblocks 为例,将许多小白初听时不明觉厉的技术都做了介绍,全面且易懂。如作者所言,可以让小白对一个网站里里外外各部分都有个基本概念。
上面这张图很好的展现了我们 Storyblocks 的网站架构。如果你不是网络开发老手,可能会觉得有点复杂。接下来我们先简单的走一遍流程,再详细介绍各个环节:
当一个用户在谷歌里搜 “Strong Beautiful Flog And Sunbeams In The Forest”, 第一个搜索结果就来自于我们 Storyblock。这是一个业界领先的照片和矢量图素材网站。接下来用户点击了该搜索结果,就被带到了我们网站的图片详情页。实际上浏览器是先在 DNS 查询了怎么访问我们 Storyblocks,然后再向我们发出网络请求。
请求到达了我们网站的负载均衡部分 (load balancer),它会从我们的十来个网络服务器 (web server) 里随机挑选一个来处理这个网络请求。网络服务器从缓存 (cache) 中查询到了这张图片相关的部分信息,还有一些信息则需要去数据库 (database) 调取。同时,我们发现这张图片还没有计算过色彩信息,于是把这项工作排入工作队列 (job queue) 。这个工作将被队列异步处理,并将结果更新到数据库中去。
接下来,我们会通过我们的全文搜索服务 (full text search service) 搜索这张图片的标题,试着寻找相似的图片。假设这位用户恰好又是已经登录了的 Storyblock 用户,我们还可以通过我们账号服务 (service account service) 查找用户的账号信息。最后,我们我们向我们的数据通路 (data firehose) 发出一个页面访问的事件,把事件记录在我们的云端存储系统 (cloud storage system), 并最终将数据移至我们的数据仓库 (data warehouse),以供我们的分析师将来用它们分析业务问题。
服务器接下来会以 HTML 的格式返回页面,再经过负载均衡部分,把它送回至用户的浏览器。这个页面中包含了 Javascript 和 CSS 素材,这些东西我们已经存储在云端,并连接到我们的 CDN 中。因此用户的浏览器会去 CDN 中取回这些内容。最后,浏览器渲染出页面展现给用户。
接下来我会向你讲解每一个环节,分别给你一个 “101” 式的 (注:即完全入门级)介绍,让你从此对网站架构形成一个不错的思维模型。我接下来会继续写一系列文章,就我在 Storyblocks 学到的经验分别对如何开发每个部分给出一些建议。
1.DNS (域名服务器)
DNS 代表域名服务器 (Domain Name Server),是万维网的的核心构成之一。简单来说 DNS 提供了从域名 (例如 google.com) 到其 IP 地址 (例如 85.129.83.120) 的查询服务,这样你的电脑发出的请求最终才能送达正确的服务器。用电话号码打比方,域名与 IP 地址之间的区别就是 “给 John Doe 打电话” 和 “给 201-867-5309 打电话” 的区别。就好像从前你要用电话簿来查询 John 的电话号码,你需要用 DNS 来查询某个域名的 IP 地址。所以你可以把 DNS 理解成互联网的电话簿。
更多的细节对我们这个 101 入门指南意义不大,这里就不展开讲了。
2. Load Balancer (负载均衡)
在讲负载均衡之前,我们先退一步讨论一下程序应用的横向与纵向规模化。什么是规模化,两种规模化之间的区别是什么?按照这篇 StackOverflow 帖子里的极简说法,横向规模化就是多加机器,而 “纵向” 则指把已有的机器升级的更强劲 (例如增加 CPU,内存)。
在网络开发中,你大部分时候都应该选择横向规模化。简单来说是因为早晚会有故障发生。服务器会挂,网络会拥堵,整个数据中心有时候也会集体掉线。拥有多个服务器能使你的应用程序在这种故障发生时还能正常运行。换句话说,你的应用”容错“能力更强大了。第二,横向规模化可以使你的后台 (网络服务器,数据库,某个服务等等) 跑在不同的服务器上,使他们之间的耦合度降到最低。最后,纵向规模化总会达到极限,那时世界上没有单独一台电脑强大到能承担你程序所有的计算任务。Google 搜索就是个很好的例子,虽然同样的道理也适用于小公司。举例来说 Storyblocks 时刻都运行在 150 到 400 个之间的 AWS EC2 实例上。要用纵向规模化达到这样的算力就困难多了。
好了,说回负载均衡。就是它使得横向规模化成为可能。它把收到的请求,导向众多镜像服务器中的一个,也负责把服务器的响应返回给客户端。这些镜像服务器处理同一个请求结果应该是一模一样的,因此负载均衡只需要保证把请求均衡分配给各个服务器,避免某一个过载。
就这么简单。从概念上理解负载均衡很容易,当然实际上其中的细节还是比较复杂的,但对这篇入门文章来说不用涉及。