浅谈架构模式变迁之从分层架构到微服务架构

前言

谈到软件系统设计的方法论,在代码层面,有我们熟悉的23种设计模式(design pattern),对应到架构层面,则有所谓的架构模式(architecture pattern)。它们分别从微观和宏观的角度指导着我们设计出良好的软件系统,因此,作为一个软件工程师,我们不仅要熟悉设计模式,对常见的架构模式也要熟稔于心。正如看到一个设计模式的名字脑里就能浮现出大致的结构图,当我们看到一个架构模式的名字时,也要马上想到对应的架构图及其基本特点。比如,当谈到分层架构时,我们就应该想起它的架构图是怎样的、有哪些出色的架构特征(architecture characteristics)、系统是如何部署的、数据存储的策略是哪种、等等。

一般地,架构模式大致可以分成两类,单体架构(monolithic architecture)和分布式架构(distributed architecture)。本系列文章将会介绍以下8种常用的架构模式:

单体架构

分层架构(Layered architecture)

管道架构(Pipeline architecture)

微内核架构(Microkernel architecture)

分布式架构

基于服务的架构(Service-based architecture)

事件驱动架构(Event-driven architecture)

基于空间的架构(Space-based architecture)

面向服务的架构(Service-oriented architecture)

微服务架构(Microservices architecture)

软件设计中的谬误

在介绍架构模式前,我们先谈谈软件设计中的谬误(fallacy)。所谓谬误,就是在设计软件系统,特别是分布式系统时,我们先入为主地假设它们是正确,但实际上并非如此的一些观念。这些观念都是我们在设计软件时考虑不周的体现。

谬误1:网络是可靠的

网络是不可靠的

很多软件工程师常常假设网络是可靠的,但实际并非如此。相比20年前,现在的网络会可靠很多,但是仍然具有很大的不确定性。如上图所述,Serivce B可能完全是正常运行的,但是因为网络的问题,Service A发出的请求无法到达Service B。一种更糟糕的场景是,Service B可以收到Service A的请求,并处理了相关的数据,但是网络问题导致了Service A无法收到Service B的响应,从而造成了数据不一致。网络的不可靠也是为什么系统中常常出现服务通信超时、服务熔断等的原因。

总而言之,如果假设网络是可靠的,那么我们设计出来的软件系统将会是不可靠的。

谬误2:时延是0

时延不为0

如上图所示,服务内组件间的函数/方法级别的调用,耗时是微秒,甚至是纳秒级别;但是服务间的远程调用(比如REST、消息队列、RPC),耗时会是毫秒级别,甚至在异常场景会达到了秒级!在设计系统,特别是分布式系统时,时延是一个无法被忽视的因素,我们必须清楚系统的平均时延,否则设计出来的方案可能根本不可行。比如,假设系统中服务间通信时延为100ms,如果一个请求的调用链涉及到10个服务,那么该请求的时延将会是1000ms!这么高的平均时延对于一般系统来说是完全无法接受的。

进行系统设计时,考虑平均时延还不够,更重要的是95th和99th百分点。一个系统的平均时延可能仅仅只有数十毫秒,但是95th百分点的时延却达到了数百毫秒,很多时候,这也恰恰成为了拖垮整系统性能的那块“短板”。

谬误3:带宽是无限的

带宽是有限的

在单体架构中,业务流程都在单服务内闭环,消耗的带宽很少甚至为0,因此带宽并不是主要关注点。一旦将系统拆分成分布式架构,一个业务流程可能涉及多个服务间的通信,带宽就成了必须考虑的因素。带宽的不足,会导致网络变慢,从而影响系统的时延(谬误2:时延是0)和可靠性(谬误1:网络是可靠的)。

如上图所示,假设在一个Web系统中,Service A负责处理前端请求,Service B负责管理用户信息(包括姓名、性别、年龄等45个属性)。Service A每处理一个请求都需要向Service B查询用户姓名(200 bytes),而在一次请求中,Service B却返回了用户的所有信息(500 kb)。如果系统每秒处理2000次请求,每次请求消耗500 kb带宽,那么每秒消耗的总带宽会是1 Gb!如果Service B仅仅返回必须的姓名,那么同等条件下,每秒消耗的总带宽仅仅是400 kb。

此类问题就是所谓的stamp coupling,解决方法也很多,比如在请求中添加属性选择,使用GraphQL替代REST。相比于这些技术手段,更重要的是确定服务间通信所需的最小数据集,并在进行系统设计时将其作为一个重点关注的因素。

谬误4:网络是安全的

网络是不安全的

VPN、防火墙等的广泛使用,使得很多工程师在设计系统时忽略了“网络是不安全的”这一重要原则。特别是从单体架构演进到分布式架构以后,系统被攻击的概率将会大大增加。因此,在分布式系统中,每个服务都必须是安全的endpoint,这样才能确保任何未知或恶意的请求都被拦截掉。当然,安全是有代价的,这也是像微服务架构这类细服务粒度的系统,一次业务请求中调用链过长后性能极速下降的重要原因。

谬误5:网络拓扑一成不变

网络拓扑是时常变化的

这里的网络拓扑指的是系统运行时所涉及到的网络设备,包括所有的路由器、防火墙、集线器、交换机等。很多工程师会假设网络拓扑是固定的,然而并非如此。

假设如下场景,为架构师的你在周一早上回到公司后,发现组内同事都在为系统中所有的服务间通信都在不断出现响应超时现象而抓狂,但奇怪的是周末并没有做服务变更。经过几个小时的攻关后,你发现周一凌晨2点时有过一次网络升级,而恰恰是这次“次要”的网络升级,推翻之前设计系统时的时延假设,从而触发了本次事故。

因此,软件工程师也需要与网络管理员时常联系,确保在每次网络升级前都明确网络拓扑的变更点,从而做出相应的调整。

谬误6:只有一个网络管理员

不只有一个网络管理员

网络管理员往往不止有一个,特别是在“云”时代,数据中心分散在多个地域,理所当然也存在着多个局域网。运行在“云”上的系统很有可能跨越多个数据中心,因此工程师们应当感知各个数据中心的网络管理员对网络的相关操作,提前做出应对措施,避免出现因网络拓扑变更(谬误5:网络拓扑一成不变)而导致的服务通信超时,甚至触发服务熔断。

谬误7:通信成本为0

通信成本不为0

这里的通信成本并非指网络时延,而是指每增加一次服务间调用所导致的钱的花销。很多工程师在设计系统时常常忽视掉通信成本,大家都在鼓吹分布式架构相对了单体架构的优越性,却忘记了它带来的服务器、防火墙、网关等硬件的数量增加,这些都是白花花的银子。

因此,在进行系统设计时,我们也应该将硬件资源和网络拓扑纳入考虑因素。

谬误8:网络是同质的

网络并非同质的

很多工程师都会假设网络是同质的,也就是所有的网络设备都来自同一硬件厂商,这当然也是一个谬误。实际上,一个大的通信网络中,硬件设备往往来自于不同的厂商,这得益于网络协议标准的统一。厂商间设备的协作测试毕竟不会太充分,在一些特殊场景下极有可能存在网络丢包,从而影响了网络的可靠性(谬误1:网络是可靠的)、时延(谬误2:时延是0)以及带宽(谬误3:带宽是无限的)。

一切从“大泥球”开始

“大泥球”架构

“大泥球”架构是著名的反模式架构,最初在1997年由Brian Foote 和 Joseph Yoder提出。在“大泥球”架构里,系统没有进行内部的模块划分,代码耦合严重,调用关系混乱,就像一个大的泥球。如上图所示,每一个点代表一个类,红线则表示类之间的耦合关系。这样的架构对需求变更极不友好,往往牵一发而动全身,而且在部署、可测试性、性能等方面也存在着很多问题。所有的架构师都在极力避免“大泥球”的出现,但很不幸的是,它仍然在实际项目中很常见,特别是项目伊始,代码质量和结构还没被严格管控起来前。

有反模式的出现,必然就有解决它的方法,这便是架构模式,从下一篇文章开始,我们将逐个介绍常见的8种架构模式。

总结

跟设计模式类似,架构模式是软件工程师们多年来在架构设计方面的经验总结。每种架构模式并没有绝对的优劣之分,我们不能说微服务架构就一定比单体分层架构优越,它们都有着各自的应用场景。分布式架构比单体架构有着更好的可扩展性、容错性,但也带来了更高的复杂性,比如分布式事务。因此,我们应该熟知各个架构模式的特点,这样才能在特定的业务场景使用合适的架构模式。

以上就是浅谈架构模式变迁之从分层架构到微服务架构的详细内容,更多关于架构模式变迁之从分层架构到微服务架构的资料请关注我们其它相关文章!

(0)

相关推荐

  • 新手学习微服务SpringCloud项目架构搭建方法

    这篇文章主要介绍了新手学习微服务SpringCloud项目架构搭建方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 Spring的微服务框架SpringCloud受到众多公司欢迎,给大家带来一篇框架搭建入门.本次采用的版本是Spring Cloud版本为Finchley.RELEASE. 一.SpringCloud项目简介 spring cloud: 为开发人员提供了快速构建分布式系统的一些工具,包括配置管理.服务发现.断路器.路由.微代理.

  • spring boot微服务自定义starter原理详解

    这篇文章主要介绍了spring boot微服务自定义starter原理详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 使用spring boot开发微服务后,工程的数量大大增加(一定要按照领域来切,不要一个中间件客户端包一个),让各个jar从开发和运行时自包含成了一个重要的内容之一.spring boot starter就可以用来解决该问题(没事启动时别依赖于applicationContext.getBean获取bean进行处理,依赖关系

  • PHP数据源架构模式之表入口模式实例分析

    本文实例讲述了PHP数据源架构模式之表入口模式.分享给大家供大家参考,具体如下: martin fowler在<企业应用架构模式>一书中将我们平常接触到的应用开发分为三层:表现层.领域层和数据源层. 其中领域层的领域逻辑模式有:事务脚本.领域模型以及表模块. 1.事务脚本最容易理解也最易于开发,不过由于易造成代码重复等问题,不利于后期的维护,比较适合开发逻辑较为简单的业务,比如只有几个用于展示企业信息的企业站等: 2.领域模型是三种模式中最为复杂的模式,缺点显而易见,需要较高的学习成本,不过优

  • springcloud微服务之Eureka配置详解

    Eureka注册中心/服务发现框架 Eureka是Netflix开发的服务发现框架,本身是一个基于REST的服务,主要用于定位运行在AWS域中的中间层服务,以达到负载均衡和中间层服务故障转移的目的.SpringCloud将它集成在其子项目spring-cloud-netflix中,以实现SpringCloud的服务发现功能. Eureka包含两个组件:Eureka Server和Eureka Client. Eureka Server提供服务注册服务,各个节点启动后,会在Eureka Serve

  • 解析SpringCloud简介与微服务架构

    1. 微服务架构 1.1 微服务架构理解 微服务架构(Microservice Architecture)是一种架构概念,旨在通过将功能分解到各个离散的服务中以实现对解决方案的解耦.你可以将其看作是在架构层次而非获取服务的类上应用很多SOLID原则.微服务架构是个很有趣的概念,它的主要作用是将功能分解到离散的各个服务当中,从而降低系统的耦合性,并提供更加灵活的服务支持. 概念:把一个大型的单个应用程序和服务拆分为数个甚至数十个的支持微服务,它可扩展单个组件而不是整个的应用程序堆栈,从而满足服务等

  • SpringCloud让微服务实现指定程序调用

    我们在做微服务时,有时候需要将微服务做一些限制,比如只能我们自己的服务调用,不能通过浏览器直接调用等. 我们可以使用spring cloud sleuth,在应用调用微服务时通过Tracer产生一个traceId,并通过request设置到header里面, 然后sleuth会将该traceId在整个链路传递,我们在微服务中定义一个拦截器,取到header里面的traceId并和链路中的traceId比较, 如果相等,则表明是我们自己的应用调用,拦截器通过,否则这次请求被拦截 代码详见githu

  • Spring Cloud Stream微服务消息框架原理及实例解析

    随着近些年微服务在国内的盛行,消息驱动被提到的越来越多.主要原因是系统被拆分成多个模块后,一个业务往往需要在多个服务间相互调用,不管是采用HTTP还是RPC都是同步的,不可避免快等慢的情况发生,系统性能上很容易遇到瓶颈.在这样的背景下,将业务中实时性要求不是特别高且非主干的部分放到消息队列中是很好的选择,达到了异步解耦的效果. 目前消息队列有很多优秀的中间件,目前使用较多的主要有 RabbitMQ,Kafka,RocketMQ 等,这些中间件各有优势,有的对 AMQP(应用层标准高级消息队列协议

  • 详解多云架构下的JAVA微服务技术解析

    微服务生态 微服务生态本质上是一种微服务架构模式的实现,包括微服务开发SDK,以及微服务基础设施. 目前比较成熟的 JAVA 微服务生态包括 servicecomb(华为), spring-cloud (Pivotal), dubbo(阿里), tsf(腾讯)等.gRPC.Thrift 等也用于内部服务之间的通信,但是微服务基础设施比较欠缺. 核心的微服务基础设施包括:注册中心.配置中心.应用网关.此外,分布式事物管理.计划任务.调用链跟踪系统等也是微服务基础设施的组成部分.完整的微服务基础实施

  • 浅谈架构模式变迁之从分层架构到微服务架构

    前言 谈到软件系统设计的方法论,在代码层面,有我们熟悉的23种设计模式(design pattern),对应到架构层面,则有所谓的架构模式(architecture pattern).它们分别从微观和宏观的角度指导着我们设计出良好的软件系统,因此,作为一个软件工程师,我们不仅要熟悉设计模式,对常见的架构模式也要熟稔于心.正如看到一个设计模式的名字脑里就能浮现出大致的结构图,当我们看到一个架构模式的名字时,也要马上想到对应的架构图及其基本特点.比如,当谈到分层架构时,我们就应该想起它的架构图是怎样

  • 详解Rainbond内置ServiceMesh微服务架构

    目录 ServiceMesh 微服务架构对比 为何使用ServiceMesh ServiceMesh相对其他微服务架构优势 最大层度透明 学习成本低 架构灵活 ServiceMesh架构性能 ServiceMesh只对网络进行治理么? Rainbond与ServiceMesh ServiceMesh 一般的字面解释是“服务网格”,作为时下最流行的分布式系统架构微服务的动态链接器,处于服务到服务的通信的专用基础设施层,该层独立于应用程序为服务之间的通信提供轻量级的可靠传递. 如果简单的描述的话,可

  • 详解Java 微服务架构

    一.传统的整体式架构 传统的整体式架构都是模块化的设计逻辑,如展示(Views).应用程序逻辑(Controller).业务逻辑(Service)和数据访问对象(Dao),程序在编写完成后被打包部署为一个具体的应用.如图所示: 系统的水平扩展 如果要对系统进行水平扩展,通常情况下,只需要增加服务器的数量,并将打包好的应用拷贝到不同的服务器,然后通过负载均衡器(Nginx)就可以轻松实现应用的水平扩展. 整体式架构的缺点 应用复杂度增加,更新.维护困难. 易造成系统资源浪费. 影响开发效率. 应用

  • Java设计模式之浅谈模板方法模式

    一. 什么是模板方法设计模式 从字面意义上理解, 模板方法就是定义出来一套方法, 作为模板, 也就是基础. 在这个基础上, 我们可以进行加工,实现个性化的实现.比如:一日餐三. 早餐, 中餐, 晚餐. 每个人都要吃三餐, 但每个人的三餐吃的可能都不一样. 一日三餐定义了模板--早中晚, 每个人的三餐就是模板的具体实现. 1.1 模板方法的用途 将不变的行为从子类搬到超类,去除了子类中的重复代码.规范子类的结构 1.2 模板方法的定义 定义一个操作中的算法骨架,而将算法的一些步骤延迟到子类中,使得

  • 浅谈Redis在微服务架构中的几种应用场景

    本文介绍在SpringCloud中使用Redis作为Pub/Sub异步通信.缓存或主数据库和配置服务器的三种场景应用. Redis可以广泛用于微服务架构.它可能是您应用程序以多种不同方式利用的少数流行软件解决方案之一.根据要求,它可以充当主数据库,缓存或消息代理.虽然它也是一个键/值存储,但我们可以将它用作微服务体系结构中的配置服务器或发现服务器.虽然它通常被定义为内存中的数据结构,但我们也可以在持久模式下运行它. 这里我将向您展示一些使用Redis与Spring Boot和Spring Clo

  • 浅谈SpringCloud实现简单的微服务架构

    Spring Cloud是一系列框架的有序集合.它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册.配置中心.消息总线.负载均衡.断路器.数据监控等,都可以用Spring Boot的开发风格做到一键启动和部署.Spring并没有重复制造轮子,它只是将目前各家公司开发的比较成熟.经得起实际考验的服务框架组合起来,通过Spring Boot风格进行再封装屏蔽掉了复杂的配置和实现原理,最终给开发者留出了一套简单易懂.易部署和易维护的分布式系统开发工具包. 接下

  • 浅谈Python使用Bottle来提供一个简单的web服务

    介绍 今天有个不正经的需求,就是要快速做一个restful api的性能测试,要求测试在海量作业数据的情况下客户端分页获取所有作业的性能.因为只是一个小的的测试工作,所以就想到了Bottle框架作为Web服务器,这里就简单说说怎样使用Bottle框架. 安装 pip install bottle 启动服务 运行下面的python脚本即可启动一个Web服务. from bottle import route, run, request @route('/hello') def hello(): r

  • 详解Spring Cloud微服务架构下的WebSocket解决方案

    WebSocket在现代浏览器中的应用已经算是比较普遍了,在某些业务场景下,要求必须能够在服务器端推送消息至客户端.在没有WebSocket的年代,我们使用过dwr,在那个时候dwr真实一个非常棒的方案.但是在WebSocket兴起之后,我们更愿意使用标准实现来解决问题. 首先交代一下,本篇文章不讲解WebSocket的配置,主要讲的是针对在微服务架构集群模式下解决方案的选择. 微服务架构大家应该都不陌生了,在微服务架构下,服务是分布式的,而且为了保证业务的可用性,每个服务都是以集群的形式存在.

  • SpringCloud微服务架构升级汇总

    一.背景 1.1 应用系统的架构历史 1.2 什么是微服务? 起源:微服务的概念源于 2014 年 3 月 Martin Fowler 所写的一篇文章"Microservices".文中内容提到:微服务架构是一种架构模式,它提倡将单一应用程序划分成一组小的服务,服务之间互相协调.互相配合,为用户提供最终价值. 通信方式:每个服务运行在其独立的进程中,服务与服务间采用轻量级的通信机制互相沟通(通常是基于 HTTP 的 RESTful API). 微服务的常规定义:微服务是一种架构风格,一

随机推荐