目 录CONTENT

文章目录

Spring常见中间件

smallkun
2023-09-26 / 0 评论 / 1 点赞 / 167 阅读 / 16,259 字 / 正在检测是否收录...
温馨提示:
本文最后更新于 2023-09-26,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我删除。

Nacos

添加依赖

    <!-- web模块起步依赖-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!--        nacos的服务发现起步依赖-->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        <version>2021.1</version>
    </dependency>

添加配置文件

spring:
  cloud:
   nacos:
    discovery:
     server-addr: 127.0.0.1:8848
  application:
   name: order-provider
server:
  port: 8000

编写业务服务远程调用服务提供方获取订单的服务。

@RestController
 public class UserController {
   @Autowired
   private DiscoveryClient discoveryClient;
   @Autowired
   private RestTemplate rt ;
   @RequestMapping("getUser")
   public String getUser(){
     //获取ip
     List<ServiceInstance> list = discoveryClient.getInstances("order-provider");
     System.out.println(list);
     System.out.println(list.get(0).getUri());
     //远程调用
     String forObject = rt.getForObject(list.get(0).getUri().toString() + "/getOrder", String.class);
     System.out.println("服务的消费方。。。。。");
     return forObject;
   }
 }

多配置文件

开发阶段、测试阶段、生产阶段,不同时期配置可能不一样,例如:ip、端口、数据库,这样我们可以提供三套配置文件,每一个配置文件对应一个阶段,配置文件名字application-dev

spring:
  application:
    name: openfeign-test2
  profiles:
    active: test

分布式配置中心

用来在线管理我们的配置文件,修改配置文件之后,不用重启服务器,做到热刷新。

  1. 分布式配置中心产生的背景?
    在项目中定义配置文件,最大的缺陷?
    如果在生产环境正在运行的时候突然需要修改配置文件的话,必须重启我们的服务器。
  2. 分布式配置中心的作用
    分布式配置中心可以实现不需要重启我们的服务器,动态的修改我们的配置文件内容,
    如何判断配置文件是否发生变化 采用版本|MD5
  3. 分布式配置中心的框架有哪些:
    携程的阿波罗、Nacos(属于轻量级)、SpringCloud Config(没有界面)、携程的阿波罗(属于比较重的分布式配置)/disConfig等。
    轻量级与重量级分别表示什么意思?
    轻量级:部署、架构设计原理都比较简单,学习成本也是比较低:
    重量级:部署、架构设计、体量都是非常大,学习成本是比较高。
  4. 分布式配置中心实现原理:
    本地应用读取我们云端分布式配置中心文件(第一次建立长连接)
    本地应用读取到配置文件之后,本地jvm和硬盘中都会缓存一份。
    本地应用与分布式配置中心服务器端一致保持长连接。
    当我们的配置文件发生变化(MD5|版本号)实现区分,将变化的结果通知给我们的本地应用实时的刷新我们的配置文件。

完全百分百实现动态化修改我们的配置文件。

注意:Nacos分布式配置中心和注册中心都部署在同一个应用,就是一个单体的应用。

image-20230926195055940

基于Nacos实现分布式配置中心

Nacos是阿里巴巴开源开源框架 注册中心+分布式配置中心
替代之前Eureka和SpringConfig|携程阿波罗
添加依赖

<dependency>
   <groupId>com.alibaba.cloud</groupId>
   <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
   <version>2021.1</version>
 </dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-bootstrap</artifactId>
    <version>3.0.3</version>
</dependency>

打开nacos配置中心页面,点击添加配置
image-20230926195157735

image-20230926195204477

修改本地配置文件为bootsrap.yml,并添加config的配置。

spring:
  application:
    name: order
  cloud:
    nacos:
      server-addr: localhost:8848
      config:
        file-extension: yml

通过注解获取更新的数据

@RestController
@RefreshScope
public class HelloController {
    @Value("${server.port}")
    private String port;
    @RequestMapping("port")
    public String port(){
        return port;
    }
}

访问port接口

image-20230926195259827

在配置中心修改端口数据为9001,再次访问接口查看是否热更新了。

image-20230926195310322

image-20230926195320701

LoadBalancer

导入依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-loadbalancer</artifactId>
    <version>3.0.3</version>
</dependency>

1.注解方式

配置注解

@LoadBalanced
@Bean
public RestTemplate restTemplate(){
    return new RestTemplate();
}

调用的时候通过服务名进行调用即可

  @RequestMapping("getRibbon")
  public String getRibbon(){
     //restTemplate 他加了注解之后,就已经具备负载均衡的能力了,就可以自动帮咱们选择到底执行哪一个
     //通过服务名直接获取restTemplate底层帮我们选择
     String str = restTemplate.getForObject("http://provider01/getPro", String.class);
     return str;
 }

2.API方式

@Resource
private LoadBalancerClient loadBalancerClient;

@RequestMapping("getRibbonApi")
 public ServiceInstance getRibbonApi(){
   // 通过api去选择到底用哪个实例
   ServiceInstance choose = loadBalancerClient.choose("provider01");
   // 通过restTemplate调用指定实例
   restTemplate.getForObject(choose.getUri() + "/getPro", String.class);
   return choose;
 }

3.切换策略

创建配置类

public class LoadBalancerConfig {
    @Bean
   public ReactorLoadBalancer<ServiceInstance> reactorServiceInstanceLoadBalancer(Environment environment, LoadBalancerClientFactory loadBalancerClientFactory) {
        String name = environment.getProperty("loadbalancer.client.name");
        return new RandomLoadBalancer(loadBalancerClientFactory.getLazyProvider(name, ServiceInstanceListSupplier.class), name);
    }
}

配置

@LoadBalancerClients(defaultConfiguration = LoadBalancerConfig.class)

OpenFeign

主要是用来远程调用的,可以集成spring cloud loadbalacer 负载均衡器。支持springmvc的注解,rest风格,传参很方便。

openfeign客户端作用:是一个Web声明式的Http客户端远程调用工具,底层是封装HttpClient技术。

导包

<!--openfeign-->
<dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-openfeign</artifactId>
   <version>3.0.3</version>
 </dependency>

写服务接口写服务接口

@FeignClient("provider01")
 public interface ProviderFeignService {
   @RequestMapping("getPro")
   public String getPro();
 }

开启openfeign支持

@EnableFeignClients //开启openFiegn支持

测试

@RequestMapping("getofeign")
public String getOpenFeign(){
  return providerFeignService.getPro();
}

Gateway

  1. 什么是微服务网关

微服务网关是整个微服务API请求的入口,可以实现过滤Api接口。

作用:可以实现用户的验证登录、解决跨域、日志拦截、权限控制、限流、熔断、负载均衡、黑名单与白名单机制等。

微服务中的架构模式采用前后端分离,前端调用接口地址都能够被抓包分析到。

image-20230926202404373

在微服务中,我们所有的企业入口必须先经过Api网关,经过Api网关转发到真实的服务器中。

如果此时需要添加验证会话信息:

传统的方式我们可以使用过滤器拦截用户会话信息,这个过程所有的服务器都必须写入该验证会话登录的代码。

过滤器与网关的区别

过滤器适合于单个服务实现过滤请求;

网关拦截整个的微服务实现过滤请求,能够解决整个微服务中冗余代码。

过滤器是局部拦截,网关实现全局拦截。

Zuul与Gateway有哪些区别]

Zuul网关属于netfix公司开源的产品,属于第一代微服务网关

Gateway属于SpringCloud自研发的网关框架,属于第二代微服务网关

相比来说SpringCloudGateway性能比Zuul性能要好:

注意:Zuul网关底层基于Servlet实现的,阻塞式的Api, 不支持长连接。

SpringCloudGateway基于Spring5构建,能够实现响应式非阻塞式的Api,支持长连接,能够更好的整合Spring体系的产品,依赖SpringBoot-WebFlux。

组件名称 所属公司 组件简介
zuul Netflix 停更进维 基于servlet实现
Zuul2 Netflix 正在从新开发
gateway springcloud springcloud自研的一套非阻塞的网络异步网关 基于WebFlux实现

需求:将经过网关的请求统一转发到百度服务器

导入依赖

<dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-gateway</artifactId>
   <version>3.0.3</version>
 </dependency>

添加网关配置

server:
  port: 8888
spring:
  application:
    name: gatewaytest01
  cloud:
    gateway:
      routes:
        - id: baidu
          uri: https://baidu.com
          predicates:
            - Path= /api/baidu/**
          filters:
            - StripPrefix= 2
        - id: test02
          uri: lb://gatewaytest02
          predicates:
          	- Path= /test02/**
          filters:
          	- StripPrefix= 1

Gateway整合Nacos实现服务转发

在gateway中配置uri配置有三种方式,包括

  1. ws(websocket)方式: uri: ws://localhost:9000
  2. http方式: uri: http://localhost:8080/
  3. lb(注册中心中服务名字)方式: lb:// provider01/

Gateway支持自动将拦截匹配到的请求转发到nacos的服务中,有高可用的环境下,也自动支持负载均衡。欧克,那么接下来,咱们开始编写代码啦。。。😄

在入门项目基础上继续导入nacos服务发现坐标

<!-- nacos的服务发现起步依赖-->
 <dependency>
   <groupId>com.alibaba.cloud</groupId>
   <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
   <version>2021.1</version>
 </dependency>

修改application.yml

server:
  port: 80
spring:
  application:
    name: gateway02
  cloud:
    gateway:
      routes:
        - id: test02
          uri: lb://gatewaytest02 # 服务名 lb 负载均衡 
          predicates:
          	- Path= /test02/**  # 大写
          filters:
          	- StripPrefix= 1

Nginx与网关的区别

微服务网关能够做的事情,Nginx也可以实现。

相同点:都是可以实现对api接口的拦截,负载均衡、反向代理、请求过滤等,可以实现和网关一样的效果。

不同点:

Nginx采用C语言编写的

在微服务领域中,都是自己语言编写的,比如我们使用java构建微服务项目,Gateway就是java语言编写的。

毕竟Gateway属于Java语言编写的, 能够更好对微服务实现扩展功能,相比Nginx如果想实现扩展功能需要结合Nginx+Lua语言等。

Nginx实现负载均衡的原理:属于服务器端负载均衡器。

Gateway实现负载均衡原理:采用本地负载均衡器的形式。

GateWay解决跨域的问题

@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
    ServerHttpRequest request = exchange.getRequest();
    ServerHttpResponse response = exchange.getResponse();
    HttpHeaders headers = response.getHeaders();
    headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, "*");
    headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS, "POST, GET, PUT, OPTIONS, DELETE, PATCH");
    headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true");
    headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS, "*");
    headers.add(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS, "*");
    return chain.filter(exchange);
}

微服务中跨域的问题 不属于前端解决,jsonp 只能支持get请求。

核心点就是在我们后端。

解决跨域的方式

  1. HttpClient转发

  2. 使用过滤器允许接口可以跨域 响应头设置

  3. Jsonp 不支持我们的post 属于前端解决

  4. Nginx解决跨域的问题保持我们域名和端口号一致性

  5. Nginx也是通过配置文件解决跨域的问题

  6. 基于微服务网关解决跨域问题,需要保持域名和端口一致性

  7. 使用网关代码允许所有的服务可以跨域的问题

  8. 使用SpringBoot注解形式@CrossOrigin

配置方式跨域

spring:
  cloud:
    gateway:
      globalcors:
        cors-configurations:
          '[/**]':
            allowedOrigins: [ "http://localhost:63342" ]
            allowedMethods:
              - GET
              - POST
              - HEAD
              - PUT
              - DELETE
            allowedHeaders: "*"
            allowCredentials: true

架构说明

image-20230926203055848

Sentinel

服务保护的基本概念

服务接口保护有哪些方案?

黑名单和白名单、对IP实现限流/熔断机制、服务降级、服务隔离机制黑名单和白名单、对IP实现限流/熔断机制、服务降级、服务隔离机制

https://www.oschina.net/p/sentinel?hmsr=aladdin1e1

文档地址:https://github.com/alibaba/Sentinel/wiki/%E6%8E%A7%E5%88%B6%E5%8F%B0

服务限流

服务限流目的是为了更好的保护我们的服务,在高并发的情况下,如果客户端请求的数量达到一定极限(后台可以配置阈值),请求的数量超出了设置的阈值,开启自我的保护,直接调用我们的服务降级的方法,不会执行业务逻辑操作,直接走本地fallback的方法,返回一个友好的提示。

服务熔断

在并发量高的情况下,可能网路拥挤,超负荷,网路抖动等情况,因此有可能会发生请求响应超时,在众多微服务级联调用情况下,很可能会引发连锁效应,导致整片微服务都超时、无响应。当遇到超时无响应时,微服务不能一直等待,需要主动断开,这样才能将损失降到最低,尽量不影响其他微服务来调用此服务,这样就能防止雪崩,类似电路中的保险丝,避免整个电路瘫痪。

服务降级

在高并发的情况下, 防止用户一直阻塞等待,采用限流/熔断方式,给程序提供一个降级的方法(类似备胎),给客户端快速返回一个友好的提示,这时不会执行业务逻辑请求,直接走本地的fallback的方法。

提示语:当前排队人数过多,稍后重试~

服务的雪崩效应

默认的情况下,Tomcat或者是Jetty服务器只有一个线程去处理客户端的请求,

这样的话就是在高并发的情况下,如果客户端所有的请求都堆积到同一个服务接口上,

那么就会产生tomcat服务器所有的线程都在处理该接口,可能会导致其他的接口无法访问,短暂没有线程处理。

假设我们的tomcat线程最大的线程数量是为20,这时候客户端如果同时发送100个请求会导致有80个请求暂时无法访问,就会转圈。

image-20221123192158731

如何去证明我们的tomcat服务器只有一个线程池处理我们所有接口的请求。

打印线程名称 线程名称组合:线程池名称+线程id名称。

服务雪崩解决方案:服务隔离机制。

服务的隔离的机制

服务的隔离机制分为信号量和线程池隔离模式

  1. 服务的线程池隔离机制:每个服务接口都有自己独立的线程池,互不影响,缺点就是占用cpu资源非常大。

  2. 服务的信号量隔离机制:最多只有一定的阈值线程数处理我们的请求,超过该阈值会拒绝请求。

Sentinel 和 Hystrix区别

前哨以流量为切入点,从流量控制,熔断降级,系统负载保护等多个维度保护服务的稳定性。

前哨具有以下特征:

  1. 丰富的应用场景:前哨兵承接了阿里巴巴近10年的双十一大促流的核心场景,例如秒杀(即突然流量控制在系统容量可以承受的范围),消息削峰填谷,传递流量控制,实时熔断下游不可用应用等。

  2. 完备的实时监控:Sentinel同时提供实时的监控功能。您可以在控制台中看到接收应用的单台机器秒级数据,甚至500台以下规模的整合的汇总运行情况。

  3. 广泛的开源生态:Sentinel提供开箱即用的与其他开源框架/库的集成模块,例如与Spring Cloud,Dubbo,GRPC的整合。您只需要另外的依赖并进行简单的配置即可快速地接入Sentinel。

  4. 完善的SPI扩展点:Sentinel提供简单易用,完善的SPI扩展接口。您可以通过实现扩展接口来快速地定制逻辑。例如定制规则管理,适应动态数据源等。

image-20230926203450527

Sentinel 实现对Api动态限流

限流配置有两种方案:

  1. 手动使用代码配置 纯代码/注解的形式

  2. Sentinel控制台形式配置

  3. 默认情况下Sentinel不对数据持久化,需要自己独立持久化

Sentinel控制台启动

  1. 下载编译好的jar包https://github.com/alibaba/Sentinel/releases
  2. cmd执行
    1. java -Dserver.port=6969 -Dcsp.sentinel.dashboard.server=localhost:6969 -Dproject.name=sentinel-dashboard -jar sentinel.jar
  3. 打开控制台

image-20230926204027992

Spring cloud 基于控制台整合Sentinel

我们要将需要限流的微服务注册到sentinel控制台中。

  1. 创建微服务工程,注册到nacos中。

  2. 添加sentinel依赖

<!--nacos依赖-->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    <version>2021.1</version>
</dependency>
<!--sentinel依赖-->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-alibaba-sentinel</artifactId>
    <version>2.2.0.RELEASE</version>
</dependency>

在application.yml中加入sentinel配置信息。

server:
  port: 8000
spring:
  application:
    name: spring-cloud-sentinel01
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1
    sentinel:
      eager: true  # 开启心跳
      transport:
        dashboard: 127.0.0.1:6969 # 整合到的控制台ip+端口

启动微服务,并且在sentinel控制对其服务接口进行管理。

image-20230926204130217

限流测试

image-20230926204140365

正常访问有结果展示,如果恶意攻击会显示如下效果

image-20230926204148677

自定义返回限流提示

上面的效果虽然实现了,但是大家发现没有:

  1. 在限流配置页面资源名必须加/,并且资源名不能自定义。

  2. 限流返回的文字是系统默认的,如何自定义显示想要的结果呢?

👇欧克,那么接下来我们需要了解下sentinel提供的注解配置。👇

@SentinelResource

  • 属性:value:流量规则资源名称

  • blockHandler :熔断降级走这里

  • fallback:其他异常

@SentinelResource(value = "kill",fallback = "blockHandlerMsg")
@RequestMapping("getSecKill")
public String getSecKill() {
    return  "开始秒杀";
}
public String blockHandlerMsg(){
    return "小伙子,做点人事。";
}

全局异常处理

通过上面自定义资源名,限流后会抛出一个异常FolowException,用户直接看到错误页面,体验感太差,所以需要全局异常捕获。

@RestControllerAdvice
public class GloableException {
    @ExceptionHandler(FlowException.class)
    public String getMsg(FlowException e){
        return "您被限流了,请稍后重试。" + e.toString();
    }
}

阈值类型—线程数

一秒之内就只有一个线程才能访问。

@SentinelResource(value = "kill",fallback = "blockHandlerMsg")
@RequestMapping("getSecKill")
public String getSecKill() throws InterruptedException {
    Thread.sleep(5000);
    return "开始秒杀";
}

热点规则

改规则主要应用于秒杀流控上,可以根据用户进行限流,比普通流控规则更加精准限流。

image-20230926204251347

热点规则vip通道

Vip通道,其实就是设置例外单独设置限流的用户

image-20230926204306434

熔断降级

  • blockHandler :熔断降级走这里
  • fallback:其他异常
@RequestMapping("hello")
@SentinelResource(value = "hello",blockHandler = "block",fallback = "fall")
public String hello(){
    int a = 1/0;
    return port;
}
public String block(BlockException e){
    //查redis,或者返回错误码,具体看业务怎么设计。
    return "熔断降级"+e;
}
public String fall(){
    return "服务器错误";
}

image-20230926204332888

image-20230926204338886

Seate

image-20230926204710091

https://github.com/seata/seata

https://seata.io/zh-cn/index.html

Seata的实现原理

image-20230926204728950

角色:Transaction Coordinator 事务协调器、Transaction Manager 事务管理者、Resource Manager 资源管理器

  1. 如支付服务)执行业务时,会通过aop拦截@GlobalTransactional注解,会先查询ThreadLocal是否有XID,如果没有(表示TM),会请求TC创建一个XID,获取到XID,保存到ThreadLocal

  2. 在调用其他服务接口(如订单服务)的时候,会把XID存放到Http请求头传给RM(订单服务)

  3. RM从请求头上获取到XID,会保存到Threadlocal,并且向TC注册事务

  4. RM操作sql前,会记录前置镜像到undo_log表,然后执行sql,成功后再记录后置镜像到undo_log表(记录undo_log和执行业务sql是同一事务),然后提交事务

  5. TM调用RM返回,继续执行业务,如果异常,通知TC,然后TC通知所有事务分支进行回滚

  6. RM收到回滚通知,会执行后置镜像sql,将数据还原,然后删除当前XID中undo_log的镜像记录

  7. 如果成功,通知TC,然后TC通知所有事务分支

  8. RM收到成功通知,删除当前XID中undo_log的镜像记录

image-20230926204738696

seata下载

https://gitee.com/mirrors/Seata/tags

seata初体验

从官网下载最新版的Linux版seata-server,无需任何配置,上传到服务器,直接启动即可

image-20230926204800041

高版本seata-server官方提供了管理页面:http://你seata服务器ip:7091/,如下图所示:

image-20230926204814886

创建两个数据库并导入undo_log

创建过程省略,undo_log表参考官网,下面给出:

-- 注意此处0.3.0+ 增加唯一索引 ux_undo_log
CREATE TABLE `undo_log` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `branch_id` bigint(20) NOT NULL,
  `xid` varchar(100) NOT NULL,
  `context` varchar(128) NOT NULL,
  `rollback_info` longblob NOT NULL,
  `log_status` int(11) NOT NULL,
  `log_created` datetime NOT NULL,
  `log_modified` datetime NOT NULL,
  `ext` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

两张业务表

image-20230926204849660

创建两个SpringBoot项目

创建过程省略,下面给出核心代码

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
    <version>2021.1</version>
</dependency>

image-20230926204915589

image-20230926204927693
Tip: 注意细节

只需要在调用方加上全局事务注解,其他地方依然是本地事务注解

给两个项目添加配置

spring:
  application:
    name: gongshang
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql:///gongshang?useSSL=false
    username: root
    password: root
    type: com.zaxxer.hikari.HikariDataSource
  cloud:
    nacos:
      server-addr: 192.168.26.69:8848
server:
  port: 7000
mybatis:
  type-aliases-package: com.javasm.domain
seata:
  tx-service-group: gongshang_group
  service:
    vgroup-mapping:
      gongshang_group: gongshang
    grouplist:
      gongshang: 192.168.26.69:8091

另外一个原理同上省略

启动两个项目并测试

  1. 分别演示正常和异常情况
  2. 并观察数据库数据是否满足一致性
  3. 异常场景可以自己制造,如下图:
    1. image-20230330161147259
  4. 测试过程中可以通过debug方式,在运行过程中,可以观察到seata管理页面中展示的数据,如下图所示:

image-20230926205029525

seata高可用环境搭建

目前存在的问题

在上面例子当中,测试环境只是部署单台seata-server,事实上在生产环境中,为了满足高可用,通常会部署多台seata-server,在上述例子中,seata的注册中心和配置中心用的都是默认的file方式,如下图从官网截取的图片所示:

image-20230926205101362

查看本地配置亦是如此,如下图所示:

image-20230926205111747

综上所述:

  1. 单机版seata-server只适用于开发或测试环境,生产环境则需要满足高可用,则需部署多台seata-server
  2. 而seata-server默认使用的file方式存在的问题有:
    1. 每台seata-server都使用本地file方式存储数据,这个数据是无法在它们之间共享的,这样就不能很好控制全局事务了。
  3. 解决方式是急需有一个公共的空间来存放它们的配置数据,可以是第三方的存储方案,seata支持如下:
    1. 注册中心:file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
    2. 配置中心:file、nacos 、apollo、zk、consul、etcd3
    3. store数据:db、redis

store接入数据库

部署多台seata-server就可以共用同一个数据库数据,store存放是全局xid,全局锁等信息,如下图所示

image-20230926205136587

image-20230926205141753

image-20230926205148171

完整架构

image-20230926205204055

接入nacos

上述例子已经实现了部署多台seata-server实现了高可用环境部署,事实上若线上部署多台seata服务器,它们的配置文件如果需要修改,必须在每台机器上手动修改,如果我们能集中去管理这些配置文件,将seata-server集群做成我们若干个微服务这才是真正的实现了高可用环境搭建,如下图所示:

image-20230926205220603

我们可以将seata-server的配置文件全部提取到nacos的配置中心去统一管理,后面加seata-server服务器只用填写好nacos地址,便可以自动拉去seata-server的配置,这样即实现了配置的统一管理,如下图所示:

image-20230926205230518

**Tip:**对于配置的集中管理,其实官网给出了两种方案:

  • 上述所写既是方案一(新版才支持,官网说到从v1.4.2开始才支持,小陈老师用的目前最新版v1.6.1)
  • 方案二是通过脚本上传配置到nacos配置中心
    • 以前老版seata-server上传很快大概有近90行配置,上传速度秒传
    • 现在新版seata-server上传龟速大概有近105行配置,一行一样的上传,大概要花费3分钟左右,实在是不能忍,因此我们选择方案一

配置详情参考官网,为了方便大家复制,也给出配置:

store.mode=db
#-----db-----
store.db.datasource=druid
store.db.dbType=mysql
# 需要根据mysql的版本调整driverClassName
# mysql8及以上版本对应的driver:com.mysql.cj.jdbc.Driver
# mysql8以下版本的driver:com.mysql.jdbc.Driver
store.db.driverClassName=com.mysql.jdbc.Driver
store.db.url=jdbc:mysql://192.168.26.69:3306/seata?useUnicode=true&characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useSSL=false
store.db.user=root
store.db.password=root
# 数据库初始连接数
store.db.minConn=1
# 数据库最大连接数
store.db.maxConn=20
# 获取连接时最大等待时间 默认5000,单位毫秒
store.db.maxWait=5000
# 全局事务表名 默认global_table
store.db.globalTable=global_table
# 分支事务表名 默认branch_table
store.db.branchTable=branch_table
# 全局锁表名 默认lock_table
store.db.lockTable=lock_table
# 查询全局事务一次的最大条数 默认100
store.db.queryLimit=100


# undo保留天数 默认7天,log_status=1(附录3)和未正常清理的undo
server.undo.logSaveDays=7
# undo清理线程间隔时间 默认86400000,单位毫秒
server.undo.logDeletePeriod=86400000
# 二阶段提交重试超时时长 单位ms,s,m,h,d,对应毫秒,秒,分,小时,天,默认毫秒。默认值-1表示无限重试
# 公式: timeout>=now-globalTransactionBeginTime,true表示超时则不再重试
# 注: 达到超时时间后将不会做任何重试,有数据不一致风险,除非业务自行可校准数据,否者慎用
server.maxCommitRetryTimeout=-1
# 二阶段回滚重试超时时长
server.maxRollbackRetryTimeout=-1
# 二阶段提交未完成状态全局事务重试提交线程间隔时间 默认1000,单位毫秒
server.recovery.committingRetryPeriod=1000
# 二阶段异步提交状态重试提交线程间隔时间 默认1000,单位毫秒
server.recovery.asynCommittingRetryPeriod=1000
# 二阶段回滚状态重试回滚线程间隔时间  默认1000,单位毫秒
server.recovery.rollbackingRetryPeriod=1000
# 超时状态检测重试线程间隔时间 默认1000,单位毫秒,检测出超时将全局事务置入回滚会话管理器
server.recovery.timeoutRetryPeriod=1000

Security认证&鉴权

Elasticsearch

RocketMQ

SpringDataJPA

ShardingSphere JDBC

ShardingSphereProxy

1

评论区