应用程序架构是如何演变的
【squids.cn】 全网zui低价RDS,免费的迁移工具DBMotion、数据库备份工具DBTwin、SQL开发工具等
如果您一直在开发或以某种方式参与应用程序架构,那么在过去的几年中您肯定看到了许多变化。有很多不同类型的架构和技术陆续出现然后消失,以至于有时很难跟踪它们。但是,当你反思它们时,它们不仅可以讲述过去的故事,还可以预示应用程序架构的发展方向。
在这篇文章中,我将讨论近几年来应用程序架构在我看来是如何演变的,以及每次演变的驱动因素是什么。我们将讨论单体架构、面向服务的架构(SOA)、微服务,最后是事件驱动架构(EDA)。让我们开始吧!
单体架构
在过去,所有东西都是单体的。大团队会专注于一个单体应用程序,这个应用程序负责执行许多任务。单体架构允许您迅速地将原型组合在一个应用程序中,这个应用程序可以完成所有的事情。由于你不需要依赖其他团队,所以维护成本较低。然而,当应用程序被推送到生产并继续增长时,事情很快就会失控。
例如,一个典型的单体应用程序可能包括多个层次,如用户界面层、业务逻辑层、数据接口层和数据存储层。此应用程序会接受用户输入,处理它,应用业务逻辑,使用现有数据进行丰富,然后可能将其存储在关系型数据库中,供以后进行额外的处理。
单体架构有三个主要的缺点:部署慢、可扩展性差和相互依赖。单体应用程序更难调试和更新。大型应用程序需要大量的时间和努力来确定问题并部署更新,而当这些更新被推出时,需求可能已经发生了变化。
单体应用的第二个缺点是可扩展性差。一个应用程序能做的只有那么多。在当今的世界,计算资源比过去便宜得多,我们通过简单地为应用程序投入更多的计算资源,更容易地并行计算。一个过去运行在强大但非常昂贵的服务器上的单体应用程序,现在可以作为较小的应用程序并行运行在普通硬件上。此外,较慢的部署(我们之前讨论过的)使得快速扩展变得更加困难。
此外,在一个大型应用中,每一个小的改动都可能影响到应用的一个或多个其他部分。这增加了可能破坏重要功能的额外风险。例如,用户界面层的一个错误可能会影响整个应用程序。
在我之前的工作中,我曾在一个应用上工作,该应用提供了对跨资产市场数据(股票、外汇、大宗商品等)的访问。在一个版本中,我为股票用户推出了一个新功能,但由于我们的应用是单体的,我的这个小改动最终破坏了一个由外汇用户使用的应用的非常重要的功能。这两个功能是完全独立的,但由于它们是同一个代码库的一部分,它们有很多共享资源。不用说,外汇用户并不满意。
敏捷 vs. 瀑布
很快,公司们开始意识到,他们需要找到一个更好的方法来构建他们的应用程序。大约在同一时间,敏捷方法论正变得越来越受欢迎。以前,公司主要使用瀑布方法论来开发应用程序,这意味着收集大量的需求,进行极端的规划,涵盖所有的边界情况,然后在一个大的爆炸中小心地发布具有所有功能的最终产品。

对于某些行业,由于每次迭代所涉及的成本和/或监管要求,这是唯一的方法。而对于许多其他行业,敏捷方法论更为有效。敏捷方法论是关于在快速迭代中发布最小可行产品(MVP)。你失败得越快,知道什么不起作用,就越好。敏捷方法论,虽然已经存在了一段时间,但在2011年左右变得非常流行,当时敏捷联盟(是的,这是真的)创建了《敏捷实践指南》。敏捷认证和敏捷教练无处不在。不管你怎么努力躲藏,你的敏捷教练总会在每日晨会时找到你。
面向服务的架构
随着敏捷方法论的推广,人们明确地认识到,拥有可以轻松更新和扩展的小型应用程序有着宝贵的优势。这引出了面向服务的架构。在单体架构中,一个应用程序自己做所有事情,而在面向服务的架构中,一个应用程序会被分解成基于其用途的几个较小的服务。正如IBM的这篇文章所提及的:
SOA的核心目的是通过格式良好、易于使用、同步的接口(如Web服务)来暴露系统中的数据和功能。
回到我们关于单体应用的例子,它可以被分解成多个较小的服务:
-
用户界面服务。
-
业务逻辑服务。
-
数据集成服务。
-
数据存储服务。
每个服务都负责一个特定的用例。它们都独立存在,并通过基于简单对象访问协议(SOAP)的同步API进行通信。然而,随着你组织中服务数量的增长,为每个服务编写一个与其他所有服务通信的接口会变得越来越困难。这时,你会从企业服务总线(ESB)中受益。ESBs允许开发人员解耦他们的服务(请参阅下面的图)并使整体架构更加灵活。

解耦服务图
解耦您的服务
面向服务架构的多个好处包括:
-
快速推出。
-
更容易调试。
-
可扩展性。
-
职责明确。
-
对其他服务/组件的依赖性较少。
由于这些明显的优势,大多数公司开始采纳面向服务的架构以及敏捷方法论,但他们几乎不知道,云计算的革命即将到来。
微服务
面向服务的架构最终为微服务架构铺平了道路,它们有很多相似之处,但在一些细微之处有所不同。
我认为导致微服务架构产生的最重要因素是廉价和灵活的基础设施。由于水平扩展你的基础设施并在集群上而不是在强大的服务器上运行你的服务变得如此容易,所以鼓励开发人员编写可以轻松在集群上并行运行的软件。大约在同一时期,出现了大量的分布式应用和框架,如Hadoop,它普及了map-reduce编程模型。
此外,大约在2015年,AWS变得非常流行。那时AWS已经存在了一段时间,但大约在2015年,基础设施即服务(IaaS)的整个概念真正起飞,而且非常方便地启动EC2实例变得很便宜。初创公司是第一个采用IaaS的,不久之后被中小型公司所追随。经过大量的争论和讨论,大型公司最终接受了IaaS,并决定采用混合云方法。

分布式云基础设施是很好的,但有一个问题。与你自己的数据中心中的少量服务器相比,它非常难以预测和管理。在分布式云基础设施上稳健地运行一个应用程序绝非易事。很多事情可能会出错。你的应用程序的一个实例或你的集群上的一个节点可能会静默地失败。你如何确保你的应用程序可以继续运行,尽管出现这些故障?答案是微服务。
微服务是一个非常小的应用程序,负责一个特定的用例,就像在面向服务的架构中一样,但它与其他服务完全独立。它可以使用任何语言和框架开发,并可以部署在任何环境中,无论是本地还是公共云。此外,它们可以轻松地在不同地区的多个不同服务器上并行运行,以提供并行性和高可用性。例如,一个小的数据应用程序可以在一个计算集群的5个实例上运行,这样如果一个实例失败,其他4个会确保你的数据应用程序继续运行。
将你的服务分解为多个微服务意味着它们需要相互通信。与依赖企业服务总线和同步API的面向服务架构不同,微服务利用了消息代理和异步API。
容器化
正如面向服务架构的转变受到敏捷方法论的推动一样,微服务运动也受到了容器化的推动。HackerNoon的这篇文章很好地描述了容器化:
容器化涉及将一个应用程序及其所有相关的配置文件、库和依赖性捆绑在一起,使其能够在不同的计算环境中高效且无错误地运行。

Docker,最初于2013年发布,是最受欢迎的容器平台。如今,几乎所有现代软件都可以通过docker来运行。随着云基础设施的兴起,确保在新环境中、特别是在云上运行软件,docker变得极其重要。
随着微服务的普及,服务网格的概念也随之兴起,该网格允许服务主要使用请求/应答消息模式保持连接。Nginx在其博客上对服务网格有很好的解释:
服务网格是一个可配置的、低延迟的基础设施层,设计用于处理使用应用程序编程接口(API)的应用程序基础设施服务之间基于网络的大量进程间通信。

在2014年,Google开源了Kubernetes,允许你编排你的微服务。借助docker和Kubernetes,部署和管理云上的分布式微服务变得容易得多。在过去的几年中,这两种技术变得越来越受欢迎。如今,大多数新兴的初创公司都编写原生云微服务,可以通过docker轻松部署,并通过Kubernetes编排,许多大型公司正在与Pivotal这样的公司合作,轻松地将他们的应用迁移到云上。
云基础设施和分布式微服务的兴起导致了大量为监控微服务(它们消耗了多少内存)、自动化(自动跨服务器持续部署微服务)和资源管理(为最便宜的AWS资源竞标)提供服务的初创公司的诞生。如果你曾参加过AWS峰会,那么你就知道我在说什么。
事件驱动的架构
随着我们继续捕获越来越多的数据,我们继续找到创造性的方法来使用它。随着IoT(如Alexa微波炉)和可穿戴设备(如Apple Watch)的兴起,有了大量的时序数据或事件。
在我们面前有这么多的屏幕(智能手机、智能手表、平板电脑、笔记本电脑等)可以立即推送通知,公司发现变得更加事件驱动非常重要。他们的用户期望在重要事件发生时获得实时通知。例如,当我的Delta航空公司应用程序通知我航班延误或开始登机时,它都是实时的。它不等我手动检查或仅在固定间隔时检查事件。
在这个勇敢的新事件驱动的世界中,微服务是围绕事件设计的。它仍然相对较新,并正在迅速地在各个行业中普及。
结论
在这篇文章中,我的目标是向您展示在我看来,应用程序架构在过去几年中如何受到不同技术和需求的影响和发展。当大多数公司尝试采用微服务和云时,其他公司则走在前面并采用了事件驱动的架构。在我看来,可预见的未来是以事件驱动的方式设计的微服务。
作者:Himanshu Gupta
更多内容请关注公号【云原生数据库】
squids.cn,云数据库RDS,迁移工具DBMotion,云备份DBTwin等数据库生态工具。
相关文章:
应用程序架构是如何演变的
【squids.cn】 全网zui低价RDS,免费的迁移工具DBMotion、数据库备份工具DBTwin、SQL开发工具等 如果您一直在开发或以某种方式参与应用程序架构,那么在过去的几年中您肯定看到了许多变化。有很多不同类型的架构和技术陆续出现然后消失,以至于…...
云原生Docker Cgroups资源控制操作
目录 资源控制 cgroups四大功能 CPU 资源控制 设置CPU使用率上限 进行CPU压力测试 设置50%的比例分配CPU使用时间上限 设置CPU资源占用比(设置多个容器时才有效) 设置容器绑定指定的CPU 对内存使用的限制 限制容器可以使用的最大内存 限制可用的…...
【Java集合类面试二十五】、有哪些线程安全的List?
文章底部有个人公众号:热爱技术的小郑。主要分享开发知识、学习资料、毕业设计指导等。有兴趣的可以关注一下。为何分享? 踩过的坑没必要让别人在再踩,自己复盘也能加深记忆。利己利人、所谓双赢。 面试官:有哪些线程安全的List&a…...
分布式系统的链路追踪,让你轻松解决订单无法查看的问题!
你好,我是积极活泼的小米!今天我要跟大家聊聊分布式系统的链路追踪,这个话题对于我们在技术领域工作的小伙伴们来说,可是非常重要的哦! 背景 昨天,产品大佬丰哥找到了我,他抱怨说分销员的订单…...
基于生产数据测试设计、测试回归
问题背景 QA搬砖日常中,你会不会有这样的问题,测试设计时有些场景没考虑到,上线就因为测试中没覆盖到的场景而导致缺陷溢出。从缺陷分类统计来看,类似这样的例子占比是很高的。 解决措施 仅依靠测试者设置的场景,模拟…...
装了mac os 14.0 sonoma 在腾讯会议投屏时候,无法设置麦克风权限问题
愿意:界面上直接空白的,无法手动或自动弹出要配置授权的软件 解决思路: 给 TCC.db 增加1条权限记录 添加到数据库里 /usr/bin/sqlite3 ~/Library/Application\ Support/com.apple.TCC/TCC.db "INSERT INTO main.access (service, cli…...
ARM 汇编指令 orreq 的使用
orreq 阅读代码时,发现有个【组合指令】 orreq, orr 一般是 OR,也就是或操作,后面加个 eq 表示什么呢? 比如下面的代码:前面一个操作, tst,好像没做实际的操作,可能影响…...
Python---练习:for循环 求1-100的和/所有偶数的和
案例: 使用for循环,求1 ~ 100的和 之前用while循环,做过算出1--100的和。 相关链接: Python--练习:使用while循环求1..100的和-CSDN博客 结合着看看for循环怎么实现。 思考: 先把for循环的基本语法写…...
APP逆向基础(APK流程)
APK的基本结构 Android体系结构和APK基本结构-CSDN博客 APK 打包流程 【Android 安装包优化】APK 打包流程 ( 文件结构 | 打包流程 | 安装流程 | 安卓虚拟机 )_adnroid 安装包优化,打指定资源_韩曙亮的博客-CSDN博客 APK安装流程...
Tomcat调试端口被占用解决办法
Tomcat调试端口被占用解决办法 tomcat启动报错: Unable to open debugger port (127.0.0.1:52718): java.net.BindException "Address already in use: NET_Bind"这个错误表明Tomcat服务器在启动时尝试打开调试端口(通常是在调试模式下使用的…...
feign之间相互通信RequestInterceptor拦截器失效
1、问题描述 前段时间碰到一个问题,有两个服务A和服务B,通过feign进行通信。因为feign之间无法直接传递请求头,只能传请求体。因此需要借助RequestInterceptor拦截器获取到请求头。服务B中设置了RequestInterceptor拦截器,但是在A…...
GoLong的学习之路(十)语法之函数
书接上回,上回书说到,结构体,一言之重在于体。一体之重在于经。经之重甚于骨。这张就说go的经络—函数。 文章目录 函数函数如何定义参数可变参数 返回值多返回值 函数类型与变量 高阶函数函数作为参数函数作为返回值匿名函数闭包defer语句底…...
随笔:使用Python爬取知乎上相关问题的所有回答
项目中数据分析的需要自己从知乎某个专门的问题上爬数据,但众所周知,知乎的问题的显示方式有点胃疼(指滑动后下翻加载更多回答,还经常卡住),翻了翻网上的教程发现有的要么就是很老了要么就是付费的…...
ORB-SLAM安装过程遇到问题记录整理
一、ORB-SLAM2 1.c error: ‘decay_t’ is not a member of ‘std’ 如下图所示: 解决方法: 修改 ORB_SLAM的 CMAKELIST.txt文件, 将set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdc11") 修改为 set(CMAKE_CXX_STANDARD 14) 2…...
Ubuntu22.0.4安装svn服务
1、检查是否已安装 1.1、检查是否已安装 svnserve --version1.2、删除SVN遗留文件 sudo apt-get remove --purge subversion2、安装svn apt-get install subversion3、新建存储目录 sudo mkdir /data/svn sudo mkdir /data/svn/repository4、更改文件夹的读写权限 sudo…...
GNSS边坡位移监测仪在自然灾害应急能力提升工程领域的应用
GNSS边坡位移监测仪在自然灾害应急能力提升工程领域的应用 二、工作原理 GNSS的基本原理是测量出已知位置的卫星到用户接收机之间的距离,然后综合多颗卫星的数据就可知道接收机的具体位置。要达到这一目的,卫星的位置可以根据星载时钟所记录的时间在卫星…...
k8s客户端配置
K8s客户端安装 前提 K8s服务部署成功,如下 角色 IP地址 操作系统 主机名 Kubernetes版本 master节点 172.16.4.167 CentOS 7.9 k8s-master01 v1.28.2 工作节点1 172.16.4.168 CentOS 7.9 k8s-worker01 v1.28.2 工作节点2 172.16.4.169 CentOS 7.9…...
网络套接字编程
1.基础预备知识 1.1源ip和目的ip 在IP数据包头部中, 有两个IP地址, 分别叫做源IP地址, 和目的IP地址 源IP地址表示发起通信的设备的IP地址。它是数据包的出发点,标识了数据包的来源。当一个设备发送数据包到网络上的其他设备时,该数据包的源IP字段会被…...
Node编写更新用户信息接口
目录 前言 定义路由和处理函数 验证表单数据 实现更新用户基本信息的功能 前言 继前面几篇文章,本文介绍如何编写更新用户信息接口 定义路由和处理函数 路由 // 更新用户信息接口 router.post(/userinfo, userinfo_handler.updateUserinfo) 处理函数 // 导…...
Delphi解决 openssl DLL 与 Indy 的SSL/TLS 连接问题
昨天,突然间,我的一个 Delphi 程序无法连接到互联网上的各种WMS服务器。我收到以下错误消息: 使用 SSL 连接时出错。错误 1409442E:SSL 例程:ssl3_read_bytes:tlsv1 警报协议版本 由于我使用的是最新版本…...
在软件开发中正确使用MySQL日期时间类型的深度解析
在日常软件开发场景中,时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志,到供应链系统的物流节点时间戳,时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库,其日期时间类型的…...
日语AI面试高效通关秘籍:专业解读与青柚面试智能助攻
在如今就业市场竞争日益激烈的背景下,越来越多的求职者将目光投向了日本及中日双语岗位。但是,一场日语面试往往让许多人感到步履维艰。你是否也曾因为面试官抛出的“刁钻问题”而心生畏惧?面对生疏的日语交流环境,即便提前恶补了…...
应用升级/灾备测试时使用guarantee 闪回点迅速回退
1.场景 应用要升级,当升级失败时,数据库回退到升级前. 要测试系统,测试完成后,数据库要回退到测试前。 相对于RMAN恢复需要很长时间, 数据库闪回只需要几分钟。 2.技术实现 数据库设置 2个db_recovery参数 创建guarantee闪回点,不需要开启数据库闪回。…...
React hook之useRef
React useRef 详解 useRef 是 React 提供的一个 Hook,用于在函数组件中创建可变的引用对象。它在 React 开发中有多种重要用途,下面我将全面详细地介绍它的特性和用法。 基本概念 1. 创建 ref const refContainer useRef(initialValue);initialValu…...
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする 1、前言(1)情况说明(2)工程师的信仰2、知识点(1) にする1,接续:名词+にする2,接续:疑问词+にする3,(A)は(B)にする。(2)復習:(1)复习句子(2)ために & ように(3)そう(4)にする3、…...
Java如何权衡是使用无序的数组还是有序的数组
在 Java 中,选择有序数组还是无序数组取决于具体场景的性能需求与操作特点。以下是关键权衡因素及决策指南: ⚖️ 核心权衡维度 维度有序数组无序数组查询性能二分查找 O(log n) ✅线性扫描 O(n) ❌插入/删除需移位维护顺序 O(n) ❌直接操作尾部 O(1) ✅内存开销与无序数组相…...
使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装
以下是基于 vant-ui(适配 Vue2 版本 )实现截图中照片上传预览、删除功能,并封装成可复用组件的完整代码,包含样式和逻辑实现,可直接在 Vue2 项目中使用: 1. 封装的图片上传组件 ImageUploader.vue <te…...
【C++进阶篇】智能指针
C内存管理终极指南:智能指针从入门到源码剖析 一. 智能指针1.1 auto_ptr1.2 unique_ptr1.3 shared_ptr1.4 make_shared 二. 原理三. shared_ptr循环引用问题三. 线程安全问题四. 内存泄漏4.1 什么是内存泄漏4.2 危害4.3 避免内存泄漏 五. 最后 一. 智能指针 智能指…...
(一)单例模式
一、前言 单例模式属于六大创建型模式,即在软件设计过程中,主要关注创建对象的结果,并不关心创建对象的过程及细节。创建型设计模式将类对象的实例化过程进行抽象化接口设计,从而隐藏了类对象的实例是如何被创建的,封装了软件系统使用的具体对象类型。 六大创建型模式包括…...
探索Selenium:自动化测试的神奇钥匙
目录 一、Selenium 是什么1.1 定义与概念1.2 发展历程1.3 功能概述 二、Selenium 工作原理剖析2.1 架构组成2.2 工作流程2.3 通信机制 三、Selenium 的优势3.1 跨浏览器与平台支持3.2 丰富的语言支持3.3 强大的社区支持 四、Selenium 的应用场景4.1 Web 应用自动化测试4.2 数据…...
