写点什么

简单软件架构的一些好处

  • 2022-03-29
  • 本文字数:3806 字

    阅读完需:约 12 分钟

简单软件架构的一些好处

本文最初发表于 Wave 官网,经原作者 Dan Luu 授权,InfoQ 中文站翻译并分享。

 

Wave 是一家价值 17 亿美元的公司,拥有 70 名工程师,该公司的产品是一款加减数字的 CRUD 应用程序。为了与此保持一致,我们的架构是一种标准的 CRUD 应用架构,基于 Postgres 的 Python 单体架构。先从一个简单的架构入手,然后尽量用最简单的方式来解决问题,这使得我们的业务范围能够扩大到这种规模,而工程师们大多专注于为用户提供价值的工作。

 

Stackoverflow 扩大了单体的规模,取得了良好的效果(2013 年的架构/2016 年的架构),最后以 18 亿美元的价格被收购。如果我们关注的是流量而非市场市值,那么 Stackoverflow 就是互联网上流量最高的前 100 个网站之一(关于其他许多建立在单体之上的有价值的公司的案例,请参考这条 Twitter 主题的回复。我们没有很多网络流量,因为我们是一个移动应用,但 Alexa 还是将我们的网站列在了前 75000 名,尽管我们的网站基本上只是人们查找 APP 的一种途径,而大部分人并没有从我们的网站中获得这些 APP)。

 

有些应用的要求,使得在一个枯燥的数据库中构建出一个简单的单体应用是不可能的,但对大部分应用来说,即便是在前 100 个网站的流量水平上,计算机的运行速度也足以满足使用简单的架构来提供服务,通常创建简单的架构比复杂的架构更便宜、更容易。

 

尽管简单的架构具有不合理的有效性,但是大部分的新闻报道都是围绕着复杂的架构展开的。举例来说,在最新的通用技术会议上,就有六场演讲讨论了怎样构建或处理基于微服务的复杂结构的负面影响,却没有一场演讲讨论如何构建简单的单体。甚至关于量子计算的演讲也有一场。更大规模的会议也一样;最近旧金山的一次以企业为导向的会议上,关于处理复杂架构的演讲,场次就高达两位数;却没有一场关于如何构建简单的单体的演讲。我上次去的那次会议给我留下了很深的印象,就是许多公司的员工,他们的应用程序规模很小,本来可以用简单的架构就能完成,但是他们使用的都是会议圈子和网络上流行的最新、最复杂的技术。

 

我们的架构是如此简单,以至于我都懒得去做一个架构图。我会讨论我们所做的使一切乏味的事。

 

我们目前使用的是乏味的、同步的 Python,这意味着,当我们的服务器进程在等待 I/O 时被阻塞,比如网络请求。我们之前尝试过 Eventlet,这是一种理论上能使我们从 Python 中获得更高效率的异步框架,但是我们碰到了大量的 Bug,我们觉得,等待事件的 CPU 和延迟成本,都不值得我们为处理 Eventlent 问题而承担操作上的痛苦。其他知名的 Python 框架也有类似的情况,但是大规模使用它们的用户往往也会报告大规模使用这些框架带来的严重后果。使用同步的 Python 代价很高,因为我们需要支付 CPU 的费用,而在网络请求期间,CPU 除了等待之外什么都不做,但是,现在,我们每个月只能处理几十亿个请求,因此,即便是使用 Python 这种缓慢的语言,也要支付公共云的零售费用,这样的成本也很低。我们工程团队的成本完全决定了我们所运营的系统的成本。

 

我们将长时间运行的任务(我们不想让响应阻塞)分配到一个队列中,而不是承担使我们的单体异步的复杂性。

 

我们不能像我们想的那样无聊的地方,就是我们的内部数据中心。当我们只在塞内加尔和科特迪瓦运营时,我们完全是在云端中运营,但是,随着我们的业务范围扩大到乌干达(以及未来更多的国家/地区),我们不得不拆分后端,部署到当地的内部数据中心,以遵守当地的数据存储法律和法规。这并非一项简单的操作,但正如那些在面向服务的复杂架构中做过相同工作的人所知道的那样,这种操作要比使用复杂的服务导向的架构要简单得多。

 

另外一个方面是我们必须研发的软件,而非购买。刚起步时,我们强烈地倾向于购买软件,而非研发软件,因为一个由少数工程师组成的团队无法承担研发软件的时间成本。虽然“购买”这一选项,通常会给你提供一些无效的工具,但这在那个时候是正确的选择。如果我们不能说服供应商修复 Showstopper 错误,而这个错误对我们至关重要,那么在这种情况下,构建更多的自己的工具,并且在更多的方面保留内部的专业知识,这的确是很有意义的,但这与公司应只选择“构建”其核心能力的标准建议相悖。这种复杂性的大部分都是我们不愿意承担的,但是对于某些类别的产品,即便是进行了相当广泛的研究,我们仍然找不到供应商能够提供适合我们的产品。公平地说,我们的供应商需要解决的问题比我们需要解决的问题复杂得多,因为我们的供应商承担着为每个客户解决问题的复杂性,而我们只需要为一个客户解决问题,那就是我们自己。

 

译注:Showtopper 错误是导致执行停止并基本上变得无用的硬件或软件错误。必须修复此严重错误,以使开发过程进一步进行。

 

我们在运营的头几个月里,就犯了一个错误,就是没有仔细地界定数据库事务的边界,这在今天已经付出了一定的代价。在 Wave 的代码库中,SQLAlchemy 数据库会话是一个请求全局变量;在任何时候访问 DB 对象的属性时,它都隐含地开始一个新的数据库事务,并且 Wave 代码库中的任何函数都可以在会话上调用 commit,使其提交所有挂起、的更新。这使得我们很难控制数据库更新发生的时间,从而增加了出现微妙的数据完整性错误的概率,并且很难依靠数据库来构建类似于幂等键(idempotency key)或事务性暂存的作业流失。这样做还会增加我们意外地持有打开的长时间运行的数据库事务的风险,这可能使模式迁移操作变得困难

 

一些我们不确定的选择(因为我们在考虑更改,或建议其他从零起步的团队考虑另一种方式)有:使用 RabbitMQ(就我们的目的而言,Redis 可能同样适用于任务队列,只需要 Redis 就可以减轻操作负担);使用 Celery(这对于我们的用例来说过于复杂,并且已经出现了好几次故障,比如在版本升级过程中出现了向后兼容性问题);使用 SQLAlchemy(它使开发人员难以理解自己的代码将会产生怎样的数据库查询,从而导致各种难以调试的情况,同时也带来了不必要的操作痛苦,尤其是与上面提到的数据库事务边界的观点有关);以及使用 Python(由于我们的创始 CTO 的技术背景,这是最初的正确选择,但其并发支持、性能和广泛的动态性使我们质疑它是否是大规模后端代码库的正确选择)。以上所有这些都不是主要的错误,而且对于一些(例如 Python) 来说,缺陷已经很少了,因此,与投资到理论上更好的迁移相比,我们将花费更少的费用去进行更多的维护,但如果我们现在就从头编写一套类似的代码库,那么我们就会认真考虑,它们是否正确的选择。

 

在某些方面,我们很满意能做出这样的选择,虽然这些听上去并不像是最简单可行的解决方案,比如我们的 API,我们使用 GraphQL;我们的传输协议,我们有一段时间使用自定义协议;还有我们的主机管理,我们使用 Kubernetes。对于我们的传输协议,我们曾经使用了一种基于 UDP 的自定义协议,并带有 SMS 和 USSD 后备功能,这也是这场讲座所提到的性能理由。在 HTTP/3 发布后,我们已经能够用 HTTP/3 来替代我们的自定义协议,通常我们只需要 USSD 就可以解决像最近在马里发生的互联网关闭这样的事件)。

 

对于 GraphQL 的使用,我们相信其优点多于缺点:

 

优点:

 

  • 精确返回类型的自文档化;

  • 精确返回类型的代码生成使得客户端更加安全;

  • GraphiQL 交互式探索器是生产力的一个胜利;

  • 我们的各种应用(用户应用、支持应用、Wave agent 应用等)大多可以共享一个 API,从而减少复杂性。

  • 可组合的查询语言允许客户端在一次数据包往返中准确获取它们需要的数据,而无需建立大量的特殊用途的端点;

  • 避免了对什么算作 RESTful API 的无意义争论。

 

缺点:

 

  • 当我们采用 GraphQL 时,GraphQL 库并不是很好(基本的 Python 库是从 JavaScript 库中移植过来的,因此不是 Python 化的,Graphene 需要大量的模板,Apollo-Android 生成的优化代码非常烂)。

  • 默认的 GQL 编码是冗余的,而且由于很多客户端的带宽较低,所以我们非常关心限制大小。

 

对于 Kubernetes,我们之所以选择 Kubernetes,是因为我们清楚,如果业务成功(确实如此),而且我们不断扩张,我们最终会扩张到那些要求我们在该国内运营服务的国家。各国之间的具体规定各不相同,但是我们在非洲的主要市场上拓展了业务,这就要求我们在该国运营我们的 “主要数据中心”,还有其他一些规定,例如,要求我们能够将故障转移到该国的数据中心。

 

电信集成是我们无法回避的复杂性的一个方面。从理论上讲,我们将使用 SaaS SMS 提供商来完成这一切,但是,非洲各大 SaaS SMS 提供商的业务并没有遍及整个非洲,因此在那里使用这些服务的费用都让人望而却步。如果我们利用 SaaS SMS 提供商来解决我们所有的短信需求,那么以前的那些说工程师的薪酬成本如何主导我们系统成本的说法是站不住脚的;提供电信集成服务的团队为此付出了数倍的代价。

 

通过将应用架构尽量简化,我们就可以将复杂性(以及人力)预算用于有利于业务发展的领域。如果没有足够的理由去提高复杂性,那么我们就可以基于尽可能简单地做事的这一想法,用少量的工程师,创建一个规模不小的业务,虽然我们所经营的非洲金融业务通常被视为难以涉足的业务,我们会在以后的文章中谈到(我们的早期和最有帮助的咨询顾问之一,他给我们提出的建议,对于 Wave 的成功非常关键,起初提出 Wave 是一个糟糕的商业点子,而创始人应该选择另一个,因为他预见到了许多潜在的困难)。

 

原文链接:

https://www.wave.com/en/blog/simple-architecture/index.html

2022-03-29 14:504471

评论 2 条评论

发布
用户头像
机翻的吧,一点都读不通顺
2022-03-30 11:43
回复
用户头像

微服务架构趋势下如何处理存量系统
https://xie.infoq.cn/article/3f9e2ea9e02ef60a90f7dac3d
2022-03-30 08:46
回复
没有更多了
发现更多内容

Java Agent场景性能测试分析优化经验分享

华为云开发者联盟

开发 华为云 java 华为云开发者联盟 企业号 3 月 PK 榜

Spring Boot是如何内嵌Tomcat的?原理剖析

Java tomcat Spring Boot

从ChatGPT的技术发展角度解析未来智能化的发展方向

加入高科技仿生人

人工智能 AI 低代码 智能化 ChatGPT

坚如磐石:TiDB 基于时间点的恢复(PiTR)特性优化之路丨6.5 新特性解析

PingCAP

TiDB

PHP中出现Cannot modify header information - headers already sent

ModStart

如何通过C#和VB.NET压缩PDF文档

Geek_249eec

C# .net PDF VB.NET

政企专属的IM即时通讯平台,促进团队安全沟通与协作

BeeWorks

国内“谁”能实现chatgpt,对MOSS、ChatYuan给出关键技术简评,一文带你深入了解宏观技术路线| 社区征文

汀丶人工智能

ChatGPT

软件开发,如何同时保证效率和质量?

飞算JavaAI开发助手

百度点石隐私计算平台与FATE开源框架实现互联互通

百度安全

人工智能 开源 联邦学习 开发

极狐GitLab DevSecOps 为企业许可证安全合规保驾护航

极狐GitLab

许可证 DevSecOps 极狐GitLab 安全左移 安全合规

Centos 环境搭建

流火

Linux centos Centos 7

1.基于Label studio的训练数据标注指南:信息抽取(实体关系抽取)、文本分类等

汀丶人工智能

数据标注 关系抽取 labelstudio 实体抽取

主题别名(Topic Alias)-MQTT 5.0新特性

EMQ映云科技

物联网 IoT mqtt 企业号 3 月 PK 榜 主题别名

国内“谁”能实现chatgpt,一文带你深入了解宏观技术路线| 社区征文

汀丶人工智能

ChatGPT

软件测试/测试开发 | 测试平台开发-前端开发之数据展示与分析

测试人

软件测试 自动化测试 测试开发 测试平台

瓴羊Quick BI提供移动端自助分析解决方案, 易于性高于 Fine BI、 Smart BI

流量猫猫头

大数据 数据分析

SVN vs Git 不是技术之争,而是生态之争

极狐GitLab

git svn DevOps 版本控制 极狐GitLab

博睿数据入选中国信通院《高质量数字化转型产品及服务全景图》

博睿数据

可观测性 智能运维 博睿数据 信通院 高质量发展

软件测试 | Vuetify框架

测吧(北京)科技有限公司

测试

软件测试 | ECharts简介与安装

测吧(北京)科技有限公司

测试

4道数学题,求解极狐GitLab CI 流水线|第4题:合并列车

极狐GitLab

ci DevOps pipeline runner 合并列车

该如何正确的中断一个线程的执行

华为云开发者联盟

开发 华为云 华为云开发者联盟 企业号 3 月 PK 榜

文件传输协议的五种安全文件传输替代方案

镭速

如何在服务端渲染fabric.js

ModStart

AI开发实践丨客流分析之未佩戴口罩识别

华为云开发者联盟

人工智能 华为云 华为云开发者联盟 企业号 3 月 PK 榜

还在头疼你的API,送你一个保姆级的API设计管理平台

华为云开发者联盟

云计算 开发 华为云 华为云开发者联盟 企业号 3 月 PK 榜

吹爆Alibaba自研的Spring全能笔记,建议人手一份!

小小怪下士

Java spring springmvc springboot

【2.24-3.3】写作社区优秀技术博文一览

InfoQ写作社区官方

热门活动 优质创作周报

简单软件架构的一些好处_大数据_Dan Luu_InfoQ精选文章