使用nacos动态刷新数据源导致seata异常

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用nacos动态刷新数据源导致seata异常相关的知识,希望对你有一定的参考价值。

参考技术A 在执行有@GlobalTransactional的方法时会报错,并且看起来特别不应该

在异常中能看到是获取connection出现了类不一致问题,接下来开始埋坑。。。

seata在开始保存代理数据源时有问题,导致在获取connection时爆出异常;然后就是漫长的查找debug时间,最后发现在获取connection时,seata一点问题也没有0.0

后来发现正常系统的datasource和有问题的datasource代理内容不一致,而且有问题的datasource是一个代理对象,再次猜想:代理中包裹着代理,导致异常出现

@RefreshScope 设置到了DruidDataSource上,导致DruidDataSource被cglib动态代理

在执行getConnection时,先是cglib的GenericScope.invoke执行了ReflectionUtils.invokeMethod使用了反射,导致getConnection获取的类是DruidPooledConnection而不是接口Connection,接下来被seata再次代理(SeataAutoDataSourceProxyAdvice)得到的类变成了ConnectionProxy,返回后导致出现ClassCastException异常

1.4.2 Seata以nacos作为注册中心的配置和使用

1.4.2 Seata以nacos作为注册中心的配置和使用

下载Seata 1.4.2

Seata下载连接

1. 解压Seata 1.4.2

2. Seata目录如下

3. 下载Seata Source Code

下载地址

4. 解压后找到Script目录


这个目录下的内容在配置Seata的时候需要用到

配置seata

1. 创建相关数据库和表

默认情况下, seata的存储方式是文件, 我们改为以数据库的方式存储, 这里可以不改, 看需求

建表语句

建表语句 Seata Source Code的Script目录下的server / db 里



以mysql为例

-- -------------------------------- The script used when storeMode is 'db' --------------------------------
-- the table to store GlobalSession data
CREATE TABLE IF NOT EXISTS `global_table`
(
    `xid`                       VARCHAR(128) NOT NULL,
    `transaction_id`            BIGINT,
    `status`                    TINYINT      NOT NULL,
    `application_id`            VARCHAR(32),
    `transaction_service_group` VARCHAR(32),
    `transaction_name`          VARCHAR(128),
    `timeout`                   INT,
    `begin_time`                BIGINT,
    `application_data`          VARCHAR(2000),
    `gmt_create`                DATETIME,
    `gmt_modified`              DATETIME,
    PRIMARY KEY (`xid`),
    KEY `idx_gmt_modified_status` (`gmt_modified`, `status`),
    KEY `idx_transaction_id` (`transaction_id`)
) ENGINE = InnoDB
  DEFAULT CHARSET = utf8;

-- the table to store BranchSession data
CREATE TABLE IF NOT EXISTS `branch_table`
(
    `branch_id`         BIGINT       NOT NULL,
    `xid`               VARCHAR(128) NOT NULL,
    `transaction_id`    BIGINT,
    `resource_group_id` VARCHAR(32),
    `resource_id`       VARCHAR(256),
    `branch_type`       VARCHAR(8),
    `status`            TINYINT,
    `client_id`         VARCHAR(64),
    `application_data`  VARCHAR(2000),
    `gmt_create`        DATETIME(6),
    `gmt_modified`      DATETIME(6),
    PRIMARY KEY (`branch_id`),
    KEY `idx_xid` (`xid`)
) ENGINE = InnoDB
  DEFAULT CHARSET = utf8;

-- the table to store lock data
CREATE TABLE IF NOT EXISTS `lock_table`
(
    `row_key`        VARCHAR(128) NOT NULL,
    `xid`            VARCHAR(128),
    `transaction_id` BIGINT,
    `branch_id`      BIGINT       NOT NULL,
    `resource_id`    VARCHAR(256),
    `table_name`     VARCHAR(32),
    `pk`             VARCHAR(36),
    `gmt_create`     DATETIME,
    `gmt_modified`   DATETIME,
    PRIMARY KEY (`row_key`),
    KEY `idx_branch_id` (`branch_id`)
) ENGINE = InnoDB
  DEFAULT CHARSET = utf8;

我在名为seata的数据库建立了表

2. 修改file.conf文件

进入seata目录, 进入config目录
注意: 进入的是seata的目录, 不是Source Code


3. 修改registry.conf文件

跟file.conf在同一个目录下

修改 type = “nacos”

还是这个文件找到最下面, 修改config

  • 这里namespace没有配置, 默认情况下就在public下, 如果想改, 可以自己修改, 我以最简单的方式配置

4. 把配置上传到nacos

打开Seata Source Code文件夹, 找到config-center, 进入, 打开context.txt

在context.txt文件中修改seata配置



其他不用修改, 留意一下这个

把context.txt文件中的内容上传到nacos

提前启动nacos

进入nacos目录

不双击打开

打开git bash

sh nacos-config.sh -h 127.0.0.1 -p 8848 -u nacos -w nacos
-h 是 host, 是你的nacos的ip地址, 本地就用 127.0.0.1
-p 是nacos的端口号 8848
-u 是 username 即用户名 默认都是nacos
-w 是 password 即密码 默认也是nacos

运行

运行完成


到这里就完成了配置上传nacos

Windows启动seata

默认情况下
用jdk1.8直接可以启动seata
其他版本的博主没有试过

  • 进入bin目录
  • 双击.bat文件即可

1. jdk8启动

直接双击.bat文件即可


启动成功

2. jdk17启动

  1. 编辑.bat文件, 用记事本打开
  2. 修改 %JAVACMD%

    将原来的替换为
%JAVACMD% %JAVA_OPTS% -server --add-opens=java.base/java.lang=ALL-UNNAMED -Xmx2048m -Xms2048m -Xmn1024m -Xss512k -XX:SurvivorRatio=10 -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=256m -XX:MaxDirectMemorySize=1024m -XX:-OmitStackTraceInFastThrow -XX:-UseAdaptiveSizePolicy -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath="%BASEDIR%"/logs/java_heapdump.hprof -XX:+DisableExplicitGC  -Xlog:gc:"%BASEDIR%"/logs/seata_gc.log -verbose:gc -Dio.netty.leakDetectionLevel=advanced -Dlogback.color.disable-for-bat=true -classpath %CLASSPATH% -Dapp.name="seata-server" -Dapp.repo="%REPO%" -Dapp.home="%BASEDIR%" -Dbasedir="%BASEDIR%" io.seata.server.Server %CMD_LINE_ARGS%
  1. 双击启动

3. 闪退问题

如果出现闪退, 可能是jdk版本不对, 检查一下jdk版本, jdk17启动要改配置

4. 其他配置

见下面的测试

Linux启动seata

linux不能使用jdk17启动, 使用jkd8一定是可以的, 不需要任何修改, 直接启动即可

如果使用高版本jdk, 会出下面问题

测试seata

  1. 订单服务
  2. 库存服务
  3. 订单服务通过open-feign调用库存服务
  4. 在订单服务抛出异常, 检查能不能进行回滚操作

1. 版本

父工程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">

    <artifactId>seata-sample</artifactId>
    <groupId>org.example</groupId>
    <version>1.0-SNAPSHOT</version>
    <modelVersion>4.0.0</modelVersion>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <spring.boot.version>2.6.6</spring.boot.version>
        <spring.framework.version>5.3.18</spring.framework.version>
        <spring.cloud.version>2021.0.2-SNAPSHOT</spring.cloud.version>
        <spring.cloud.alibaba.version>2021.0.1.0</spring.cloud.alibaba.version>
        <spring.data.version>2021.0.2-SNAPSHOT</spring.data.version>
    </properties>


    <dependencyManagement>
        <!--        Spring Boot-->
        <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</groupId>
                <artifactId>spring-framework-bom</artifactId>
                <version>$spring.framework.version</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <!--        Spring Cloud-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>$spring.cloud.version</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <!--        Spring Cloud Alibaba-->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>$spring.cloud.alibaba.version</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <!--        Spring Data-->
            <dependency>
                <groupId>org.springframework.data</groupId>
                <artifactId>spring-data-bom</artifactId>
                <version>$spring.data.version</version>
                <scope>import</scope>
                <type>pom</type>
            </dependency>

        </dependencies>
    </dependencyManagement>

    <repositories>
        <repository>
            <id>spring-milestone</id>
            <name>Spring Milestone Repository</name>
            <url>https://repo.spring.io/milestone</url>
        </repository>

        <repository>
            <id>spring-snapshot</id>
            <name>Spring Snapshot Repository</name>
            <url>https://repo.spring.io/snapshot</url>
        </repository>
    </repositories>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>$spring.boot.version</version>
            </plugin>
        </plugins>
    </build>

</project>

2. 总体目录

  1. 目录

  2. 子工程依赖

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

    <artifactId>seata-stock</artifactId>

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

    <dependencies>

        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-jpa</artifactId>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

        <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>
        </dependency>

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>

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

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

        Nacos配置中心动态刷新数据源

Nacos配置中心动态刷新数据源

Nacos + Gateway 实现动态刷新路由

Nacos + Gateway 实现动态刷新路由

Nacos + Gateway 实现动态刷新路由

Nacos + Gateway 实现动态刷新路由