1,分布式
1,概念
分布式:不同的业务模块部署在不同的服务器上或者同一个业务模块分拆多个子业务,部署在不同的服务器上,解决高并发的问题。
分布式特点:
分布性:服务部署空间具有多样性并发性:程序运行过程中,并发性操作是很常见的。比如同一个分布式系统中的多个节点,同时访问一个共享资源。数据库、分布式存储无序性:进程之间的消息通信,会出现顺序不一致问题
分布式环境下面临的问题:
网络通信:网络本身的不可靠性,因此会涉及到一些网络通信问题网络分区 ( 脑裂 ) :当网络发生异常导致分布式系统中部分节点之间的网络延时不断增大,最终导致组成分布式架构的所有节点,只有部分节点能够正常通信三态:在分布式架构里面多了个状态::成功、失败、超时分布式事务: ACID( 原子性、一致性、隔离性、持久性 )冷备或者热备:冷备份是对数据库进行脱机备份 , 在备份过程中用户无法访问数据库 , 但冷备份速度更快更安全。热备份也称为动态备份或在线备份 , 这种技术可以在系统正常运行时进行备份 , 但是效率较慢。
2,分布式SOA架构
SOA 全称为 Service-Oriented Architecture,即面向服务的架构。它可以根据需求通过网络对松散耦合的粗粒度应用组件(服务)进行分布式部署、组合和使用。一个服务通常以独立的形式存在于操作系统进程中。
SOA 架构主要有三种实体: service provider (服务提供者)、 service requestor ( 服务使用者 )和 service register ( 服务注册中心 ) 。这三种实体又有三种服务处理功能: Publish( 发布 ) 、Find( 查找 ) 与 Bind( 捆绑 )SOA架构
当垂直应用越来越多,应用之间交互不可避免,将核心业务抽取出来,作为独立的服务,逐渐形成稳定的服务中心,使前端应用能更快速的响应多变的市场需求。
优点:1,抽取公共的功能为服务,提高开发效率
2,对不同的服务进行集群化部署解决系统压力
3,基于ESB/DUBBO减少系统耦合。
缺点:
1,抽取服务的粒度较大
2,服务提供方与调用方接口耦合度较高
3,微服务
微服务架构风格是一种将单个应用程序开发为“一套小型服务”的方法,每个服务“运行在自己的进程中”,并通过轻量级机制(通常是HTTP资源API)进行通信。这些服务“围绕业务功能构建”,并通过全自动部署机制“独立部署”。
微服务是一种架构,这种架构是将单个的整体应用程序分割成更小的项目关联的独立的服务。各个微服务之间的关联通过暴露api来实现。这些独立的微服务不需要部署在同一个虚拟机,同一个系统和同一个应用服务器中。
SOA 注重的是系统集成方面,而微服务关注的是完全分离。可以理解为微服务是 SOA 架构的升华
4,微服务技术涵盖
服务集群: 主要解决高并发的,每一个服务都可能会搭建集群,每一个集群都可能有若干服务器,解决并发问题之余还是提高服务的容错率。注册中心: 主要微服务管理工作。配置中心: 为了保证大家更新系统性的配置的时候不用每一个服务器都更改。服务网关: 请求拦截以及负载均衡。
2,架构
1,单体架构
jsp+servlet+jdbc技术
ssm/ssh技术
优点:1. 学习成本低2. 部署维护成本低3. 中小型项目选择较多
缺点:1. 耦合度高技术的耦合度高代码耦合度高开发难度也大2. 维护较困难 ( 任何一点出错,导致项目直接挂掉 )3. 扩展能力差 ( 因为都在一个项目中,增加任何技术都需要考虑是否兼容 )
2,垂直拆分架构
当访问量逐渐增大,因所有请求都只走一个服务器一个地址 IO 、服务器压力也会非常大。此时单一架构应用无法满足需求,为了应对更高的并发和业务需求,我们根据业务功能对系统进行拆分。 将一些并发访问量较大的业务模块独立成一个单独的项目进行维护、这样我们就可以初步做到并发分流。
优点:1. 系统拆分实现了流量分担,解决了一部分并发问题,也可以单独打包部署了。2. 可以针对不同模块进行优化 ( 起停 )3. 方便水平扩展,负载均衡,容错率提高
缺点:1. 系统间相互独立,会有很多重复开发工作,影响开发效率。例如:支付需要使用订单的实体类。2. 各个模块之间涉及到使用对方数据的情况下需要远程调用,且调用关系极其复杂。3. 每一个项目都是一个完整的框架 ( 例如 SSM) 、版本升级、更新信息等都需要做很多重复的工作才能达到统一( 苦逼运维 ) ,只要一个环节沟通不畅就会导致项目出现问题。4. 为了解决并发问题、失去了敏捷开发思想、企业收益也大打折扣
3,分布式架构
根据业务功能对系统进行拆分,每个业务模块作为独立项目开发,称为一个服务。同时逐渐形成稳定的服务中心,使前端应用能更快速的响应多变的市场需求,用于提高业务复用。
对比垂直拆分架构有了服务治理的概念,那么主要治理什么?1. 服务拆分粒度如何?2. 服务集群地址如何维护?3. 服务之间如何实现远程调用?4. 服务健康状态如何感知?
4,微服务架构
springboot 实现了框架的集成和轻量化和依赖的管理,所以微服务的侧重点才能几乎忽略框架而去做服务治理。 所以没有dubbo 与 springcloud , springboot 可以自嗨,如果没springboot 微服务直接垮掉!!微服务是一种经过良好架构设计的分布式架构解决方案。
特征:
1. 单一职责:微服务拆分粒度更小,每一个服务都对应唯一的业务能力,做到单一职责,避免重复业务开发2. 面向服务:微服务对外暴露业务接口3. 自治:团队独立、技术独立、数据独立、部署独立4. 隔离性强:服务调用做好隔离、容错、降级,避免出现级联问题
3,SpringCloud
1,概述
SpringCloud使工具与Spring框架无缝集成,降低开发人员构建微服务时的技术难度与成本。
2,技术选型
服务注册与发现Spring Cloud 提供了 Eureka 、 Consul 、 Zookeeper 等多种服务注册与发现的组件,使得微服务之间的互相发现变得更加容易。通过注册中心,微服务可以自动注册和注销,同时也可以查询其他服务的信息,实现服务之间的通信和协调。负载均衡Spring Cloud 提供了 Ribbon 和 Spring Cloud Loadbalancer 两种负载均衡的组件,可以根据不同的负载均衡策略,将请求分配给不同的微服务实例,提高了系统的可用性和性能。服务熔断和降级Spring Cloud 提供了 Hystrix 和 Resilience4j 两种服务熔断和降级的组件,可以在微服务出现故障或不可用时,快速切换到备用服务或返回默认响应,保证了系统的稳定性和可靠性。网关路由Spring Cloud 提供了 Zuul 和 Spring Cloud Gateway 两种网关路由的组件,可以将所有的微服务请求统一通过网关,实现请求转发、路由、负载均衡和安全验证等功能。配置中心Spring Cloud 提供了 Config Server 组件,可以将所有的微服务配置信息集中管理,同时支持动态刷新和版本控制,方便系统的配置和管理。分布式追踪Spring Cloud 提供了 Sleuth 和 Zipkin 两种分布式追踪的组件,可以对微服务之间的调用进行监控和追踪,帮助开发人员快速诊断和解决问题。服务代理Spring Cloud 提供了 Feign 和 Spring Cloud OpenFeign 两种服务代理的组件,可以简化微服务之间的调用,使得代码更加简洁和易于维护。服务测试Spring Cloud 提供了 Spring Cloud Contract 和 Spring Cloud Contract Verifier 两种服务测试的组件,可以对微服务之间的接口进行测试和验证,保证接口的正确性和稳定性。
3,服务拆分
将一个大项目拆分成多个小项目,每个微服务有自己的数据库。独立开发业务,数据独立,微服务将自己的业务暴露为接口,供其他微服务调用。
在一个项目中创建多个模块,通过一个父项目的依赖来管理子项目。
父项目pom文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.zbx</groupId>
<artifactId>cloud_demo</artifactId>
<version>1.0-SNAPSHOT</version>
<!--模块-->
<modules>
<module>user-service</module>
<module>order-service</module>
<module>cloud_demo_comms</module>
<module>eureka-server</module>
</modules>
<!-- 父工程需要指定打包方式为pom -->
<packaging>pom</packaging>
<!-- 1 SpringBoot的默认默认引用的父类 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.12.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<!-- 2.版本控制声明依赖包版本号及公共配置 -->
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<!-- 文件拷贝时的编码 -->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<!-- 编译时的编码 -->
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
<java.version>1.8</java.version>
<spring-cloud.version>Hoxton.SR12</spring-cloud.version>
<!-- MyBatis-plus系列 -->
<mybatis-plus.version>3.5.3.1</mybatis-plus.version>
<mybatis-plus-generator.version>3.5.2</mybatis-plus-generator.version>
<velocity-engine-core>2.2</velocity-engine-core>
<!-- 数据库驱动版本 -->
<mysql.version>8.0.16</mysql.version>
<!-- 工具包 -->
<hutool.version>5.7.10</hutool.version>
<!-- 分页工具 -->
<pagehelper.version>1.3.0</pagehelper.version>
</properties>
<!-- 2引入声明的依赖(引入但并不使用) 提前引入的目的是子项目再次使用可以不是书写版本号 -->
<dependencyManagement>
<dependencies>
<!-- SpringCloud -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<!--Maven 父子项目结构和 Java 继承一样,都是单继承,一个子项目只能制定一个父
pom。
很多时候,我们需要打破这种 单继承,就使用type+import -->
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- SpringBoot web-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.7.11</version>
</dependency>
<!-- mybatis-plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
<!-- 代码生成工具 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>${mybatis-plus-generator.version}</version>
</dependency>
<!-- 代码生成模板 -->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>${velocity-engine-core}</version>
</dependency>
<!-- 数据连接驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<!--3 直接继承的依赖,所以子项目默认继承 -->
<dependencies>
<!-- 单元测试 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project>
子项目pom文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>cloud_demo</artifactId>
<groupId>com.zbx</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>order-service</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<!--父依赖中引入声明了依赖并指定版本,子依赖导入时可以不指定版本-->
<dependencies>
<!--spring-boot-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--代码自动生成-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
</dependency>
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
</dependency>
<!--mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--工具项目导入-->
<dependency>
<groupId>com.zbx</groupId>
<artifactId>cloud_demo_comms</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!--eurekak客户端依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
</dependencies>
</project>
4,远程调用
在子项目中,由于两个子项目零耦合,在查询数据方面,需要进行关联数据。写在一个项目中耦合度高。
所以将两个实体类放入一个新的工具项目中,然后定义出来,在需要使用的pom中引入依赖即可。
工具项目
pom文件
<!--将自己转为工具项目-->
<dependency>
<groupId>com.zbx</groupId>
<artifactId>cloud_demo_comms</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
在需要使用该工具项目中实体组件的项目,引入改依赖即可。
4,CAP/BASE理论
CAP理论
一个分布式系统最多只能同时满足一致性(Consistency)、可用性(Availability)和分区容错性(Partition tolerance)这三项中的两项。
一致性:所有节点在同一时间的数据完全一致。
可用性:服务在正常时间内一直可用。
分区容错性:系统在遇到某节点或者网络分区故障的时候,仍然能够对外满足可用性或一致性的服务。
为什么分区容错性时必须满足的?
当我们的数据项只在一个节点保存时,一旦出现分区,那么其他部分就访问不到这个数据了,这是不能容忍的,所以我们需要把数据分布在多个节点上,那么当出现分区后,这一数据项可能到各个区里,从而提高容错性.但是当我们把数据放在多个节点中后,又会带来数据一致性的问题,为了保证数据一致, 每次写操作就需要等待所有节点执行成功,而这等待又会带来可用性的问题。
分布式系统中满足AP的样例:Eureka
在任何时间都可用,但是可能有数据不一致的情况.
分布式系统中满足CP的样例:zookeeper
满足数据的最终一致性,但是在leader选举过程中不可用
BASE理论
BASE理论是基于CAP理论逐步演化而来的,是CP(强一致性)和AP(强可用性)权衡的结果。
BASE理论的核心思想是:即使无法做到强一致性,但每个应用都可以根据自身业务特点采用适当的方式来使系统达到最终一致性。
Basically Available(基本可用)
响应时间上的损失:正常情况下,处理用户请求需要0.5s返回结果,但是由于系统出现故障,处理用户请求的时间变成3s。
系统功能上的损失:正常情况下,用户可以使用系统的全部功能,但是由于系统访问量突然剧增,系统的非核心功能无法使用。
Soft state(软状态)
数据同步允许一定的延迟。
Eventually consistent(最终一致性)
系统中所有的数据副本,在经过一段时间的同步后,最终能够达到一个一致的状态,不要求实时。
面试题
SpringCloud与Dubbo区别
Dubbo:Dobbo结构下,服务治理功能强大,服务发现结构有高可用性,支持高访问量网站。
以Zookeeper为注册中心,保证的是cp,满足节点容错性与数据一致性。大多数是使用长连接小数据量的服务提供模式使用。如果后台业务逻辑复杂时间长而导致异步逻辑多的话,Dubbo并不适合。
SpringCloud:由众多子项目组成,提供了搭建分布式系统和微服务常用工具,满足了构建微服务所需的所有解决方案,使用便利,与其他Spring家族项目完美融合,减少成本。
1、dubbo由于是二进制的传输,占用带宽会更少
2、springCloud是http协议传输,带宽会比较多,同时使用http协议一般会使用JSON报文,消耗会更大
3、dubbo的开发难度较大,原因是dubbo的jar包依赖问题很多大型工程无法解决
4、springcloud的接口协议约定比较自由且松散,需要有强有力的行政措施来限制接口无序升级
5、dubbo的注册中心可以选择zk,redis等,springcloud的注册中心用eureka或者Consul
RPC与HTTP区别:
1、RPC要求服务提供方和服务调用方都需要使用相同的技术;而http无需关注语言的实现,只需要遵循rest规范。
2、RPC并没有规定数据传输格式,这个格式可以任意指定,不同的RPC协议,数据格式不一定相同;HTTP规定了网络传输的请求格式、响应格式。
3、Http中还定义了资源定位的路径,RPC中并不需要。
4、RPC需要满足像调用本地服务一样调用远程服务,也就是对调用过程在API层面进行封装;Http协议没有这样的要求,因此请求、响应等细节需要我们自己去实现。
5、优缺点
(1)RPC方式更加透明,对用户更方便。Http方式更灵活,没有规定API和语言,跨语言、跨平台。
(2)RPC方式需要在API层面进行封装,限制了开发的语言环境。
例如我们通过浏览器访问网站,就是通过Http协议。只不过浏览器把请求封装,发起请求以及接收响应,解析响应的事情都帮我们做了。如果是不通过浏览器,那么这些事情都需要自己去完成。
分布式:不同的业务模块部署在不同的服务器上或者同一个业务模块分拆多个子业务,部署在不同的服务器上,解决高并发的问题。
微服务:微服务是一种架构,这种架构是将单个的整体应用程序分割成小的项目,关联的独立的服务。各个微服务之间的关联通过暴露api来实现。这些独立的微服务不需要部署在同一个虚拟机,同一个系统和同一个应用服务器中。
为什么使用微服务?
1,单体项目部署成本,改动影响大,成本高。
2,无法满足快速扩容,弹性伸缩,无法适应云环境特性。
3,微服务可以针对特定服务发布,影响小,风险小,成本低
4,微服务可以频繁发布版本,快速交付需求,低成本扩容,弹性伸缩,适应云环境