ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

springcloud

2021-05-01 14:03:20  阅读:305  来源: 互联网

标签:调用 服务 请求 springcloud eureka 熔断 provider


SpringCloud

早期,所有东西,后台前台等等都在一个工程打成war包

容易单点挂掉,并发能力弱,代码耦合度高

扩展,不好扩展,要么都并发,但后台不需要,造成浪费

好处:维护简单

 

基于http协议,这是和dubbo的本质区别,dubbo的核心是基于RPC:远程过程调用

 

分布式,垂直拆分:功能拆分

        水平拆分:分层  web层、service、mapper

方便水平扩展

方便独立优化

解耦合

提高并发

缺点:增加成本,重复开发

 

SNAPSTOP 快照版本,随时修改

M:mileStone M1第一个里程碑版本

SR:service RELEASE 第一个正式版本  GA

 

前后台分离  ;用户后台 ,用户前台 、订单前台、订单前台 互相调用

解决了代码冗余

缺点:调用关系错综复杂、维护困难

 

SOA:注册中心,容器   服务的提供者和调用者都注册到注册中心中

 

微服务架构

粒度很小,每一个服务对应唯一的业务能力

面向服务:restfulPI接口,跟语言无关

自治:服务之间互不干扰,各自独立

 

前后端分离:提供统一的rest接口

数据库分离:各自数据源

 部署独立, 服务之间有调用,但是重启服务互不影响,利于持续集成和交付,每个服务都是独立的组件,可复用,可替换,渐低耦合,利于维护

 

Spring cloud 、 dubbo(阿里)

 

服务之间调用方式:

1、 RPC  远程过程调用,自定义数据格式  dubbo

2、 HTTP  网络传输协议,基于tcp,规定了数据格式 Spring cloud

缺点:消息封装臃肿,优点:服务的提供和调用没有技术限定,自由灵活,可以rest风格。

 

 

 

HTTp客户端工具: 处理响应请求

HTTPclient

OKHttp

URLConnection

 

Jackson

工具类  ObjectMapper 可以序列化,反序列化

 Private static final ObjectMapper mapper=new ObjectMapper();

序列化: mapper .writeValueAsString(user)

反序列化mapper .readValue(response,User.class)

 

spring的restTemplate模板工具类,实现了序列化和反序列化

 

 

微服务

Spring Cloud  

 

核心组件:   都在Netflix下

1、Eureka  :服务治理组件。包含服务注册中心、服务注册和发现机制的实现

2、Zuul:网关组件,提供智能路由,访问过滤功能

3、Ribbon: 客户端负载均衡的服务调用组件(客户端负载)

4、Feign :服务调用,给与Ribon和Hystrix的声明式服务调用组件(声明式服务调用)

5、Hystrix:容错管理组件,实现断路器,帮助服务中延迟,为故障提供容错能力。

 

Eureka使用,创建模块 ,提供者,调用者,Eureka模块注册中心

区别于zookeper不用装在linux

Eureka Server 进入自我保护机制

防止误杀服务机制,个别客户端心跳失联,认为是客户端问题,剔除客户端。

大量客户端失联,认为网络问题,进入自我保护机制。恢复心跳,自动退出自我保护机制。

 

Renew:服务续约,每隔30秒发送一次心跳来续约。

Eviction 服务剔除,Eureka客户端连续90秒没有向Eureka服务器发送服务续约,即心跳,剔除服务。

Cancel:服务下线

 

原理:

Eureka server  集群部署,异步数据同步,数据最终一致性

Service  provider  提供者  注册到eureka

Service  consumer  消费者 获取注册服务列表,消费服务

 

Eureka模块注册中心

server:
  port: 10086
spring:
  application:
    name: wxb-eureka  #作为微服务名称注入到eureka容器
eureka:
  client:
    service-url:
      defaultZone: http://localhost:10086/eureka #http://localhost:${server.port}/eureka

 

 

启动类加注解

@EnableEurekaServer//启用eureka组件服务端

 

 

 

 

提供者加依赖eureka客户端依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

配置文件:

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/mybatis1?serverTimezone=UTC
    username: root
    password: wxb123456
  application:
    name: service-provider #作为微服务的名称

eureka:
  client:
    service-url:
      defaultZone: http://localhost:10086/eureka

 

引导类 注解启用

//@EnableEurekaClient//启用客户端eureka
@EnableDiscoveryClient//发现的客户端

 

List instances=DiscoveryClient.getInstances(service-provider )

ServiceInstance   instance=Instances.get(0)

(“http://”+Instance.getHost()+”:”+instance.getPort()+”/user/”+id,User.class)

 

 

register-with-eureka: true #默认就是true
instance:
  lease-expiration-duration-in-seconds: 10  #10秒过期时间
  lease-renewal-interval-in-seconds: 5 # 5秒一次心跳 心跳时间

 

服务端配置文件中

server:
  enable-self-preservation: false  #关闭自我保护状态
  eviction-interval-timer-in-ms: 5000 #提出无效连接的间隔时间

@autowired

DiscovertClient  discovertClient 拉取所有服务信息

 

 

 

 

Ribbon 负载均衡    客户端负载均衡

提供了默认的负载均衡算法:轮询、随机、

也可以自定义负载均衡算法  加权轮询

用法:

 

1、引入依赖(消费方) :eureka  已经依赖了  配置文件

2、加上@loadBalanced

@Bean
@LoadBalanced//开启负载均衡
public RestTemplate restTemplate(){
    return new RestTemplate();

 

3、默认轮询

 

负载均衡算法=rest接口第几次请求数%服务器集群总数量 = 实际调用服务器位置下标,每次服务重启后rest接口计数从1开始

Ribbon负载均衡策略:

轮询:对所有的服务器节点按顺序分配,每个服务器的概率是等同的

 

加权轮询:对每个服务器加了权重比利,性能强劲的服务器的权重就高一些,性能弱的权重随机

重试

最低并发

可用过滤

响应时间加权重

区域权重

 

Hystrix  熔断,微服务的一种保护机制

为每个依赖调度分配一个小的线程池,如果线程池已满调用会立即被拒绝,默认不采用排队,加速失败判定时间。

用户请求将不在访问服务,而是通过线程池中的空闲线程来访问服务,如果线程已满,或者请求超时,则降级处理

服务降级处理:优先保证核心服务,非核心服务不可用和弱可用

 

请求失败,不会阻塞,不会无休止等待或直到系统崩溃,而是会至少看到一个执行结果,例如返回有好的提示信息

服务降级会导致请求失败,不会导致阻塞,最多影响这个请求,不会影响其他服务没有响应。

触发hystrix服务降级条件:1、线程池已满  2、请求超时

 

使用:(在customers  服务调用方 配置)

 

降级:

1、引入依赖  引入启动器

2、配置文件(可以不加)

设置Hystrix的超时时间

默认是1秒,开发环境够用

生产环境的话,修改:timeoutInMilliseconds: 6000ms

 

3、启动类加注解@EnableCicuitBreaker    //开启熔断

4、两个方法产生关联 加注解@HystrixCommand(fallbackMethod=”熔断方法名”)  使用全局的熔断方法可以改成@HystrixCommand  

5、局部的熔断,熔断和被熔断方法的返回值和参数列表一致

Public  String 熔断方法名 (Long   id){

  Return “服务正忙,稍后再试”;

}

 

想要制定熔断方法为全局的

在类上面加注解@defaultProperties(defaultFallback=”熔断方法名”)

多个熔断方法,全局的:返回值和被熔断的方法一致,参数列表为空

Public  String 熔断方法名 (){

  Return “服务正忙,稍后再试”;

}

 

 

消费者consumers引导类上注解好几个,可以使用组合注解

@SpringBootApplication
@EnableDiscoveryClient//发现的客户端
@EnableCircuitBreaker//开启熔断器

可以用组合注解代替

@Spring CloudApplication

 

服务熔断:熔断器,断路器

可以弹性容错,情况好转之后,可以自动重连

先是拒绝所有后续请求,一段时间后,允许部分请求,调用成功则恢复,否则继续断开

熔断:

熔断器的三个状态:

1、闭合状态

2、打开状态:对请求计数,失败请求百分比达到阈值,触发熔断,默认阈值50%,请求次数不低于20次

3、半开状态 open之后,休眠时间:5秒,进入半开,若请求都是健康的,关闭熔断器。否则继续休眠计时

 

可以修改参数:

出发熔断的最小次数,默认20、熔断失败的请求最小占比,50%、休眠时间,默认5秒

 

流程:

1、每次调用创建hystrixcommand,依赖调用封装在run方法,执行execute同步或异步调用

2、调用是否缓存,缓存直接返回结果,没有缓存,判断熔断器是否打开

3、打开熔断器,getfallback降级逻辑

4、没打开熔断器,判断线程池/队列/信号量是否跑满,满了进入fallback降级逻辑

5、没跑满调用hystrixcommand的run方法,执行依赖逻辑,没有出现异常,继续,否则fallback降级,没有超时返回调用结果,超时进入fallback降级。

 

两种资源隔离方式

1、线程池隔离模式  线程池存储请求,处理请求,设置超时时间,为每一个线程申请线程池,消耗资源,可以应对突发洪流(处理不完,放入线程池慢慢处理)

2、信号量隔离模式  使用原子计数器/信号量 来记录当前多少个线程运行,请求到来先判断计数器数值,超过设置的最大线程个数,放弃新的请求,不超过,计数器+1,请求返回计数器-1,无法应对突发洪流

Feign

伪装,把rest请求进行隐藏,伪装成类似于springmvc的controller一样,不用拼接url、参数,一切交给feign

 

使用:

常见一个接口,在接口上加一些注解即可

Springcloud中feign支持springmvc注解,整合了Ribbon和eureka

 

1、引入依赖  openfeign

2、引导类上加注解 @EnableFeignClients  //启用feign组件

去掉

/*@Bean
@LoadBalanced//开启负载均衡
public RestTemplate restTemplate(){
    return new RestTemplate();

*/

不用再注入restemplate。去掉之前的hystrix的熔断代码

1、创建一个接口  xxxclient

2、加上注解@ FeignClient(“微服务的名称”)

3、接口中加上方法

4、注入接口到controller中  

 

有feign,默认关闭了Hystrix熔断,使用需要手动开启

Feign:

 Hystrix:

   Eanabled: true

 

Feign使用熔断

新建一个类xxxfallback 实现 xxxclient接口,实现熔断方法

接口的注解修改为:

@ FeignClient(value=“微服务的名称”,fallback=”xxxfallback ”)

 

把xxxfallback类上面加上 @Component  注入容器

 

Zuul网关

路由: 分发不同的微服务

负载均衡:同一个微服务的不同实例

 

保证对外服务的安全性,需要实现对外访问的权限控制,每个微服务都需要,破坏了restfulapi的无状态特点

无法直接服用既有接口

使用网关,所有请求都先经过zuul网关

具备服务路由,负载均衡,权限控制

核心:是一系列的过滤器

功能:身份认证与安全、审查与监控、动态路由、压力测试、静态响应处理、负载均衡、多区域弹性

 

创建zuul模块

配置文件

server:
  port: 10001
spring:
  application:
    name: wxb-zuul
zuul:
  routes:
    service-provider: #路由名称,随便起,习惯上写服务名
      path: /service-provider/**
      url: http://localhost:8080  #路由到 http://localhost:8080这个地址

 

启动类加注解 @EnableZuulProxy  //启用zuul组件

 

多个路径,负载均衡

需要把zuul注入到eureka中

1、添加eureka依赖

2、配置文件

加上eureka.client.service-url-defaultZone: http://localhost:100086/eureka

3、启用eureka  @EnableDiscoveryClient

4、

server:
  port: 10001
spring:
  application:
    name: wxb-zuul
zuul:
  routes:

 service-provider: #路由名称,随便起,习惯上写服务名
      path: /service-provider/**

       ServiceId: service-provider


   

 

或者  常用

  routes:
     service-provider:  /service-provider/**   #可以随便改/user/**

     service-consumer: /consumer/**

 

或者不写,访问路径直接自己加上 localhost:10001service-provider/user/1  即可

 

还可以加  /api  区分是否请求经过网关  可以不要(专业性)

routes:
     service-provider:  /service-provider/**   #可以随便改/user/**

     service-consumer: /consumer/**

Prefix: /api

路径前面必须加/api才能访问

 

Zuul过滤器:请求拦截

流程:

请求--》pre  类型过滤器---》route filter--》post filters  ---响应

Pre、routing 出现异常的话---》error filter--post filter-》响应  error filter 本身异常,执行postfilter--响应

 

post filter 本身异常--》error filter--》响应

 

自定义:

1、一个类loginFilter  继承 ZuulFilter 接口,重写四个方法  类上加@component 放入spring容器

public abstract String filterType();  return “pre”;
//执行顺序,返回值越小,执行顺序越高

public abstract int filterOrder();   return  10;

//是否执行该过滤器:true:执行

boolean shouldFilter();  return true;
//编写过滤器逻辑
Object run() throws ZuulException{

Return  null;//什么都不做

//初始化zuul网关的 上下文对象

Requestcontest con=Requestcontest.getCurrentContext();  

 

//获取对象

Request  rr=Con.getRequest();

//获取参数

String  ss=Rr.getParameter(“”)

Con.setSentZuulResponse(false)    //不转发请求

//设置状态码,401,身份未认证

Con.setResponseStatusCode(HttpStatus.SC_UNAUTHORIZED)

Con.setResponseBody(“request error”)  //设置响应提示

}

 

2、过滤器类型 : pre routing、post、error

 

声明式:直接装配  和 编程式

 

 

 

 

 

 

浏览器browser---》consumer-----》provider

Consumer、provider都去注册中心Eureka,provider可能调用别的provider、redis、MySQL、elasticSearch等等   Consumer还可能调用别的provider

 

Eureka的时候 项目的返回从Json变为了Xml

SpringBoot项目中集成了EurekaServer,又需要jackson-dataformat-xml这个依赖 ,

可以将实体转换为xml也可以转换为json,根据发起请求的request头中Accept,application/xml在最后匹配json的*/ *前面,优先级高过json,所以返回了XML

解决:在请求的Mapping上加上produces = { “application/json;charset=UTF-8” }

 

Ribbon 客户端的负载均衡

Provider以集群的方式启动

增加端口号;1000\2000\3000 三个provider

1、Eclipse 直接修改配置文件的端口,main方法启动,在dashboerd看不到,

  或者启动一个端口之后 Run As--》run configurations--》选择项目--》new configuration---》

选择arguments标题栏,program arguments中输入 --server.port=需要的端口号即可

2、Idea 不修改配置文件,在edit configuration 中 点击 copy configuration

在environment 选项下面,program arguments中写: --server.port=需要的端口号即可

 

Feign:声明式远程调用

 

// 表示当前接口和一个provider对应,springboot-provider指定要调用的微服务名称
@FeignClient("springboot-provider")
public interface EmployeeRemoteService {

 

主启动类加注解@EnableFeignClients

 

400:参数类型不匹配,需要的参数没有传参,违反数据校验规则

Common和provider传参都需要加注解     

用来获取请求参数的注解@RequestParam @PathVariable @RequestBody不能省略,

简单类型

@RequestMapping("/provider/get/emp/list/remote")
List<Employee> getListRemote(@RequestParam("keyword") String keyword);

复杂类型:

@requestBody(Employee employee)

 

Hystrix:熔断、降级

微服务很多,多个调用同一个微服务,被调用的微服务超时,都开始等待

一个问题蔓延至整个系统。

 

CAP

一致性+可用性+P:分区容错性(必须的) 一致性+可用性(保证一个)

雪崩:某个服务出现故障,导致服务级联调用而引发雪崩

 

Provider的提供方案:

熔断:一段时间内侦测到多个类似错误,会强迫之后的多个调用快速失败,不在访问远程服务器,防止应用不断尝试,让程序继续执行,防止超时出现

 

使用ResultEntity作为返回值类型,成功失败返回同一个类型,result属性判断成功还是失败,失败:message   成功:data返回数据

 

Consumer的提供方案:

降级:防止用户一直等待,使用降级方式,调用FallBack(返回友好提示,不会去处理请求) 

              例如: 当前请求人数过多,请稍后重试

 

Dubbo可以整合hystrix

 

<!--provider熔断-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>

 

主启动类上面加注解:// 开启断路器功能 @EnableCircuitBreaker

// @HystrixCommand 指定当前方法出问题指定另一个备用方法
@HystrixCommand(fallbackMethod = "getEmpWithCircuitBreakerBackUp")
@RequestMapping(value = "/provider/get/emp/circuit/breaker",produces = { "ap

 

public ResultEntity<Employee> getEmpWithCircuitBreakerBackUp(@RequestParam("sinal") String sinal){

 

 

Consumer 客户端降级

1、实现consumer端 实现服务降级功能  

2、实现fallbackFactory接口时,要传入@FeignClient标记的接口类型
3、在create() 方法中返回@FeignClient标记的接口类型的对象,当provider调用失败
*               会执行这个对象的对应方法

 

public class MyFallBackFactory implements FallbackFactory<EmployeeRemoteService> {
    public EmployeeRemoteService create(final Throwable throwable) {

 

 

@FeignClient(value = "springboot-provider",fallbackFactory = MyFallBackFactory.class)
public interface EmployeeRemoteService {

 

feign:
  hystrix:
    enabled: true    # 开启降级

 

监控: provider

1、加入监控依赖  spring-boot-starter-actuator

 

2、配置application.yml

management:
  endpoints:
    web:
      exposure:
        include: hystrix.stream

 

3、创建监控工程

加入依赖

spring-cloud-starter-netflix-hystrix-dashboard

在主启动类上面加注解

// 启用仪表盘
@EnableHystrixDashboard

配置文件配置:

server:
  port: 8000
spring:
  application:
    name: springcloud-dashboard

监控访问地址:http://localhost:8000/hystrix

使用:

1、直接查看数据(provider)访问地址:localhost:1000/actuator/hystrix.stream    (1000是provider的端口号)  不方便,因为一直在监控,数据不断增加

2、第二种访问  http://localhost:8000/hystrix ,在页面输入localhost:1000/actuator/hystrix.stream   ,Delay设置毫秒,Title标题,使用默认值即可

 

 

Zuul网关:提供给一个统一的入口

没有的话,直接访问provider,有网关的话

请求到达网关

 

1、客户端直接请求不同的微服务,增加复杂性

2、存在跨域请求www.a.com  www.b.com  浏览器跨域存在阻碍(出于安全考虑)

3、认证复杂,登陆问题:1、共享session 2、单点登录

4、难以重构,可能需要新的微服务

 

Zuul: 请求的路由  、 过滤

请求---》zuul----》请求特征---》微服务名称-----》Eureka---》具体的微服务

依赖:  spring-cloud-starter-netflix-eureka-client

spring-cloud-starter-netflix-zuul

配置文件:

server:
  port: 9000

spring:
  application:
    name: springcloud-zuul
eureka:
  client:
    service-url:
      defaultZone: http://localhost:5000/eureka/

启动类:

// 开启zuul网关代理
@EnableZuulProxy

初步访问:服务名称最好小写,访问也要小写

http://localhost:9000/微服务名称/目标为服务具体功能地址

例如:http://localhost:9000/springcloud-feign-consumer/feign/consumer/test/fallback?signal=1

可以是自定义路由规则,代替微服务名称(不想暴露微服务名称)

在配置文件中配置:

zuul:
  routes:
    employee:
      service-id: springcloud-feign-consumer
      path: /my/**

此时通过:微服务名称

http://localhost:9000/springcloud-feign-consumer/feign/consumer/test/fallback?signal=1

和  路由

http://localhost:9000/my/feign/consumer/test/fallback?signal=1

都可以访问。

可以设置禁用服务名称访问

ignored-services:           # 禁用服务名称访问  ,忽略所有  ignored-services: '*'
  -  springcloud-feign-consumer

还可以在禁用的基础上增加前缀

ignored-services:  ‘*’       // 所有微服务都不可以通过名称访问

prefix: /bbb   

 

还可以

server:
  port: 9000
  servlet:
    context-path: /aaa         # 属于springboot 的application tomcat 访问之前加此路径

 

这是通过zuul访问的规则路径

 

还可以不通过zuul直接:http://localhost:7000/feign/consumer/test/fallback?signal=1  来访问

 

请求---》gateway(过滤器)-----》微服务

转发只允许在自己工程内部才可以

重定向可以访问新的资源

 

ZuulFilter

 

线程本地化技术  threadLocal

一个请求访问另一个请求:session域、application域等(横向)

同一个线程内部:可以直接调用方法,通过传参;还可以通过threadlocal技术先set()  使用再 get()

 

springcloud要基于springboot开发

 

Springcloud分布式架构一站式解决方案,可以天然基于spring全家桶开发

Dubbo 熔断降级需要hystrix

 

阿里的Nacos加入spring,官方推荐Nacos代替eureka作为注册中心

 

Idea项目工程导入eclipse

找到项目——复制,删除idea特征,留下maven特征(src+Pom.xml目录)通过eclipse的import --》maven  已存在的项目即可,最好把项目复制到工作区,maven导入的不会复制项目再工作区。

 

 

 

Seata   分布式事务解决方案

全局的数据一致性问题

http://seata.io/zh-cn/    1+3

全局唯一的事务ID  transation ID  XID

三组件:

Transation Coordinator  TC   事务协调者  驱动全局事务的提交回滚

Transation Manager    TM   事务管理器  开始全局事务的提交回滚

Resource  Manager    RM  资源管理器  管理分支事务,驱动分支事务提交回滚

 

1、TM向TC申请开启一个全局事务@GlobalTransactional,创建成功并生成一个全局唯一XID

2、XID在微服务调用的上下文中传播

3、RM向TC注册分支事务,将其纳入XID对应全局事物的管辖

4、TM向TC发起针对XID的全局提交或回滚决议

5、TC调度XID下辖的全部分支事务完成提交或回滚

 

下载网址:https://github.com/seata/seata/releases

使用:本地@Transational  全局@GlobalTransational

 

下载使用1.1.0版本

1、备份file.conf配置文件

2、修改:自定义事务组名称+事务存储模式为DB+数据库连接信息

3、修改service模块和store模块

 

 

先启动nacos-server.cmd

再启动seata-server.bat

三个微服务:订单==库存==账户

用户下单==》创建一个订单==》远程调用库存服务扣减库存==》远程调用账户扣减余额==》订单状态修改成已完成。

跨越三个数据库,两次远程调用,必然存在分布式事务问题

 

 

@GlobalTransactional

没有加注解,超时超时之后,出现超时异常,库存减少,钱减少,但是订单显示未完成。

Feign有超时重试机制,可能多次扣减。

 

@GlobalTransactional(name = "wxb-create-order",rollbackFor = Exception.class)

异常:统统回滚   异常之后,没有插入写操作

 

Seata原理

Tc:seata服务器

Tm:@GlobalTransactional 事务发起者

Rm:一个数据库就是一个rm  事务的参与方

 

默认AT模式:无侵入自动补偿,阿里云 GTS

TCC模式:可与AT混用,更灵活

SAGA模式:长事务,每个参与者都提交本地事务。无锁,高性能,不保证隔离性

XA模式(开发中)

 

一阶段

Seata拦截业务SQL,,业务更新前,before images  前置镜像

执行业务SQL,更新业务数据

更新之后,after images 后置镜像 生成行锁(locK_table表)

所有操作再一个数据库事务完成

二阶段

顺利,seata把一阶段的的快照数据和行锁删除,解锁,清理数据

异常:二阶段回滚,回滚一阶段已经执行的业务SQl,反向补偿,before images 还原数据,之前还需要校验脏写,如果有,转人工处理。还原之后,删除before images、after images   和行锁   删除un_log 表数据

 

 

 

Cap理论

不能同时满足c、a、p(必须保证)

一致性:强一致性,每次读写返回的值都是最新的,结果一致。

可用性:发出请求总能得到数据,不一定是最新数据

分区容错性:分布式系统,不同的节点,遇到分区故障,可以满足一致性和可用性,不能同步,但是也可以容忍。除非网络全部故障。

CA:放弃分区容错,一个整体应用,不是分布式,单体架构

CP:放弃可用性,保证一致性  例如 zookeeper,redis

AP:保证可用性  例如eureka,淘宝,最终一致性。

 

强一致性:复制是同步的

弱一致性:复制是异步的,即使过了不一致时间窗口期,读取的也不一定是最新值,存在问题。12306买票

 

最终一致性:弱一致性的特殊形式,没有更新的条件,最终访问的是最后的值。

随着时间推移,数据最终一致。

 

一般采用ap  保证可用性,采用最终一致性。

 

Base理论

BA:基本可用  和高可用的区别:基本可用(故障时)可以适当延长响应时间。

S:柔性状态  数据存在中间状态,同步中,正在同步。

E:最终一致性  一段时间后,数据必须一致。

 

分布式事务协议

二阶段提交2PC 常用方案    协调者一个 和  参与者 多个

1、准备阶段  投票阶段  可以不可以提交,记录日志,没有提交事务  ,同意/终止

2、提交阶段  所有参与者返回同意,发出commit请求,发送ack 完成,协调者收到所有的ack,完成事务。如果返回消息是 终止,或者超时未返回,撤销事务,告诉所有的参与者根据一阶段日志 ,回滚事务。无论成功与否,事务在二阶段都会完成。

优点:数据强一致性。

缺点:事务节点都是阻塞型  底层是锁 占用资源   需要补充超时机制,否则失联会一直阻塞。数据一致性问题,协调者或者某个参与者宕机,协调者发出消息,但是唯一接收消息的参与者宕机,即使再选举出新的协调者,事务的状态不确定。

 

三阶段提交 3PC  二阶段的改进

引入超时机制、插入准备阶段,保证提交之前各个节点状态一致。

多了先询问能不能操作执行,再执行事务,不提交,反馈之后再提交。

1、cancommit  询问  返回yes/no    no/超时  直接中断事务。

2、Precommit  协调者根据参与者反馈进行操作  事务预提交,执行事务操作,但不提交事务,记录事务日志。返回ack,等待最终指令。

3、执行提交。二阶段  失败 (no/超时)中断事务  协调者撤销请求,回滚。

 

缺点:第三阶段:超时之后,会继续事务提交,造成数据不一致。

 

 

分布式方案:

1、TCC

2、全局消息

3、分布式事务 seata

 

TCC  事务补偿机制  二阶段提交(强一致性)

byteTcc(停止更新)

Try尝试    锁定资源

confirm确认  执行业务,释放锁

Cancel 取消  出问题,释放锁

 

库存、订单

一、Try:库存100,要购买2   先检查库存是否足够,冻结购买的库存2,创建订单,状态为待确认。

二、Confirm/cancle:根据try的服务是否正常 ,执行confirm或cancel,如果执行confirm或cancel失败,会一直重试。(保证了数据的强一致性)并发性一般。

 

存在性能瓶颈、业务耦合度较高,增加开发成本

数据最终一致性(基于confirm和cancle幂等性)

可靠性:集群解决单点故障

 

Seata  at模式和tcc模式

AT模式:基于本地ACID事务的关系型数据库

TCC模式:不依赖底层数据库,数据库日志表、成功批量清理回滚日志、失败自动补偿,数据回滚。

自定义的prepare、commit、rollback逻辑

标签:调用,服务,请求,springcloud,eureka,熔断,provider
来源: https://www.cnblogs.com/wxb1204/p/14641068.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有