人人享有的建筑

2025-05-24

人人享有的建筑

有人说了可怕的建筑这个词,而你不是建筑师?

当你只是想在网页上放个小部件,却有人质疑你对计算复杂性的理解时,你会害怕吗?
不必担心——它可能远没有你想象的那么复杂。

架构向来以难以理解、难以触及和“硬计算机科学”而闻名。你遇到的大多数软件架构,无论是中级还是 Web 规模的 Web 应用,都惊人地相似。
我们将在这本面向非架构师和 Web 程序员的简短架构入门指南中,介绍一些基础知识、一些专业术语以及你可能随处可见的一些架构模式。

网络服务器到底是什么?

好吧,让我们从基础开始。“网络”,或者用它滑稽而过时的完整敬语“万维网”,只是一堆连接到互联网的计算机。网络是一系列描述如何从这些连接的计算机中检索“资源”(也就是网页)的约定。

长话短说,“Web 服务器”实现了“HTTP 协议”——一系列可以发送给远程计算机的命令——让你可以发出“嘿,电脑,把那个文档发给我”。如果这听起来很熟悉,那是因为你的 Web 浏览器就是这样工作的。

当您www.my-awesome-website.com在浏览器中输入内容时,计算机上运行的代码会生成一个“http 请求”,并将其发送到与您在地址栏中输入的 URL(即网站地址)关联的 Web 服务器。

所以,Web 服务器——运行在远程计算机上的程序,连接到互联网,监听请求并在收到请求时返回数据。它能够正常工作本身就是一个小奇迹,它建立在 DNS(将 my-awesome-website.com 转换为 IP 地址的工具)以及大量的网络、路由和交换之上。除非你深入研究,否则你可能不需要真正了解这些内容。

市面上有大量的通用 Web 服务器 - 但实际上,您可能只会看到 Apache、NGINX 和 Microsoft IIS 的混合,以及一些开发堆栈特定的 Web 服务器(Node.js 可以自行服务,C# 的 ASP.NET CORE 和 Kotlin 的 HTTP4K 等也可以)。

HTTP 是如何工作的?它是一种架构吗?

如果您曾经做过任何 Web 编程,那么您可能至少对 HTTP 有所了解。
它是“超文本传输​​协议”(Hyper Text Transfer Protocol)的缩写,也是浏览器与 Web 服务器通信时所使用的协议。让我们来看一个简单的原始 HTTP“请求消息”:

GET http://www.davidwhitney.co.uk/ HTTP/1.1
Host: www.davidwhitney.co.uk
Connection: keep-alive
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64…
Accept: text/html,application/xhtml+xml,application/xml;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: en-GB,en-US;q=0.9,en;q=0.8

HTTP 的基础知识很容易掌握——它有一个强制性的“请求行”——这是第一部分,包含一个动词(最常见的是 GET、POST、PUT 和 HEAD 之一)、URL(网址)和协议版本 (HTTP/1.1)。
然后是一堆可选的请求标头字段——也就是所有其他内容——可以将其视为您向 Web 服务器提交的关于您的额外信息。标头之后是一行空行和一个可选的正文。
这就是 HTTP/1.1。到这里就完成了。服务器将以类似的格式进行响应。

HTTP/1.1 200 OK
Cache-Control: public,max-age=1
Content-Type: text/html; charset=utf-8
Vary: Accept-Encoding
Server: Kestrel
X-Powered-By: ASP.NET
Date: Wed, 11 Dec 2019 21:52:23 GMT
Content-Length: 8479


<!DOCTYPE html>
<html lang="en">...

第一行是状态码,后面是头部信息和响应主体。就是这样。Web 服务器可以根据请求的内容,向你发送任何它想发送的内容,而发出请求的软件必须能够解析响应。请求正确的内容并做出恰当的响应,这其中有很多细微的差别,但基本原理是相同的。

Web 是 REST 设计模式的一种实现,REST 的全称是“表述性状态转移”。你会经常听到人们谈论 REST——它最初是由 Roy Fielding 在他的博士论文中定义的,但更重要的是,它描述了当时 HTTP/1.0 的工作方式,并在 Fielding 开发 HTTP/1.1 的同时被记录下来。

所以 Web 默认是 RESTful 的。REST 描述了 HTTP 的工作方式。

简而言之?唯一可寻址的 URI(网址),返回某台机器上保存的某些状态(网页、文档、图片等)的表示。
根据客户端请求的内容,该状态的表示可能会有所不同。

这就是 HTTP、REST 和架构风格的结合体。

Web 应用程序的架构是什么样的?

您可以按照多种不同的架构模式编写优秀的软件,但大多数人只坚持少数几种常见的模式。

“MVC 应用”

MVC(模型视图控制器)是一种简单的设计模式,它将应用程序的处理逻辑与呈现逻辑解耦。MVC 真正成为人们关注的焦点,是因为 Ruby on Rails 的成功(尽管这种模式比 Ruby on Rails 早了几十年)。大多数人说“MVC”时,实际上指的是“Rails 风格”的 MVC 应用,其中代码被组织到几个不同的目录中。

/controllers
/models
/views

Rails 推广了“约定优于配置”的理念,将所有这些东西连接在一起,同时还引入了“路由”和合理的默认值。ASP.NET MVC 几乎全盘照搬了 Rails 的理念,之后几乎所有 MVC 框架也都效仿了它。

广义上讲,默认情况下,如果你有一个类似这样的 URL,

http://www.mycoolsite.com/Home/Index

MVC 框架会使用其“路由”(定义查找内容的规则)尝试在 controllers 目录中查找“HomeController”文件或模块(取决于你的编程语言)。其中可能存在一个名为“Index”的函数。该函数会返回一个模型(一些数据),该模型由“视图”(views 文件夹中的 HTML 模板)渲染。

所有不同的框架都以略微不同的方式实现这一点,但核心思想保持不变——通过控制器将功能组合在一起,并具有返回数据页面和处理来自网络的输入的功能。

“带有 API 的单页应用程序

SPA 非常常见,它被 Angular、React 和 Vue.js 等客户端 Web 框架所推广。这里唯一的区别在于,我们将 MVC 应用的大部分工作转移到了客户端。

这里有几个不同的风格——客户端 MVC、MVVM(模型-视图-视图-模型)以及函数式响应式编程(FRP)。乍一看,这些区别可能看起来很微妙。

Angular 是一个客户端 MVC 框架 - 遵循“模型、视图和控制器”模式 - 只不过现在它在用户的 Web 浏览器中运行。

React——函数式反应式编程的一种实现——它更灵活一些,但更关注数据中的状态变化事件——通常使用像 Redux 这样的事件存储来存储其数据。

MVVM 在单页应用程序中同样常见,其中提供数据(模型)和 UI(视图模型所服务)之间存在双向绑定。

在所有这些客户端繁重的 JavaScript 框架之下,通常是一个看起来与“MVC 应用程序”几乎没有区别的 API,但不是返回预渲染的页面,而是返回客户端“绑定”其 UI 的数据。

“静态网站托管在 CDN 或其他非托管服务器上”

或许情况有些不同——20多岁的时候,静态网站又开始复苏。想想看,如果一直在电脑上运行代码,网站要扩展以应对高流量是很困难的。

我们花了数年时间构建相对复杂且性能较差的内容管理系统(如 WordPress),这需要花费大量金钱和硬件来扩展。

作为应对措施,将内容渲染移至“开发时”进行,具有明显的成本和可扩展性优势。即使没有代码运行,它也不会崩溃!

因此,静态站点生成器变得越来越流行——通常允许你使用常规的前端 Web 开发栈,然后使用构建工具生成所有文件,然后打包并分发到简单的 Web 服务器或 CDN。参见 Gatsby、Hugo、Jekyll 和 Wyam 等工具。

“别的”

Web 应用程序遵循其他原型 - 转译框架(WebAssembly 中的 C# Blazor 和 Kotlin 的 javascript 编译目标)呈缓慢上升趋势 - 但随着当今主流 javascript 框架的广泛流行,它们都试图很好地配合。

我为什么要选择其中一个而不是另一个?

这个问题比较棘手。说实话,这主要取决于个人喜好,而且它们都是构建 Web 应用程序的非常合适的方法。

服务器渲染的 MVC 应用非常适合低交互性的网站。尽管高保真前端正成为一种趋势,但仍有大量网站仅仅是网站,而非 Web 应用,而庞大工具链的复杂性成本通常不值得投入。

现在几乎默认,任何需要高保真用户体验的应用,都可能是 React、Angular 或 Vue 应用。这些编程模型非常适合响应式用户体验,如果你不使用这些模型,最终你很可能需要自己重新设计它们。

静态网站?非常适合博客、营销微网站、内容管理系统,以及任何以实际内容为最有价值互动的网站。它们扩展性好,基本不会崩溃,而且运行成本低。

HTTP API、Rest、GraphQL、前端后端

你最终肯定会与 API 进行交互,虽然有很多术语让这些概念听起来很复杂,但核心其实很简单。
你使用或构建的大多数 API 都是“REST 式”的。

您将发出与浏览器相同类型的“HTTP 请求”,大多数情况下返回 JSON 格式的响应(有时也返回 XML 格式)。您可以将这些 API 描述为 JSON-RPC 或 XML-RPC。

早在千禧年之交,人们就曾推动“SOAP”(简单对象访问协议)API 的标准化,虽然这带来了很多好东西,但人们发现 XML 难以阅读,因此它们的受欢迎程度逐渐下降。

具有讽刺意味的是,许多在 SOAP 中解决的问题(一致的消息信封格式、安全考虑、模式验证)随后必须在 JSON 之上使用新兴的开放标准(如 Swagger(现为 OpenAPI)和 JSON:API)进行“重新解决”。

我们擅长重新发明网络上已有的东西。

那么,是什么让 REST API 成为 REST API,而不是 JSON-RPC?

我很高兴你没有问。

REST 的核心在于对通过 HTTP 协议对资源进行的操作进行建模。如果你想深入了解 REST 为何是一种优秀的架构风格,可以阅读 Jim Webber 的一本好书《Rest in Practice》(Rest 实践)。REST 确实是一种优秀的架构风格,但许多现代人对 REST 的否定之声都相对缺乏根据,与之前 SOAP 的遭遇并无太大不同。

人们真正关心的是什么是 REST,什么不是 REST,而如果你把 JSON-RPC 描述成 REST,可能会让真正关心 REST 的人感到不快。JSON-RPC 是理查德森成熟度模型的“0 级”——该模型描述了 REST 设计的特征。不必太过担心,因为只需做几件事,你就能构建出符合 REST 规范、合理且优秀的 JSON-RPC。

首先,你需要正确使用 HTTP 动词,GET 用于获取数据(并且不要使用副作用),POST 用于“执行操作”,PUT 用于“创建状态由客户端控制的内容”。
之后,确保将 API 组织成逻辑上的“资源”——你的核心领域概念是“客户”、“产品”、“目录”等等。

最后,使用正确的 HTTP 响应代码与您的 API 进行交互。

您可能不会使用“超媒体作为应用程序状态的引擎”,但您可能会做得足够好,以至于没有人会来讨好您。

只需适度操作,你就能享受到完全 RESTful API 的诸多优势——资源可以通过 HTTP 导航,文档可以缓存,API 也能在大多数常用工具中运行。使用 swagger 或 OpenAPI 库生成 schema,你做的事情和大多数人做的差不多。

但是我在 hackernews 上看到 REST sux 和 GraphQL 才是可行之道?

是的,我们也都读过那篇文章。

GraphQL 有点让人困惑,它既是一种查询语言,又是一个 HTTP API 标准,还是一个 Schema 工具。随着客户端密集型 Web 应用的激增,GraphQL 通过将哪些数据应该返回给客户端的定义有效地推入到客户端代码本身,获得了广泛的欢迎。

这种“前端查询”式的方法并非首次被提出,而且很可能也不会是最后一次。GraphQL 与以往方法(尤其是微软的 OData)略有不同的一点是,其类型和查询是通过服务器端的解析器代码实现的,而不是直接映射到某个 SQL 存储。

这很有用,原因有两个:这意味着 GraphQL 可以成为您域中一堆不同 API 上的单一 API;它通过允许客户端指定他们试图返回的数据子集,解决了 REST API 中相当常见的“过度获取”问题;它还可以充当某种反腐败层,防止对底层存储进行无限制的访问。

GraphQL 还被设计为您的 Web 或移动应用程序对话的单一连接点,这对于优化性能非常有用 - 简单来说,一个 API 通过网络以较低的延迟调用下游 API 比您的移动应用程序(高延迟)调用所有内部 API 更快。

GraphQL 实际上只是一种智能且有效的方法来架构你的 API,并提供一个 BFF – 即前端的后端,而不是永远最好的朋友 – 它可以快速改变。

最好的朋友?最好的朋友到底是什么?

想象一下这个问题——你在 MEGACORP 工作,那里有一百个团队或小队(你不记得了,他们每隔一周重新命名一次命名法)——每个团队或小队负责一组微服务。

你是一名 Web 程序员,只想完成一些工作,而新版本刚刚上线了一项新功能。于是
你阅读了文档。

该文档描述了如何协调多个 API 之间的调用,所有调用都需要 OAuth 令牌和声明,最终您将获得闪亮的新功能。

所以,当你编写 API 调用时,你意识到不断地向客户端发送和接收数据所花费的时间,更不用说必须检查所有数据是否安全传输的安全风险,会让你的速度停滞不前。
这就是为什么你需要一个永远的好朋友。

抱歉,前端是后端。

BFF 是一个服务于单个应用程序(确切地说,只服务于单个应用程序)的 API。它将内部域名(MEGACORPS BUSINESS)转换为其服务应用程序的内部语言。它负责处理诸如身份验证、速率限制等您不想重复执行的操作。它减少了与服务器的不必要的往返,并将数据转换为更适合其目标应用程序的格式。

将其视为一个 API,仅适用于您的应用程序,由您控制。

GraphQL 和 OData 等工具非常适合 BFF。GraphQL 与现代 JavaScript 驱动的前端配合得特别好,而 Apollo 和 Apollo-Server 等优秀工具则可以通过批量处理请求来优化这些调用。

它对于前端开发人员来说也相当友好——查询和模式与 json 非常相似,并且它让你的堆栈“一路向下”保持 javascript,而不受某些遥远的后端团队的束缚。

您可能会看到的其他事物以及原因

现在我们了解了 Web 服务器、Web 应用和 API,那么现代 Web 编程肯定不止这些吧?以下是你可能最常遇到的问题。

负载均衡

如果你的网站足够幸运,流量很大,但又不幸没有使用平台即服务提供商(稍后会详细介绍),那么你迟早会遇到负载均衡器。别慌。负载均衡器使用过时的语言,通常由脾气暴躁的系统管理员操作,或者只是运行 NGINX 的副本。

负载均衡器所做的就是接受应用程序的 HTTP 请求(或来自应用程序的请求),选择不太繁忙的服务器,然后转发请求。

你可以让负载均衡器做各种疯狂的事情,而这些事情你可能不应该用负载均衡器来做。但人们仍然会尝试。

您可能会看到负载均衡器将软件中特别“热路径”的负载均衡到专用硬件池上,以尝试确保其安全或将其与故障隔离。您还可能会看到负载均衡器用于为您处理 SSL 证书——这称为 SSL 终止。

分布式缓存

如果一台计算机可以在内存中存储一​​些数据,那么很多台计算机就可以存储……更多的数据!

分布式缓存由“Memcached”率先推出,最初于 2003 年编写,用于扩展博客平台 Livejournal。当时,Memcached 帮助 Livejournal 在相对较少的服务器上共享所有最新条目的缓存副本,从而大大减少了同一硬件上的数据库服务器负载。

内存缓存用于存储计算量“大”、耗时或只需在运行服务器软件的所有不同计算机上保持一致的结果。它会略微增加网络延迟,从而使应用程序可用的内存总量等于所有服务器可用内存总量的总和。

分布式缓存对于防止“缓存踩踏”也非常有用——当非分布式缓存失败时,所有客户端都会重新计算缓存数据,但通过共享内存,完全缓存失败的几率会大大降低,即使发生这种情况,也只会重新计算一些数据。

分布式缓存无处不在,所有主要托管服务提供商都倾向于支持 memcached 或 redis 兼容(阅读:您可以使用 memcached 客户端库来访问它们)管理的缓存。

理解分布式缓存的工作原理非常简单——添加新项时,生成的键(用于检索该项的键)包含将数据存储在缓存中的计算机的地址或名称。在分布式缓存集群中的任何一台计算机上生成键都会生成相同的键。

这意味着当使用与缓存交互的客户端库时,它们知道必须调用哪台计算机来检索数据。

像这样分解大型共享内存池是明智之举,因为它使得查找速度变得异常快——没有一台计算机需要扫描大量内存来检索项目。

内容分发网络 (CDN)

CDN 是由世界各地的其他人运营的网络服务器。您将数据上传到 CDN,他们会将您的数据复制到其所有“边缘”(这是一个比较傻的术语,其实就是“复制到他们在全球运行的所有服务器”),这样当有人请求您的内容时,DNS 响应会返回一个距离他们较近的服务器,这样他们获取内容的时间就会快得多。

CDN 的运营机制比实际使用要复杂得多——但如果您有大量静态资源(例如图片!)或大型文件(例如视频、大型二进制文件!),CDN 是一个不错的选择。CDN 还能有效降低服务器的整体负载。

卸载到 CDN 是以极低的成本获得额外性能的最简单方法之一。

让我们谈谈设计模式!这才是真正的建筑

“Design patterns are just bug fixes for your programming languages”

人们谈论设计模式,仿佛它们是什么圣杯——但设计模式的本质,是人们经常遇到的问题的答案,并且存在一种公认的解决方法。如果我们的语言、工具或框架更优秀,它们或许就能帮我们完成这项工作(事实上,随着时间的推移,更新的语言特性和工具往往会淘汰设计模式)。

让我们快速浏览一下一些非常常见的:

  • MVC –“分离数据模型、UI 代码和业务逻辑,以免混淆”
  • ORM – “对象关系映射” – 使用映射库和配置规则,管理内存中对象到关系存储的存储。不要混淆对象和它们的存储位置。
  • 活动记录– “所有对象都应该能够自我保存,因为这些只是 Web 表单,谁在乎它们是否与数据库绑定!”
  • 存储库— “您所有的数据访问都在此类中 — 与其交互以加载内容。”
  • 装饰器——“在对象、类或函数周围添加或包装‘装饰器’,以添加缓存或日志记录等常见行为,而无需更改原始实现。”
  • 依赖注入——“如果你的类或函数依赖于某些东西,那么调用者(通常是你正在使用的框架)有责任提供这种依赖关系”
  • 工厂– “将创建此类产品所需的所有代码放在一个地方,且仅放在一个地方”
  • 适配器– “使用适配器来连接那些原本无法协同工作的事物——将内部数据表示转换为外部数据表示。例如,将 Twitter 的回复转换为 YourSocialMediaDataStructure。”
  • 命令——“每个独立的动作或请求都在一个地方实现”
  • 策略——“定义多种可以互换的方法”
  • 单例——“我的整个应用程序中只有一个这样的对象”。

以上只是一些你会听到的模式术语的不完全列表。设计模式本身并没有什么特别之处,它们只不过是 StackOverflow 上一个广为接受且流行的答案的 1990 年代版本。

微服务架构

微服务架构只是面向服务设计的“第三次浪潮”。

他们从哪里来?

20世纪90年代中期,“COM+”(组件服务)和SOAP非常流行,因为它们通过将组件拆分成小组件,降低了部署风险,并提供了一种标准且相对简单的跨进程通信方式。这导致了分布式系统“3层”架构以及后来“n层”架构的流行。

N-Tier 实际上是“拆分数据层、业务逻辑层和表示层”的简写。这种方法对某些人来说很有效,但也存在一些问题,因为系统的水平切片通常需要修改每一层才能完成完整的更改。这种连锁反应不利于可靠性。

随后,产品供应商也参与其中,SOAP 变得复杂且不再流行,这促使人们走向“第二波浪潮”——游击式 SOA。其设计与 SOA 类似,只是少了些繁琐的仪式感,采用了更完全垂直的切片,并减少了供应商中间件的使用。

这导致了更小、更灵活的服务的激增,与此同时,Netflix 也在推广 hystrix——他们的延迟和容错系统平台。

第三波 SOA 浪潮,被称为微服务架构(由 James Lewis 和 Martin Fowler 提出),非常流行,但可能不太为人所理解。

微服务应该是:小型、独立可用、独立版本控制、独立可交付的服务,执行特定领域的功能或操作。

微服务通常是:脆弱的、相互依赖的、目光短浅的服务,充当 HTTP 上的数据访问对象,经常以多米诺骨牌般的方式失败。

良好的微服务设计遵循一些简单的规则

  • 基于角色/操作,而不是以数据为中心
  • 始终拥有自己的数据存储
  • 通过外部接口或消息进行通信
  • 一起变化、相互依存的东西,其实是同一件事
  • 所有服务都具有容错能力,并且能够承受其依赖项的中断

不具备这些特质的微服务很可能只是秘密的分布式单体应用。没关系,很多人都在大规模地运营分布式单体应用,但你迟早会感受到痛苦。

六边形架构

现在这听起来就像是一些“真正的建筑TM”

六边形架构,也称为“端口和适配器”模式 - 由 Alistair Cockburn 定义,是“真实应用架构”建议中较好的一个。

简而言之,您的所有逻辑、业务规则、特定领域的内容都以与您的框架、依赖项、数据存储、消息总线、存储库或 UI 无关的形式存在。

所有这些“外部的东西”都会“适应”您的内部模型,并在需要时注入。

那到底是什么样子的呢?所有逻辑都包含在文件、模块或类中,无需依赖框架代码、粘合剂或外部数据访问。

为什么?因为这意味着你可以独立地测试所有内容,而不会受到 Web 框架或某些有问题的 API 的干扰。保持逻辑清晰,避免所有这些外部问题,是设计应用程序的安全方法。

还有第二种非常流行的方法,被称为“十二要素应用程序”——它主要具有相同的设计目标,并附加了一些规定性规则。

缩放

如果您尝试自己做的话,扩展会很困难,所以绝对不要尝试自己做。

如果可以避免,请使用供应商提供的云抽象,例如 Google App Engine、Azure Web Apps 或 AWS Lambda,并启用自动缩放支持。

考虑将你的 API 放在无服务器堆栈上。抽象程度越高,扩展就越容易。

传统观点认为“横向扩展是唯一划算的选择”,但许多成功的公司都成功地利用少量大型机器或虚拟机实现了纵向扩展。横向扩展还能带来其他好处(通常与地理分布相关,或跨可用区弹性),但即使最终只剩下“更强大的”选项,也不必感到沮丧。

分布式系统的架构模式

构建分布式系统比开发单个应用程序更难。虽然没人真正谈论过这个问题,但事实确实如此。当你把所有东西都分成小块时,更容易出现故障,但如果处理得当,彻底崩溃的可能性就会降低。

有几件事情总是有用的。

到处都是断路器

熔断是一种非常有用的分布式系统模式,可以将传出连接建模成电路。通过测量任何给定电路上的调用成功率,如果调用开始失败,就可以“熔断保险丝”,将出站请求放入队列,而不是直接发送那些你知道会失败的请求。

过了一会儿,让一个请求流过电路(“半开”状态),如果成功,则再次“关闭”电路并让所有排队的请求流过。

断路器是一种非凡的方法,可以确保您在可能出现故障时不会发生故障,并且还可以保护陷入困境的服务免受您的呼叫的打击。

当您意识到您拥有所调用的 API 时,您会更加感谢您的断路器。

幂等性和重试

所有断路器的免费设计模式——您需要确保将所有出站连接包装在重试策略和退避策略中。

这是什么意思?你应该将你的调用设计成在重复提交时是非破坏性的(幂等性),并且如果你的调用配置为在发生错误时重试,那么当重复发生故障时,你可能需要稍微回退一点(即使不是指数级的)——至少给你调用的东西一些时间恢复。

舱壁

舱壁的设计灵感来源于潜艇上的实体舱壁。当潜艇船体的一部分受损时,舱壁就会关闭,防止潜艇其他部分进水。这是一个很酷的比喻,它的核心就是隔离。

可以为软件的各个部分保护保留的资源、容量或物理硬件,以便系统某个部分的中断不会波及到其他部分。

您可以为多线程系统中的某些调用设置最大并发限制,明智地使用超时(最好是超时,而不是锁定和失败),甚至为重要的业务功能(如结帐或付款)保留硬件或容量。

具有重放/消息日志的事件驱动架构

基于事件/消息的架构通常具有弹性,因为根据设计,对它们的入站调用并非同步的。通过使用缓冲在队列中的事件,您的系统可以支持中断、扩展和缩减以及滚动升级,而无需任何特殊考虑。它的正常操作模式是“从队列读取”,并且在特殊情况下也不会改变。

当与竞争消费者模式(多个处理器竞争使用来自队列的消息)相结合时,使用队列和事件驱动架构可以轻松扩展以获得良好的性能。

我需要 Kubernetes 吗?

不,您可能不会遇到与 Google 相同的扩展问题。

随着 Docker 和容器的普及,那些提供“近乎平台化”的基础设施即服务抽象的东西被大肆炒作。这些都非常昂贵且费力。

如果您有能力管理它,请尽可能使用最接近纯托管平台的平台。Azure 应用服务、Google App Engine 和 AWS Lambda 将为您的程序员带来数倍的生产力提升。它们在生产环境中更易于操作,并且更易于解释和支持。

Kubernetes(通常缩写为 k8s,以及其由诸如 helm 和 flux 等名称深奥的附加组件组成的出色生态系统)需要一支全职运营团队来运营,即使在 EKS/AKS/GKS 上的“托管供应商模式”下,学习曲线也比其他替代方案陡峭得多。

Heroku?应用服务?应用引擎?这些都是你自己就能在几分钟到几个小时内为生产环境设置的。

你会在各个地方看到使用 Kubernetes 推动“云中立”解决方案的压力——但这不过是骗人的把戏。云中立仅仅意味着你需要永久地支付云迁移的成本(维护抽象,将你的流程与供应商特有的有用功能隔离),而不是在(极不可能的)更换云供应商的情况下。

负责任地使用技术包括使用最适合您所遇到的问题和规模的技术。

合理的建议

永远做尽可能简单的事情。架构是有成本的,就像所有抽象一样。在深入研究一些复杂的架构模式之前,你需要确保自己能够获得收益。

通常,最好的架构是最简单的并且最容易改变的。

文章来源:https://dev.to/david_whitney/architecture-for-everyone-1b0h
PREV
GraphQL 初学者指南
NEXT
观点:建筑师 VS 工程师 VS 开发人员