SpringCloudAlibaba整合分布式事务Seata

1 整合分布式事务Seata

点击了解分布式事务Seata相关信息

1.1 环境搭建

1.1.1 Nacos搭建

点击了解Nacos原理和使用

1.1.2 Seata搭建

点击了解Seata搭建

1.2 项目搭建

1.2.1 项目示意

如下图中,alibaba-demo为外层父目录模块,call为调用模块,common为存放共同依赖实体模块,order为支持crud模块
在这里插入图片描述

1.2.2 pom.xml

1.2.2.1 alibaba-demo模块

<?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>org.example</groupId>
    <artifactId>alibaba-demo</artifactId>
    <packaging>pom</packaging>
    <version>1.0-SNAPSHOT</version>
    <modules>
        <module>common</module>
        <module>order</module>
        <module>call</module>
    </modules>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <spring.boot.version>2.6.11</spring.boot.version>
        <spring.cloud.version>2021.0.4</spring.cloud.version>
        <spring.cloud.alibaba>2021.0.4.0</spring.cloud.alibaba>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.83</version>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring.boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring.cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${spring.cloud.alibaba}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
</project>

1.2.2.2 call模块

<?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>alibaba-demo</artifactId>
        <groupId>org.example</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>call</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-loadbalancer</artifactId>
        </dependency>


        <dependency>
            <groupId>org.example</groupId>
            <artifactId>common</artifactId>
            <version>${project.version}</version>
        </dependency>
    </dependencies>

</project>

1.2.2.3 order模块

该模块中引入 spring-cloud-starter-alibaba-seata 模块

<?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>alibaba-demo</artifactId>
        <groupId>org.example</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>order</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.2.8</version>
        </dependency>
        <dependency>
            <groupId>org.example</groupId>
            <artifactId>common</artifactId>
            <version>${project.version}</version>
        </dependency>

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

    </dependencies>


</project>

1.2.2.4 common模块

<?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>alibaba-demo</artifactId>
        <groupId>org.example</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>common</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.0</version>
        </dependency>
    </dependencies>

</project>

1.2.3 配置文件

1.2.3.1 order模块

server:
  port: 8000

spring:
  application:
    name: cloud-order-demo
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/test?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true
    username: xxxx
    password: xxxx
    type: com.alibaba.druid.pool.DruidDataSource
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
        username: xxxx
        password: xxxx


mybatis-plus:
  mapper-locations: 'classpath:mapper/*Mapper.xml'
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl


seata:
  enabled: true
  tx-service-group: mygroup
  data-source-proxy-mode: AT
  service:
    vgroup-mapping:
      mygroup: default
    grouplist:
      default: 127.0.0.1:8091
  registry:
    nacos:
      application: my-stata-server
      group: SEATA_GROUP
      namespace: 5658186c-c382-453a-843e-6a490cc80480
      username: nacos
      password: nacos
      server-addr: 127.0.0.1:8848
  config:
    nacos:
      group: SEATA_GROUP
      namespace: 5658186c-c382-453a-843e-6a490cc80480
      username: nacos
      password: nacos
      server-addr: 127.0.0.1:8848
      # 此处的data-id 和服务端上的一致,服务端怎么配这里也怎么配
      data-id: seataServer.properties

注意:

  • 上面的 seata.tx-service-group: 自定义值 要和它自己 seata.service.vgroup-mapping.自定义值:default自定义值相对应
    还要和 服务端的seata.properties中的service.vgroupMapping.自定义值=default自定义值 相对应
  • 上面的seata.service.vgroup-mapping.自定义值:default要和服务端的seata.propertiesservice.default.grouplist=127.0.0.1:8091 中的 default 相对应
  • 如果启动有error报错:不能找到service.vgroupMapping.自定义值 的服务,可以把service.vgroupMapping.单独配置指定

1.2.3.2 call模块

server:
  port: 7000

spring:
  application:
    name: cloud-call
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
        username: nacos
        password: nacos


logging:
  level:
    # feign日志以什么级别监控哪个接口
    cn.feign: debug

1.2.4 OpenFeign调用

在call模块中
调整feign日志级别

import feign.Logger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class FeignConfig {

    @Bean
    Logger.Level feignLoggerLevel() {
        return Logger.Level.FULL;
    }
}

feign调用接口

import cn.entity.User;
import cn.feign.fallback.UserFeignFallbackFactory;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;

import java.util.List;

@FeignClient(value = "cloud-order-demo",fallbackFactory = UserFeignFallbackFactory.class,path = "/user")
public interface UserFeignService {

    @PostMapping("/query")
    public List<User> queryAll();

    @PostMapping("/save")
    public boolean save(User user);
}

feign回调工厂接口,可以打印详细堆栈信息

import cn.entity.User;
import cn.feign.UserFeignService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.openfeign.FallbackFactory;
import org.springframework.stereotype.Component;

import java.util.List;

@Slf4j
@Component
public class UserFeignFallbackFactory implements FallbackFactory<UserFeignService> {
    @Override
    public UserFeignService create(Throwable cause) {
        log.error("异常原因:{}", cause.getMessage(), cause);
        return new UserFeignService(){
            @Override
            public List<User> queryAll() {
                return null;
            }

            @Override
            public boolean save(User user) {
                return false;
            }
        };
    }
}

1.2.5 order模块

controller

@RequestMapping("/user")
@RestController
public class UserController {

    @Autowired
    private IUserService userService;



    @PostMapping("/query")
    public List<User> query (){
        List<User> list = userService.list();
        return list;
    }

    @PostMapping("/save")
    @GlobalTransactional
    @GlobalLock
    public boolean save (@RequestBody User user){
        boolean save = userService.save(user);
        if(save){
            long count = userService.count();
            long i = count / 0;
        }
        return save;
    }

    @PostMapping("/add")
    public int add (@RequestBody User user){
        int i = userService.insertUser(user);
        return i;
    }


}

后续的server以及mapper模块都是集成mybatisplus,没有任何代码,因此不在赘述

1.3 jdk启动问题

1.3.1 问题现象

如果是用的 jdk是在 9 以上,启动时可能报错,如下:

Caused by: java.lang.reflect.InaccessibleObjectException: Unable to make protected final java.lang.Class java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int,java.security.ProtectionDomain) throws java.lang.ClassFormatError accessible: module java.base does not "opens java.lang" to unnamed module @45752059
at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:354) ~[na:na]
at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:297) ~[na:na]
at java.base/java.lang.reflect.Method.checkCanSetAccessible(Method.java:199) ~[na:na]
at java.base/java.lang.reflect.Method.setAccessible(Method.java:193) ~[na:na]
at net.sf.cglib.core.ReflectUtils$2.run(ReflectUtils.java:56) ~[cglib-3.1.jar:na]
at java.base/java.security.AccessController.doPrivileged(AccessController.java:318) ~[na:na]
at net.sf.cglib.core.ReflectUtils.(ReflectUtils.java:46) ~[cglib-3.1.jar:na]
... 39 common frames omitted

1.3.2 解决问题

报这个错误是由于:这是由于 JDK 8 中有关反射相关的功能自从 JDK 9 开始就已经被限制了,为了兼容原先的版本,需要在运行项目时添加 --add-opens java.base/java.lang=ALL-UNNAMED 选项来开启这种默认不被允许的行为。
这个参数是 Java 9 及更高版本中引入的一个模块化系统(Jigsaw)的特性。它允许你在启动 Java 应用程序时,打开某个模块的某个包,使得其他模块可以访问这个包中的类和成员,这个参数通常用于解决Java 9 及更高版本中,由于模块化系统导致的访问限制问题。例如,一些库可能需要访问 Java 基础模块中的某些类和成员,但在默认情况下,这些访问可能会受到限制。通过添加这个参数,可以确保这些库能够正常工作。

具体来说,--add-opens 参数的作用是:

  • java.base/java.lang:表示要打开的模块和包。这里是 Java 基础模块(java.base)中的java.lang包。
  • ALL-UNNAMED:表示允许哪些模块访问这个包。这里是所有未命名的模块,即没有模块化的代码。
posted @ 2023-05-28 21:49  上善若泪  阅读(93)  评论(0编辑  收藏  举报