写点什么

可伸缩性原则

  • 2008-07-25
  • 本文字数:3234 字

    阅读完需:约 11 分钟

从最简单的水平来看,可伸缩性就是做更多的事情。更多的事情可以是响应更多的用户请求,执行更多的工作,或处理更多的数据。设计软件这件事本身是复杂的,而让软件做更多的工作也有其特有的问题。这篇文章针对构建可伸缩软件系统提出了一些原则和方针。

1. 减少处理时间

增加应用所做工作数量的一个方法就是减少完成单项工作所花费的时间。举例来说,减少处理一个用户请求所需的时间意味着你能在同样长的时间内处理更多的用户请求。这里有一些本原则适用的例子和一些可能的实现策略。

  • 并置(Collocation):通过并置数据和代码,减少因获取所需数据而产生的必要开销。
  • 缓存:如果数据和代码不能并置,就缓存数据,以减少反复取数据的开销。
  • 池化:通过池化昂贵的资源,减少与其使用相关的开销。
  • 并行化:通过分解问题、并行化独立的步骤,减少完成一个工作单元所需的时间。
  • 分区处理:通过分割处理代码、并置相关的分区,尽可能将相关的处理过程集中在一起。
  • 远程处理:减少访问远程服务所花费的时间,比如可以通过更粗粒度地划分接口。远程还是本地是明确的设计决策,不能随意来回更动,这一点应当牢记。还要考虑分布式计算的第一准则——不要分布你的对象。

软件开发人员总爱在不需要的地方引入抽象和层。是的,这些概念对软件组件之间的解耦来说是很好的工具,但它们可能会增加复杂性、影响性能,尤其是在每层的数据表示之间都需要转换的情况下。因此,减少处理时间还要注意保证抽象不要过于抽象化,并且没有过多的分层。另外,对于我们视为理所当然的运行时服务,有必要理解其成本,因为除非它们提供了特定的服务水平协议,否则很有可能最终会成为应用中的瓶颈。

2. 分区

减少单个工作单元的处理时间能达到不错的效果,但当你达到单进程方案的极限,最终还是需要对系统作水平伸缩。在典型的 Web 应用中,水平伸缩可能很简单,只要加入更多的 Web 服务器来处理用户请求,再给它们加上负载均衡就行了。但是,你可能会发现总体架构的某些部分会成为资源争用的焦点,因为一切东西都会在同一时间变得忙碌起来。一个很好的例子就是所有 Web 服务器后端的单一数据库服务器。当这个单一的数据库服务器变成瓶颈时,你必须改变方法,其中一种方式就是采用分区策略。简而言之,这涉及到将架构的单个部分分解成更小、更容易管理的部分。将单个的元素分割成更小的部分能实现水平伸缩,这恰恰也是 eBay 这样的大型网站采用、以此来确保它们的架构可伸缩的技术。分区是一个很好的解决办法,尽管你可能会发现牺牲了一致性

至于如何分割你的系统,那要看情形而定。真正无状态的组件能简单地作水平伸缩,将工作负载分散到所有实例上,让组件的所有实例都能有效地运行。另一方面,如果需要维护某状态,你需要找到一种工作量分割策略能允许有状态组件的多重实例,让每个实例负责工作和/ 或数据的一个独特的子集。

3. 可伸缩性在于并发

可伸缩性天生就和并发联系在一起;毕竟,它就是要在同样的时间内做更多的工作。像 EJB 早期版本这样的技术试图提供一种简化的编程模型,鼓励我们编写单线程的组件。遗憾的是,组件往往要依赖于其它组件,还是导致了并发问题。如果没有考虑并发,系统中的数据会很容易被损坏。另一方面,围绕并发做了太多的保护会导致系统实质上变成串行的,限制了伸缩的能力。并发编程不是很难做到,在构建可伸缩系统的时候,有一些简单的原则会有所帮助。

  • 如果你确实需要持有锁(比如本地对象、数据库对象等),试着尽可能短地持有它们。
  • 设法减少对共享资源的争用,并尽可能是争用避开关键处理路径(比如通过异步调度工作)。
  • 任何针对并发的设计都需要预先完成,以便能被充分地理解哪些资源可以被安全共享、哪里可能会是潜在的可伸缩性瓶颈。

4. 必须知道需求

为了构建一个成功的软件系统,你需要知道你的目标是什么、你针对什么去做。尽管功能性需求往往是明确的,但常常会缺少非功能性需求(或系统质量需求)。如果你真是需要构建一套高可伸缩的软件,那你首先需要调查清楚关键组件 / 工作流的以下特质:

  • 目标平均性能和峰值性能(即响应时间、延迟等)。
  • 目标平均负荷和峰值负荷(即并发用户、信息量等)。
  • 性能和可伸缩性可接受的极限。

性能也许不是最紧要的方面,但你必须尽早知道这个信息,因为处理可伸缩性的方法会由性能需求决定。

5. 持续测试

理解了需求就可以开始设计和构建解决方案。我们提出的设计、编写的代码实际上都是静态的,所以你在执行之前不能完全断定它会怎样运转。此外,所有关于性能和可伸缩性的决策应该由证据支持的原因也在于此,而且应当从项目一开始就收集和审核这些证据,此后也要一直继续。换句话说,就是设立贯穿系统的可度量目标,证实并度量实际的性能,并在项目的各个阶段考虑性能。

最常犯的错误之一是,我们对系统性能和可伸缩性的见解会被我们自己的经验或道听途说所混淆。你可能要审核对工程做出的其它决策,这样做的原因之一是要满足系统的非功能性特性。比如说,非功能性需求可能会影响你选择不使用标准,改用非主流 / 流行的一些东西。非功能性需求可能会打破僵化的教条,证据胜过教条。

6. 架构先行

或许对构建可伸缩的系统来说最重要的原则是,如果你需要使系统具备这样的性质,就必须预先设计出这样的性质。很多人(包括我自己)陷入的陷阱,就是以为可以构建一个应用,它会自动地垂直伸缩(scale up)或水平伸缩(scale out),尤其是在 J2EE 刚出现的时候。设计为可水平伸缩的应用几乎总能垂直伸缩,但是设计为垂直伸缩的应用几乎不可能水平伸缩。大多数应用能通过在更加强大的硬件上运行来垂直伸缩,但水平伸缩却是一个更为复杂的问题。比如说,你怎么确保数据在应用实例之间保持一致性?你如何使你的单例和同步代码块跨线程工作?

当然,预先思考这件事情不一定等同于做一个瀑布式的、预先的大设计。迭代和敏捷过程都是助力,它们能提供一个框架帮助我们可以做出刚好够用的设计来解决问题。要务实。哦,不管我们自认为是多么擅长于设计可伸缩的应用,不要相信自己、尽早地编写/ 测试代码才是最好的举动。

7. 着眼于全局

最后,记着要着眼于全局——看到树木之前先看看森林。对我们来说,在细粒度代码级别调整组件确实很容易,但最终需要优化的却是作为一个整体的系统。关注每一个环节的性能和可伸缩性,必要时牺牲局部的优化。如果你需要使用性能分析工具确定瓶颈,不妨去做,但在对全局的性能有所认识之前先不要急于动手。由于性能与整个系统所有等待时间的集合成反比,任何等待时间增加得比负载还快的操作都会成为问题。尽管说了这么多,但我还想指出,如果你发现满足性能和可伸缩性目标很困难,那就有必要怀疑一下是否选择了正确的架构。还是那句话,着眼于全局,确保有人在承担架构师的责任

总结

这篇文章针对构建可伸缩应用提出了一些原则和方针,覆盖了软件开发过程中许多不同的方面。无论谁要构建可伸缩的系统,我能给他的最好建议就是你需要明确地考虑并设计你的系统。可伸缩性不是魔术,它也不会无偿获得。最后一点,更快的硬件也许能救你于一时,但还是不要依赖它为妙!

关于本文

2005 年年底,英国伦敦举办了针对架构师的非官方峰会,本文中的大多数原则就来源于其中一场可伸缩性讨论的一些笔记。该峰会由 Alexis Richardson、Floyd Marinescu、Rod Johnson、John Davies、Steve Ross-Talbot 组织。题为“ JP Rangaswami 谈企业中的开源与信息前景”的视频也来源于此峰会。

关于作者

Simon 是一名注重实践的软件架构师,他在 Detica ’的全球金融市场集团工作。Simon 专心参与的项目有桌面客户端和 Web 应用,也有高度可伸缩的分布式系统和面向服务的体系架构(SOA)。他的专攻技术是 Java,作为一名注重实践的权威,他被要求建议并设计解决方案;定义、交付并保证所选择的架构适合于目的,能满足非功能性需求。Simon 已经编写或与他人合著过很多 Java EE Web 技术相关的书籍,在数次会议上发表过演讲,并创建了 Coding the Architecture ——一个介绍关于软件架构实用和务实观点的网站。

阅读英文原文 Scalability Principles

2008-07-25 20:257864
用户头像

发布了 151 篇内容, 共 66.7 次阅读, 收获喜欢 18 次。

关注

评论

发布
暂无评论
发现更多内容

Tapdata 和 Databend 数仓数据同步实战

Databend

数字经济赋能乡村建设,助力乡村全面振兴

加入高科技仿生人

低代码 数字经济 乡村振兴 农村

ZBC通证月内已翻倍,Nautilus Chain 上线前夕的“开门红”

西柚子

行业分析| OA系统中的实时通讯

anyRTC开发者

音视频 远程办公 视频会议 视频通话 OA

建议收藏!数据可视化大屏设计必备步骤

葡萄城技术团队

0经验拿下大厂年薪30万Offer,我的面试求职之路(含面试题)~

霍格沃兹测试开发学社

当 Amazon Lambda 遇上 Apache APISIX 可以擦出什么火花?

API7.ai 技术团队

AWS api 网关 Lambda s APISIX

大前端CPU优化技术--SIMD技术

江湖修行

simd neon

工业数字孪生:西门子工业网络与设备虚拟调试案例(TIA+MCD+SINETPLAN)

工赋开发者社区

测试开发 | Dubbo 接口测试技术,测试开发进阶必备(附源码)

霍格沃兹测试开发学社

LeetCode题解:89.格雷编码,归纳法,详细注释

Lee Chen

JavaScript LeetCode

云小课|MRS数据分析-通过Spark Streaming作业消费Kafka数据

华为云开发者联盟

大数据 数据分析 华为云 企业号 2 月 PK 榜 华为云开发者联盟

代码的发展与终结

飞算JavaAI开发助手

低代码选型,论协同开发的重要性

葡萄城技术团队

IoT企业物联网平台,从设备端到云端业务系统全链路开发实战——实践类

阿里云AIoT

数据库 监控 物联网 存储 消息中间件

软件供应链受威胁下的应对方法——供应链安全管理平台的五大工具能力

墨菲安全

SCA 供应链安全

和狂飙的 ChatGPT 聊聊软件开发的现在与未来

极狐GitLab

DevOps 研发效能 DevSecOps 极狐GitLab ChatGPT

设备上报二进制数据在 IoT 平台解析实践——实践类

阿里云AIoT

小程序 监控 物联网 传感器 测试技术

IoT物联网设备端硬件上云技术方案详解——实践类

阿里云AIoT

物联网 存储 开发工具 数据采集 传感器

2023年Java面试正确姿势(1000+面试题附答案解析)

Java编程日记

Java 架构 后端 java程序员 java面试

经常会采坑的javascript原型应试题

loveX001

JavaScript 前端

深入理解JS作用域链与执行上下文

loveX001

JavaScript

一图读懂 | ChatGPT热潮背后,金融行业大模型应用路在何方?——金融行业大模型应用探索

易观分析

金融 科技

基于 IoT物联网 + 表格存储DB + DataV 搭建实时环境监控大屏——实践类

阿里云AIoT

数据库 监控 物联网 存储 数据可视化

AntDB数据库再获奖,亚信安慧被评为“2022 PostgreSQL中国最佳创新企业”

亚信AntDB数据库

数据库 AntDB 国产数据库 AntDB数据库 企业号 2 月 PK 榜

CVE-2023-23752 Joomla未授权访问漏洞分析

墨菲安全

漏洞分析 软件供应链安全

聊聊 HTAP 的前世今生

墨天轮

数据库 OLAP TiDB OLTP HTAP

ChatGPT专题 | 万字长文解析!复现和使用GPT-3/ChatGPT,你所应该知道的

工赋开发者社区

社招前端二面面试题总结

loveX001

JavaScript 前端

如何通过Java 代码设置 Word 文档页边距

在下毛毛雨

C# .net word文档 页边距

用户属性-MQTT 5.0新特性

EMQ映云科技

物联网 IoT mqtt 企业号 2 月 PK 榜 用户属性

可伸缩性原则_架构_Simon Brown_InfoQ精选文章