web 应用主流架构概览php
上图即是我司(Storyblocks)网络架构的很好展示。若是你还没成为经验老道的 web 工程师,可能以为上图巨复杂。在详解各个模块前,咱们先简单过一下流程。html
用户在 Google 搜索关键字 “Strong Beautiful Fog And Sunbeams In The Forest”,首条结果即是来自我司的拳头产品:Storyblocks —— 图片矢量图素材站,用户点击搜索结果进入图片详情页。在用户操做的背后,客户端浏览器向 DNS 服务器查询图片所在服务器,并发送访问请求。前端
用户请求经过负载均衡(随机选择多个服务器中的一个)访问站点处理请求。服务器从缓存服务中查找图片信息,并从数据库中调取其它信息。咱们注意到此时,图片还没有进行色彩渲染计算,便发送“色彩渲染”任务到任务队列。此时该服务所在服务器异步处理任务,适时将结果更新到数据库。mysql
接下来,咱们尝试匹配类似图片,以图片标题做为输入,进行全文搜索服务。用户登入系统,系统经过帐户服务查找帐户信息。最后,系统将该页面查看事件做为日志流处理并在云存储系统中记录,再录入数据仓库,供数据分析师作以后的商业分析。android
服务器将渲染的 HTML 页面先通过负载均衡,再返回到用户浏览器。页面包含 Javascript 脚本和 CSS 资源文件,存于与咱们的 CDN 相连的云端存储系统中,用户浏览器直接经过 CDN 获取内容。最后,浏览器显式地渲染页面,供用户浏览。ios
下面,咱们就每个组件详细讨论,作最最基础的介绍,帮你建构认知模型,思考整个前面提到的整个网络服务架构。以后我还会发布其它文章,基于在我司学习到的内容,为你们更有针对性地从实践角度作推荐。git
DNS(Domain Name Server)是域名服务器的简称,它是互联网依存的基础设施。简单来讲,DNS 提供域名与 IP 地址的键值对查找,例如(google.com 域名对应 85.129.83.120 IP 地址),这很是有必要,它让你的电脑经过请求寻路到特定服务器。就比如打电话,域名与 IP 地址的关系相似于联系人和电话号码的关系。之前你须要电话号码簿记录他人的电话号码,如今你须要 DNS 服务器寻找域名对应的 IP 地址。因此你能够把 DNS 想象成互联网世界的电话簿。github
这里咱们还有不少细节能够深刻,暂时先跳过,由于这不是咱们基础课的重点。web
在详解负载均衡以前,咱们先退一步讨论一下应用的纵向扩展和横向扩展。二者有什么区别?简单来讲,参考 StackOverflow 的这篇帖子,横向规模扩展意味着经过在资源池中加机器,纵向扩展意味着在已有机器上加强算力(如 CPU,RAM)。算法
在 web 开发绝大多数状况下,会选择横向扩展。理由很简单,服务器会宕机,网络会断线,数据中心会掉电。多台服务器能够保证你的应用在可以一边停机维护,一边持续工做。换句话说,应用可以“容错”。另外,横向扩展能最小限度地耦合不一样后台服务(web 服务器,数据库,等等),使不一样服务在不一样机器上运行。还有一点,纵向扩展是有上限的,到达必定限度就没法再扩展。世界上也不存在一台超算计算机承载应用的全部计算,典型例子想象一下 Google 的搜索平台,哪怕其它公司达不到这么大的规模。其它公司,好比我司,Storyblocks,任什么时候候都把服务跑在 150-400 个 AWS EC2 实例上。经过纵向扩展提供算力是至关有挑战的。
回到负载均衡,能够说它是横向扩展的黑魔法。它将传入请求转路到多个服务器中的其中一个,再将响应回传给客户端。多个服务器彼此做为镜像,任意机器都会以一样的方式处理请求。向服务集群分发消息,便不会出现单个服务器过载的状况。
理论上负载均衡就这些要点,很简单直接。固然了,简单的理论背后有更多细节,这篇入门文章里咱们再也不赘述。
从上层角度来看,web 应用服务器相对好理解,它们用来处理核心业务逻辑,处理用户请求,给客户端浏览器返回 HTML。处理这些任务即是与后台基础设施间通讯,好比数据库、缓存服务、任务队列、搜索服务、其它微服务和消息/日志队列等等。通常状况下至少两个应用服务器,或者更多,这些应用服务接入负载均衡,处理用户请求。
应用服务器的实现一般须要某种特定语言(Node.js, Ruby, PHP, Scala, Java, C# .NET 等)和对应的 MVC 框架上(Node.js 的 Express、Ruby on Rails、Scala 的 Play、PHP 的 Larave 和 Java 的 Spring 等等)。语言和框架的细节咱们这里不作赘述,有兴趣的读者能够自行深刻研究。
任意现代 Web 应用都使用一个甚至多个数据库来存储信息。数据库用来定义数据结构,对数据进行增删改查,高级运算操做等等。多数状况下,web 应用服务器与一个数据库进行直接通讯,任务服务器同理。另外,每一个后台服务都有一个本身的数据库,并与其它的应用隔离。
尽管在本文中,咱们尽可能避免深刻讨论架构中的某个特定技术,这里我仍是想特殊地提一下数据库中的 SQL 和 NoSQL。
SQL(Structured Query Language)全称结构化查询语言,1970 年代发布,提供了查询关系型数据库的一种标准形式,并广为大众接受。SQL 数据库将数据以表的形式存储,经过 ID (一般为 int 整型)这种方式使表之间相互关联。举个简单的例子,咱们想要存储用户的历史地址信息。须要准备两张表,用户表 users 和用户地址表 user_addresses,并经过 user_id 进行关联,以下图。表间相关联是经过在 user_addresses 表中使用 user_id 做为外键实现的。
若是你不了解 SQL,这里推荐可汗学院的课程学习。在 web 开发中 SQL 很是广泛,了解其基础做为应用架构仍是颇有必要的。
NoSQL,如其字面意思,“非-SQL”,是一种新型数据库,用来应对大规模 web 应用中的海量数据(大部分 SQL 不能很好支持横向扩展,只能从某些方面支持纵向扩展)。若是你彻底不了解 NoSQL,推荐下列文章:
我还想顺便提一点,业界一般使用 SQL 做为 NoSQL 数据库的表层调用,不懂 SQL 的话仍是颇有必要去学习的,现在的业务场景很难避开它。
缓存服务提供一种简单的键值对数据存储,使存取信息时间复杂度接近 O(1) 。应用内一般使用缓存服务存储运算成本高昂的运算结果,再次请求时从缓存中检索结果,而非在每次请求时都从新计算。缓存内容能够是数据库查询,外部服务调用结果,连接返回的 HTML,等等。下面咱们从真实场景中举例:
最经常使用到的服务器缓存技术是 Redis 和 Memcache。我以后会在其它文章中深刻讨论。
大部分 web 应用背后都有异步任务在处理,这些任务没必要直接响应用户请求。好比说,谷歌须要爬取整个互联网并创建索引以返回搜索结果,但这实际上并非在你每次搜索时都实时进行,而是经过异步方式爬取网络结果并更新索引。
异步任务有不少不一样的方式来完成,最经常使用的是任务队列。它包含两部分:正在运行的任务队列,和一或多个处理任务的服务器(一般称为 workers)。
任务队列存储了一系列须要异步运行的任务。最简单的任务调度是 FIFO(先进先出)的方式,不过大部分应用使用按优先级排序的调度方式处理任务。每当一个任务须要被执行,要么使用统一的调度算法,要么是按用户行为按需调度,该任务便被加入队列中等待被执行。
举个例子,我司利用任务队列,赋能后台任务以支持营销活动。咱们用后台任务编码多媒体文件如视频图片,处理数据如在 CSV 作元数据标记,聚合用户行为分析,运行邮件服务好比给用户发送重置密码的邮件,等等。咱们最初使用 FIFO 调度任务,后来优化为优先队列,以保证时间敏感的操做完成的实时性,好比立马发送重置密码邮件。
任务服务器执行任务时,先查看任务队列中是否有任务须要执行,如有任务便弹出该任务并执行。有不少语言和框架能够在服务器上使用做为任务队列,这里很少讲。
在一些应用中,为用户提供搜索功能,用户输入文字时(查询语句)应用返回相近结果。这种技术一般指的是“全文检索”,运用倒排索引快速查找包含查询关键字的文档。
上图中例子显示了三个文档标题被转换成倒排索引,经过某些标题关键字可以快速检索文档。一般停用词(英文中的:in、the、with 等,中文中:我、这、和、啊等)不会被加入到索引中。
尽管咱们能够直接经过数据库作全文检索,好比 MySQL 支持全文检索,但一般咱们会跑一个单独的“搜索服务”计算并存储倒排索引,并提供查询接口。目前主流的全文检索服务是 Elasticsearch,还有 Sphinx,Apache Solr 等选择。
当应用到达必定的规模,一般倾向于拆分其为单个应用,做为“微服务”。外界对这些微服务是不可感知的,但应用内服务间相互通讯。好比我司有各类运维服务和计划执行服务:
现在各大公司成败在于 “如何很好地管理数据”,在应用到达必定规模时规范数据流程。通常来讲有:加工数据、存储数据和分析数据,这三个步骤:
还有一个步骤没有在架构图中绘出:从应用和服务运维数据库中把数据导入数据仓库。例如在我司,咱们每晚都会把各个服务的数据存到 AWS Redshift,把核心业务的数据和用户交互行为的数据放在一块儿,提供给咱们的数据分析师一个总体化的数据集。
“云存储既简单,扩展性又好,方便用户在全网获取、存储、分享数据” —— AWS 云存储服务。任意在本地文件系统存储的文件,你均可以经过云存储存取,并用 HTTP 协议经过 RESTful API 访问并交互。Amazon S3 提供了目前最流行的云存储,我司在其上普遍存储各类东西,从多媒体素材、视频、图片、音频,到 CSS、Javascript 乃至用户行为数据等等。
CDN 指的是内容分发网络,该技术提供一种素材服务,好比存储静态 HTML,CSS,Javascript 和图片。从全网获取这些静态素材比从单个源服务器获取要快的多。它的工做原理是将内容分布在世界各地的边缘服务器上,而不是仅仅放在一个源节点上。好比说,下图中一个西班牙的用户访问某个源节点位于纽约的网站,可是页面的静态素材经过英国的 CDN 边缘服务器载入,这样就避免了冗余的跨大西洋的 HTTP 请求,提快了访问速度。
这篇文章 更详细解释了为何使用 CDN。总的来讲,网络应用可使用 CDN 来存储诸如 CSS、Javascript 和图片视频等素材,甚至静态 HTML 网页。
以上即是网络应用架构基础课的所有内容,但愿这篇文章对你有帮助。接下来我还会发布进阶课的文章,详细研究上述的某些组件。
若是发现译文存在错误或其余须要改进的地方,欢迎到 掘金翻译计划 对译文进行修改并 PR,也可得到相应奖励积分。文章开头的 本文永久连接 即为本文在 GitHub 上的 MarkDown 连接。
掘金翻译计划 是一个翻译优质互联网技术文章的社区,文章来源为 掘金 上的英文分享文章。内容覆盖 Android、iOS、前端、后端、区块链、产品、设计、人工智能等领域,想要查看更多优质译文请持续关注 掘金翻译计划、官方微博、知乎专栏。