其他分享
首页 > 其他分享> > SRM项目学习之架构的演变

SRM项目学习之架构的演变

作者:互联网

目录

架构的演变

首先我们先来看两张图,如下所示

上述这两张图阿里的技术架构图,看起来是不是很复杂.但是任何系统的建成都不是一蹴而就的,都是一点一点的建成.

俗话说,故不积跬步,无以至千里;不积小流,无以成江海.所以接下来我们先了解一下系统架构的演变

系统介绍

我们以电商系统的发展演变为例,分析架构演变历程。关注的是数据量、访问量提升,网站结构发生的变化,而不是具体关注业务功能点。其次,这个过程是为了让大家更好的了,解网站演进过程中的一些问题和应对策略。

所具备的功能

假如我们系统具备以下功能: 用户模块:用户注册和管理 商品模块:商品展示和管理 交易模块:创建交易及支付结算

单体架构(应用程序、数据库、文件都部署在一台服务器上)

得回忆公司刚创业那会。那是很多年前,那天,公司成立了,老板兴致勃勃的租了一间民宅,买了一台服务器。

然后大伙几个就开干了。

大伙把所有软件和应用都部署在一台机器上,这样就完成一个简单系统的搭建,这个时候的讲究的是效率。

我们在一台机子上装了lnmp,下图描述了我们这台服务器:

最初的架构,应用程序、数据库、文件都部署在一台服务器上:

数据库服务器和应用服务器分离(应用,数据,文件分离)

随着网站的上线,访问量逐步上升,服务器的负载慢慢提高,在服务器还没有超载的时候,我们应该做好规划,提升网站的负载能力。

假如代码层面的优化已经没办法继续提高,在不提高单台机器的性能,增加机器是一个比较好的方式,投入产出比非常高。

这个阶段增加机器的主要目的是讲 web 服务器和 数据库服务器拆分,这样不仅提高了单机的负载能力,也提高了容灾能力。

并且根据服务器的用途配置不同的硬件,达到最佳的性能效果。

应用、数据、文件分离,如下图所示

利用缓存改善网站性能(利用缓存改善网站性能)

在硬件优化性能的同时,同时也通过软件进行性能优化,在大部分的网站系统中,都会利用缓存技术改善系统的性能,使用缓存主要源于热点数据的存在,大部分网站访问都遵循28原则(即80%的访问请求,最终落在20%的数据上),所以我们可以对热点数据进行缓存,减少这些数据的访问路径,提高用户体验。

使用集群改善应用服务器性能(应用服务器集群和缓存服务器集群)

随着访问量的继续增加,单台应用服务器已经无法满足需求。

在假设数据库服务器还没有遇到性能问题的时候,我们可以增加应用服务器,通过应用服务器集群将用户请求分流到各个服务器中,从而继续提升负载能力。

此时多台应用服务器之间没有直接的交互,他们都是依赖数据库各自对外提供服务。

应用服务器前面部署负载均衡服务器调度用户请求,根据分发策略将请求分发到多个应用服务器节点另外,我们还可以增加缓存服务器集群, 来提高访问速度并降低mysql等数据库的压力

数据库压力变大,数据库读写分离(数据库读写分离)

架构演变到这里,并不是终点。上面我们把应用层的性能拉上来了,但是数据库的负载也在慢慢增大,那么怎么去提高数据库层面的负载呢?

有了前面的思路以后,自然会想到增加服务器。

但是假如我们单纯的把数据库一分为二,然后对于后续数据库的请求,分别负载到两台数据库服务器上,那么一定会造成数据库不统一的问题。

所以我们一般先考虑读写分离的方式 。

分库分表不是这个阶段要考虑的,是数据库优化的终极技能,因为会带来一些难题,所以能不用就不用.

使用NoSQL和搜索引擎缓解读库的压力(NoSQL和搜索引擎)

数据库做读库的话,常常对模糊查找效率不是特别好,像电商类的网站,搜索是非常核心的功能,即便是做了读写分离,这个问题也不能有效解决。

那么这个时候就需要引入Nosql和搜索引擎了。

对于海量数据的查询和分析,我们使用NoSQL数据库加上搜索引擎可以达到更好的性能。

并不是所有的数据都要放在关系型数据中。

常用的NoSQL有MongoDB、HBase、Redis,搜索引擎有Lucene、Solr、Elasticsearch

使用CDN和反向代理提高网站性能(使用CDN和反向代理提高网站性能)

假如我们的服务器都部署在成都的机房,对于四川的用户来说访问是较快的,而对于北京的用户访问是较慢的,这是由于四川和北京分别属于电信和联通的不同发达地区,北京用户访问需要通过互联路由器经过较长的路径才能访问到成都的服务器,返回路径也一样,所以数据传输时间比较长。

对于这种情况,常常使用CDN 解决,CDN将数据内容缓存到运营商的机房,用户访问时先从最近的运营商获取数据,这样大大减少了网络访问的路径。

比较专业的CDN运营商有蓝汛、网宿。

而反向代理,则是部署在网站的机房,当用户请求达到时首先访问反向代理服务器,反向代理服务器将缓存的数据返回给用户,如果没有缓存数据才会继续访问应用服务器获取,这样做减少了获取数据的成本。

反向代理有Squid、Nginx。

将应用服务器进行业务拆分

随着业务进一步扩展,应用程序变得非常臃肿,这时我们需要将应用程序进行业务拆分,如百度分为新闻、网页、图片等业务。

每个业务应用负责相对独立的业务运作。

业务之间通过消息进行通信或者共享数据库来实现。

数据库的水平、垂直拆分

我们的网站演进的变化过程,交易、商品、用户的数据都在同一个数据库中,尽管采取了增加缓存,读写分离的方式,但是随着数据库的压力持续增加,数据库的瓶颈仍然是个最大的问题。

因此我们可以考虑对数据的垂直拆分和水平拆分。

垂直拆分

把数据库中不同业务数据拆分到不同的数据库。

水平拆分

把同一个表中的数据拆分到两个甚至跟多的数据库中,水平拆分的原因是某些业务数据量已经达到了单个数据库的瓶颈,这时可以采取讲表拆分到多个数据库中。

服务拆分

这时我们发现各个业务应用都会使用到一些基本的业务服务,例如用户服务、订单服务、支付服务、安全服务,这些服务是支撑各业务应用的基本要素。

我们将这些服务抽取出来利用分部式服务框架搭建分布式服务。

阿里的Dubbo是一个不错的选择.

理解分布式-集群-微服务

分布式

分布式服务顾名思义服务是分散部署在不同的机器上的,一个服务可能负责几个功能,是一种面向SOA架构的, 服务之间也是通过rpc来交互或者是webservice来交互的。

逻辑架构设计完后就该做物理架构设计,系统应用部署在超过一台服务器或虚拟机上,且各分开部署的部分彼此通过各种通讯协议交互信息,就可算作分布式部署,生产环境下的微服务肯定是分布式部署的,分布式部署的应用不一定是微服务架构的,比如集群部署,它是把相同应用复制到不同服务器上,但是逻辑功能上还是单体应用。

案例

在架构演变中的数据库服务器和应用服务器分离实际就是一种分布式的方式部署;服务之间的职责各有不同;

通俗解释

多台服务器,但负责的功能职责不一样

集群

集群就是多个服务之间的职责相同,对于集群来说如果一个节点出现了问题,那么就可以让其他的节店顶上

案例场景

在架构演变中的使用集群改善应用服务器性能(应用服务器集群和缓存服务器集群)实际就是一种集群的方式部署

通俗解释

多台服务器,但功能一样

微服务

微服务关注:架构设计方式;

分布式关注:系统部署方式(两者概念不同)

主要是基于项目的业务模块进行细节化的拆分;

把整个项目可以基于模块,功能拆分为单独的系统

案例

通俗解释

微服务主要针对于应用层面 小项目是基于整体项目拆分的

系统架构设计之高并发

高并发原则之拆分原则

在系统设计初期,是做一个大而全的系统还是按功能模块拆分系统,这需要根据环境权衡;

如果项目只是一个人就不要拆分,如果是项目比较大如京东,淘宝这样的系统访问量是非常大的,而且设计时投入的资源足够就可以按功能拆分系统

拆分的维度

系统维度

按照系统功能业务拆分,比如商品系统、购物车、结算、订单系统等。(根据功能业务拆分模块)

功能维度

对一个系统进行功能再拆分,比如,优惠券系统可以拆分为后台券创建系统、领券系统、用券系统等。(针对于一个系统中的功能再次拆分,例如:秒杀)

读写维度

根据读写比例特征进行拆分。比如,商品系统,交易的各个系统都会读取数据,读的量大于写,因此可以拆分成商品写服务、商品读服务;读服务可以考虑使用缓存提升性能:写的量太大时,需要考虑分库分表;有些聚合读取的场景,如商品详情页,可考虑数据异构拆分系统,将分散在多处的数据聚合到一处存储,以提升系统的性能和可靠性。(根据读写比 商品的读服务 商品的写服务)

模块维度

比如,按照基础或者代码维护特征进行拆分,如基础模块分库分表、数据库连接池等.

代码结构般按照三层架构 (Web、Service、 MODEL)进行划分。(基于代码,基础,特征;MVC三层架构)

AOP维度

根据访问特征,按照AOP进行拆分,比如,最典型的例子就是权限,配置(权限,日志,配置)

拆分体系图

AKF扩展立方体(参考《The Art of Scalability》),是一个叫AKF的公司的技术专家抽象总结的应用扩展的三个维度。

理论上按照这三个扩展模式,可以将一个单体系统,进行无限扩展。

X 轴 :指的是水平复制,很好理解,就是讲单体系统多运行几个实例,做个集群加负载均衡的模式。

Z 轴 :是基于类似的数据分区,比如一个互联网打车应用突然或了,用户量激增,集群模式撑不住了,那就按照用户请求的地区进行数据分区,北京、上海、四川等多建几个集群。

Y 轴 :就是我们所说的微服务的拆分模式,就是基于不同的业务拆分。

场景说明:比如打车应用,一个集群撑不住时,分了多个集群,后来用户激增还是不够用,经过分析发现是乘客和车主访问量很大,就将打车应用拆成了三个乘客服务、车主服务、支付服务。三个服务的业务特点各不相同,独立维护,各自都可以再次按需扩展

高并发原则之服务化

概念

服务主要是指相对独立、功能内聚的一组业务,数据自我包含,对外提供标准化的业务功能或业务数据接口。

不同服务之间是松耦合的,而服务自身也能获得更好的复用。

服务化架构就是将原有的统一型架构按业务特点进行服务拆分,再通过服务注册以及企业服务总线将服务进行串联,从而构建出整个系统。

通俗解释

服务和组件的区别

组件在功能上和服务有一定的相似性,都是完成一定的业务功能,都有内聚性。

两者不同之处主要在使用上,组件要求包含在业务系统内部,需要业务系统进行集成,如果组件的功能发生了修改,则所有引用此组件的业务系统都需要进行组件升级。

而服务则是在业务系统外部独立部署的,业务系统仅需要调用服务的接口来完成功能即可,如果服务内部的功能发生了修改,只将该服务升级即可,其调用服务的业务系统并不要修改。

通俗解释

服务和子系统的区别

服务和子系统在业务上都可完成一定的业务功能, 都可对外提供接口接入。

两者的区别主要还是在系统功能的独立性上,子系统可以独立的安装部署,提供完整的一块业务功能供用户使用,而服务则还是需要依托业务系统,它无法独立于业务系统或其他服务单独给用户使用。

通俗解释

服务化需要思考的点

总结为:进程内服务→单机远程服务→集群手动注册服务→自动注册和发现服务→服务的分组/隔离/路由→服务治理放在括号内。

高并发原则之无状态

如果设计的应用是无状态的,那么应用比较容易进行水平打展。

实际生产环境可能是这样的:应用无状态,配置文件有状态。

比如,不同的机房需要读取不同的数据源,此时,就需要通过配置文件或配置中心指定。如下图所示

有状态与无状态的区别

有状态:如果一个数据需要被多个服务共享,才能完成一笔交易,那么这个数据被称为状态。进而依赖这个“状态”数据的服务被称为有状态服务,反之称为无状态服务。

那么这个无状态服务原则并不是说在微服务架构里就不允许存在状态,表达的真实意思是要把有状态的业务服务改变为无状态的计算类服务,那么状态数据也就相应的迁移到对应的“有状态数据服务”中。

场景

例如我们以前在本地内存中建立的数据缓存、Session缓存,到现在的微服务架构中就应该把这些数据迁移到分布式缓存中存储,让业务服务变成一个无状态的计算节点。
迁移后,就可以做到按需动态伸缩,微服务应用在运行时动态增删节点,就不再需要考虑缓存数据如何同步的问题。

高并发之通信

通信方式 : 消息队列/rpc/restful

下图是无状态通信与restful Api的区别图

执行流程

  1. RestFul - REST over HTTP(S)
  2. 消息队列
  3. RPC (跨语言或单语言)

理解通信

restful

自Roy Fielding提出RESTful架构自提出以来,一直都是备受欢迎的方案,特别是在Web应用的开发中。

Fielding提出的约束虽然不是标准,但在声明我们的API为RESTful之前,应该始终遵循这些约束。

HTTP上有各种各样的REST,因为没有强制执行的标准。

开发人员可以自由选择以JSON、XML或某种自定义格式形成请求有效负载。

REST over HTTP(S)仅意味着使用REST架构风格并通过HTTP(S)发送请求

消息队列

消息队列用来解耦此不需要同步调用的服务或者订阅一些自己系统关心的变化。

使用消息队列可以实现服务解耦(一对多消费)、异步处理、流量削峰/缓冲等。

比如,电商系统中的交易订单数据,有非常多的系统关心并订阅该数据,比如,订单生产系统、定期送系统、订单风控系统等等。如果订阅者太多,那么订阅单个消息队列就会成为瓶颈,此时,需要考虑对消息队列进行多个镜像复制。

使用消息队列时,还要注意处理生产消息失败,以及消息重复接收时的场景。

有些消息队列产品会提供生产重试功能,在达到指定重试次数还未生产成功时,会对外通知生产失败。

这时,对于不能容忍生产失败的业务场景来说,一定 要做好后续的数据处理工作,如持久化数据要同时增加日志、报警等。

对于消息重复问题,特别是一些分布式消息队列,出于对性能和开销的考虑,在一些场景下会发生消息重复接收,需要在业务层面进行防重处理。

RPC(跨语言或单语言)

远程过程调用在分布式系统中并不新鲜,它通过在网络上的另一个设备上执行函数/方法/过程来工作。

1. 超时和重新连接需要处理服务器崩溃,即使使用了面向连接的协议(TCP)
2. 不指定服务和客户机的绑定,具体由实现人员决定
3. RPC实现的强制性要求:
  - 被调用过程的唯一规范
  - 响应消息与请求消息匹配的规定
  - 对调用方进行服务身份验证的规定,反之亦然

消息队列与rpc选择

RestFul:一般是对外提供服务提供给web端或者其他系统调用

rpc:实时性强 要实时返回数据用rpc, 比如查看商品列表,订单列表等等,通过rpc同步实时获取数据。

mq队列:下单那里,牵涉到减库存,发短信等,这些东西用户并不需要你实时返回,用户也不关心,就放到队列mq里面,采用异步的方式处理就行了。

高并发之数据异构

数据异构

订单分库分表一般按照订单ID进行,如果要查询某个用户的订单列表,则需要聚合多个表的数据后才能返回,这样会导致订单表的读性能很低。

此时需要对订单表进行异构,异构一套用户订单表,按照用户ID进行分库分表。

另外,还需要考虑对历史订单数据进行归档处理,以提升服务的性能和稳定性。

而有些数据异构的意义不大,如库存价格,可以考虑异步加载,或者合并并发请求。

数据闭环

如商品详情就需要获取:商品品牌,商品价格(要求实时性),图片,店铺,评价等等;这些数据在微服务的拆分下可能会分为如“用户服务,商品服务,交易服务,评价服务,店铺服务,订单服务”

实现数据闭环,如商品详情页,因为数据来源太多,影响服务稳定性的因素就非常多。

最好的办法是把使用到的数据进行异构存储,形成数据团环,基本步骤如下。

因素:1. 核心就是速度需要,2. 数据分撒需要调用不同的服务,3. 网络及服务问题等

这种方式的好处就是数据的闭环,任何依赖系统出了问题,还是能正常工作, 只是更新会有积压,但是不影响前端展示。

数据闭环和数据异构其实是一个概念,目的都是事先数据的自我控制,当其他系统出现问题的时候不影响自己的系统,或者自己出问题的时候不影响其他系统。

一般通过消息队列来实现数据分发

缓存银弹

缓存对于微服务来说可谓抗流量的银弹,可总结为下:

应用场景

高并发之并发化

案例

假设一个读服务需要如下数据

如果 串行执行获取,那么需要60ms

如果A数据,B数据,数据D 三者不会依赖谁;而数据C 依赖A和B,数据E需要C的数据;那么可以通过如下方式获取。

优化后的

高并发之高可用原则

雪崩效应

除了对服务可用性的追求,微服务架构一个绕不过去的问题就是服务雪崩。

在一个调用链路上,微服务架构各个服务之间组成了一个松散的整体,牵一发而动全身,

服务雪崩是一个多级传导的过程,首先是某个服务提供者不可用,由于大量超时等待,继而导致服务调用者不可用,并且在整个链路上传导,继而导致系统瘫痪。

解决措施

限流

限流的目的是防止恶意请求流量,恶意攻击,或防止流量超出系统峰值的策略

思路:

1. 恶意请求流量只访问到cache
2. 对于穿透到后端应用的流量可以考虑使用NGINX的limit模块处理
3. 对于恶意IP可以使用nginx deny进行屏蔽。

原则是限制流量穿透到后端薄弱的应用层

降级

就是原原本需要考虑高校实时性相应数据,但是因为服务扛不住改为读缓存;或者需要获取的数据很多但是没有办法处理好则选择降级返回少量数
据。

典型生活例子:车站购票,平常与高峰期的处理

对于一个高可用服务,很重要的一个设计就是降级开关,在设计降级开关时,主要依据如下思路。

  1. 开关集中化管理:通过推送机制把开关推送到各个应用

2.可降级的多级读服务:比如

3.开关前置化:如架构从Nginx->swoft,可以讲开关前置到NGINX接入层,在nginx层做开关,请求流量不回源后端swoft应用或者只是一小部分流量回源

4.业务降级

当高并发流量来袭,在电脑系统打出设计时保障用户能下单、能支付是核心要求,并保障数据最终一致性即可。

这样就可以把一些同步调用改成异步调用,优先处理高优先级数据或特殊特征的数据,合理分配进入系统的流量,以保障系统可用。

熔断

熔断与降级的区别

切流量

可回滚(本次课程中不会讲 - 及其难 - 第二期讲)

版本化的目的是实现可审计前面加顿号,并且可回滚。

当程序或数据出错时,如果有版本化机制,那么就可以通过回滚恢复到最近-个正确的版本, 比如事务回滚、 代码库回滚、部署版本回滚、数据版本回滚、静态资源版本回滚等。

通过回滚机制可保证系统在某些场景下的高可用。

架构设计须知

在实际的工作中,不管任何一个公司均不会一开始就可以设计出合理的架构方案,而是在满足业务需求的情况下不断带带诱惑出来的这是一个持续的过程。当然如果一开始有一个好基础系统设计,未来更容易达到一个比较满意的目标。

在设计系统时,要因场景、时间而异,一个系统也不是一下子就能设计的非常完美,在资源有限的情况下,一定是先解决当下最核心的问题,预测现在未来可能出现的问题,一步步解决最头疼的问题。也就是说一个好的设计要做到,解决现有需求和问题,把控实现和进度风险,预测和规划未来,不要过度设计,从迭代中演进和完善。

在设计系统时,应该多思考墨菲定律

1. 任何事都没有表面上看起来那么简单。
2. 所有的事做起来都会比你预计的时间长。
3. 可能出错的事总会出错。
4. 如果你担心某种情况发生,那么它就更有可能发生。

在划分时,也要思考康威定律。

1. 系统架构是公司组织架构的反映。
2. 应该按照业 务闭环进行系统拆分/组织架构划分,实现闭环、高内聚、低耦合,减少沟通成本。
3. 如果沟通出现问题,那么就应该考虑进行系统和组织架构的调整。
4. 在合适时机进行系统拆分,不要一开始就把系统/服务拆得非常细,虽然闭环,但是每个人维护的系统多,维护成本高。

参考资料

标签:服务,演变,数据库,系统,SRM,拆分,服务器,架构,数据
来源: https://www.cnblogs.com/studyandstudy/p/16315987.html