springcloud alibaba integration seata

Table of contents

1. Seata server construction

1. Download seata-server

2. Start the seata server

1. Modify the file.conf in the config directory

2. Modify registry.conf in the config directory

 3. Mysql creates a new library and table

4. Initialize seata configuration

1. Modify the config.txt configuration

2. Add the configuration to nacos

5. Start seata

2. Microservice integration seata

1. Create a new microservice and introduce related dependencies

1. Microservice pom.xml

2. Seata module pom.xml

2. Submodule pom.xml

3. Submodule yml configuration

4. Create a database

5. Business module

1. Inventory service

2. Order module

6. Test verification


1. Seata server construction

1. Download seata-server

Select the seata-server version of the microservice supporting version to download, and select the windows or linux version as needed.

Releases · set/set · GitHub

Component version comparison table:

To build locally, I downloaded the Windows version 1.3.0

2. Start the seata server

The actual use needs to save some relevant information of the transaction to the database, and the relevant configuration needs to be modified before starting seata.

1. Modify the file.conf in the config directory

mode changed to db

The db module modifies the url, user, password of the database


## transaction log store, only used in seata-server
store {
  ## store mode: file、db、redis
  mode = "db"

  ## file store property
  file {
    ## store location dir
    dir = "sessionStore"
    # branch session size , if exceeded first try compress lockkey, still exceeded throws exceptions
    maxBranchSessionSize = 16384
    # globe session size , if exceeded throws exceptions
    maxGlobalSessionSize = 512
    # file buffer size , if exceeded allocate new buffer
    fileWriteBufferCacheSize = 16384
    # when recover batch read size
    sessionReloadReadSize = 100
    # async, sync
    flushDiskMode = async
  }

  ## database store property
  db {
    ## the implement of javax.sql.DataSource, such as DruidDataSource(druid)/BasicDataSource(dbcp)/HikariDataSource(hikari) etc.
    datasource = "druid"
    ## mysql/oracle/postgresql/h2/oceanbase etc.
    dbType = "mysql"
    driverClassName = "com.mysql.jdbc.Driver"
    url = "jdbc:mysql://101.37.23.0:3306/seata"
    user = "root"
    password = "nymi@2023"
    minConn = 5
    maxConn = 30
    globalTable = "global_table"
    branchTable = "branch_table"
    lockTable = "lock_table"
    queryLimit = 100
    maxWait = 5000
  }

  ## redis store property
  redis {
    host = "127.0.0.1"
    port = "6379"
    password = ""
    database = "0"
    minConn = 1
    maxConn = 10
    queryLimit = 100
  }

}
 

2. Modify registry.conf in the config directory

This configuration is to register seata to the registration center, and the configuration of seata is persisted to the configuration center.

We use nacos as the registry and configuration center.

You need to change the type to nacos and modify the configuration under nacos respectively.

registry {
  # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
  type = "nacos"

  nacos {
    application = "seata-server"
    serverAddr = "101.37.23.0:80"
    group = "SEATA_GROUP"
    namespace = ""
    cluster = "default"
    username = "nacos"
    password = "nacos"
  }
  eureka {
    serviceUrl = "http://localhost:8761/eureka"
    application = "default"
    weight = "1"
  }
  redis {
    serverAddr = "localhost:6379"
    db = 0
    password = ""
    cluster = "default"
    timeout = 0
  }
  zk {
    cluster = "default"
    serverAddr = "127.0.0.1:2181"
    sessionTimeout = 6000
    connectTimeout = 2000
    username = ""
    password = ""
  }
  consul {
    cluster = "default"
    serverAddr = "127.0.0.1:8500"
  }
  etcd3 {
    cluster = "default"
    serverAddr = "http://localhost:2379"
  }
  sofa {
    serverAddr = "127.0.0.1:9603"
    application = "default"
    region = "DEFAULT_ZONE"
    datacenter = "DefaultDataCenter"
    cluster = "default"
    group = "SEATA_GROUP"
    addressWaitTime = "3000"
  }
  file {
    name = "file.conf"
  }
}

config {
  # file、nacos 、apollo、zk、consul、etcd3
  type = "nacos"

  nacos {
    serverAddr = "101.37.23.0:80"
    namespace = ""
    group = "SEATA_GROUP"
    username = "nacos"
    password = "nacos"
  }
  consul {
    serverAddr = "127.0.0.1:8500"
  }
  apollo {
    appId = "seata-server"
    apolloMeta = "http://192.168.1.204:8801"
    namespace = "application"
  }
  zk {
    serverAddr = "127.0.0.1:2181"
    sessionTimeout = 6000
    connectTimeout = 2000
    username = ""
    password = ""
  }
  etcd3 {
    serverAddr = "http://localhost:2379"
  }
  file {
    name = "file.conf"
  }
}
 

 3. Mysql creates a new library and table

Download the source code of the corresponding version from the official website of seata.

 Download Center

After decompression, copy the entire script directory and put it in the folder after seata-server decompression.

Enter the script/server/db directory, and run the mysql.sql script in the mysql database (seata) configured in step 1 (mysql needs to create a new database named seata first)

4. Initialize seata configuration

Open the script/config-center directory under step 3,

1. Modify the config.txt configuration

Modify service.vgroupMapping.guangzhou=default, where the configuration at guangzhou must be consistent with the microservices of the project, which will be mentioned in the subsequent application.yml.

Modify store.mode=db

Modify some database-related configurations behind store.db.

2. Add the configuration to nacos

Make sure nacos is started.

Enter the script/config-center/nacos directory,

Open git here (the .sh file can be run with git under windows)

Run the command below (replace ip and port with actual ones)

sh nacos-config.sh -h ip -p port -g SEATA_GROUP -t seata-group

5. Start seata

Enter the seata/bin directory,

Double-click the seata-server.bat file, and the cmd window will display the startup status of the seata-server.

After the startup is successful, you can see that the seata-server service has been registered on the nacos client. 

2. Microservice integration seata

1. Create a new microservice and introduce related dependencies

1. Microservice pom.xml

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <modules>
        <module>seata</module>
    </modules>
    <groupId>com.wind.springcloud</groupId>
    <artifactId>alibaba</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>alibaba</name>
    <description>springcloudalibaba</description>
    <packaging>pom</packaging>
    <properties>
        <java.version>1.8</java.version>
        <spring.cloud.alibaba.version>2.2.5.RELEASE</spring.cloud.alibaba.version>
        <spring.boot.version>2.3.11.RELEASE</spring.boot.version>
        <spring.cloud.version> Hoxton.SR8</spring.cloud.version>
    </properties>

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

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

    <dependencyManagement>
        <dependencies>
            <!--        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>
            <!--        springboot版本管理-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-parent</artifactId>
                <version>${spring.boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!--        springcloud版本管理-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring.cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

        </dependencies>
    </dependencyManagement>

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

</project>

2、seata模块pom.xml

<?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</artifactId>
        <groupId>com.wind.springcloud</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.wind.springcloud</groupId>
    <artifactId>seata</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <modules>
        <module>order-seata</module>
        <module>stock-seata</module>
        <module>alibaba-order-seata</module>
        <module>alibaba-stock-seata</module>
    </modules>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.4</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.2.3</version>
        </dependency>
        <!-- nacos服务注册发现       -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!-- 添加openfeign的依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

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

</project>

2. Submodule pom.xml

Create new submodules alibaba-order-seata and alibaba-stock-seata

pom are

<?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</artifactId>
        <groupId>com.wind.springcloud</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>alibaba-order-seata</artifactId>
    <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.20</version>
            <scope>compile</scope>
        </dependency>
    </dependencies>
    

</project>
<?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</artifactId>
        <groupId>com.wind.springcloud</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>alibaba-stock-seata</artifactId>
    <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.20</version>
            <scope>compile</scope>
        </dependency>
    </dependencies>



</project>

3. Submodule yml configuration

They are as follows, you can see that it echoes the guangzhou configuration above

server:
  port: 8200
spring:
  application:
    name: order
  cloud:
    nacos:
      server-addr: 101.37.23.0:80
      discovery:
        username: nacos
        password: nacos
    alibaba:
      seata:
        tx-service-group: guangzhou
  datasource:
    username: root
    password: nymi@2023
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://101.37.23.0:3306/seata_order?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&useSSL=false&serverTimezone=Asia/Shanghai
mybatis:
  mapper-locations: classpath:/mappers/**/*Mapper.xml
seata:
  registry:
    type: nacos
    nacos:
      server-addr: 101.37.23.0:80
      application: seata-server
      username: nacos
      password: nacos
      group: SEATA_GROUP
  config:
    type: nacos
    nacos:
      server-addr: 101.37.23.0:80
      username: nacos
      password: nacos
      group: SEATA_GROUP
server:
  port: 8201

spring:
  application:
    name: stock
  cloud:
    nacos:
      server-addr: 101.37.23.0:80
      discovery:
        username: nacos
        password: nacos
    alibaba:
      seata:
        tx-service-group: guangzhou
  datasource:
    username: root
    password: nymi@2023
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://101.37.23.0:3306/seata_stock?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&useSSL=false&serverTimezone=Asia/Shanghai
mybatis:
  mapper-locations: classpath:/mappers/**/*Mapper.xml
seata:
  registry:
    type: nacos
    nacos:
      server-addr: 101.37.23.0:80
      application: seata-server
      username: nacos
      password: nacos
      group: SEATA_GROUP
  config:
    type: nacos
    nacos:
      server-addr: 101.37.23.0:80
      username: nacos
      password: nacos
      group: SEATA_GROUP

4. Create a database

Create a database corresponding to the yml configuration,

Both databases execute the mysql.sql script in seata\script\client\at\db

5. Business module

1. Inventory service

Develop inventory-related interfaces

The core code is as follows

Respectively Stock.class

package com.wind.model;

import lombok.Data;

/**
 * @author dongguanghui
 * @date 2023/6/29 14:20
 */
@Data
public class Stock {
    private Integer id;
    private Integer productId;
    private Integer count;
}
StockServiceImpl.class
package com.wind.service.impl;

import com.wind.mapper.StockMapper;
import com.wind.service.StockService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * @author dongguanghui
 * @date 2023/6/29 14:19
 */
@Service
public class StockServiceImpl implements StockService {

    @Autowired
    StockMapper stockMapper;

    public void reduct(Integer productId) {
        stockMapper.reduct(productId);
        System.out.println("更新商品:"+productId);
    }
}
stockMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.wind.mapper.StockMapper">

    <update id="reduct">
        update stock set `count` = `count` -1
        where product_id = #{productId}
    </update>
</mapper>

2. Order module

There are global transaction annotations on the method of the implementation class, and the startup class configuration enables global transaction annotations

Order module calls inventory

main code

OrderSeataApplication.class
package com.wind;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.web.client.RestTemplate;

/**
 * @author dongguanghui
 * @date 2023/6/29 14:17
 */
@SpringBootApplication
@EnableFeignClients
@EnableTransactionManagement
public class OrderSeataApplication {

    public static void main(String[] args) {
        SpringApplication.run(OrderSeataApplication.class,args);
    }

}
OrderController.class
package com.wind.controller;


import com.wind.model.Order;
import com.wind.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author dongguanghui
 * @date 2023/6/29 11:53
 */
@RestController
@RequestMapping("/order")
public class OrderController {

    @Autowired
    OrderService orderService;

    @RequestMapping("/add")
    public String add() {
        Order order = new Order();
        order.setProductId(9);
        order.setStatus(0);
        order.setTotalAmount(100);

        orderService.create(order);
        return "下单成功";
    }
}
OrderServiceImpl.class
package com.wind.service.impl;


import com.wind.api.StockService;
import com.wind.mapper.OrderMapper;
import com.wind.model.Order;
import com.wind.service.OrderService;
import io.seata.spring.annotation.GlobalTransactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

/**
 * @author dongguanghui
 * @date 2023/6/29 14:19
 */
@Service
public class OrderServiceImpl implements OrderService {

    @Autowired
    OrderMapper orderMapper;
    @Autowired
    StockService stockService;

    @GlobalTransactional
    public Order create(Order order) {
        // 插入订单
        orderMapper.insert(order);

        // 扣减库存
        stockService.reduct(order.getProductId());
        int a=1/0;
        return order;
    }
}
Order.class
package com.wind.model;

import lombok.Data;

/**
 * @author dongguanghui
 * @date 2023/6/29 14:20
 */
@Data
public class Order {
    private Integer id;
    private Integer productId;
    private Integer status;
    private Integer totalAmount;
}
StockService.class
package com.wind.api;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

/**
 * @author dongguanghui
 * @date 2023/6/29 17:26
 */
@FeignClient(value = "stock",path = "/stock")
public interface StockService {

    @RequestMapping("/reduct")
    public String reduct(@RequestParam("productId") Integer productId);
}
OrderMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.wind.mapper.OrderMapper">

    <insert id="insert" parameterType="com.wind.model.Order">
        insert into `order` (product_id,`status`,total_amount)
        values
        (#{productId},#{status},#{totalAmount})
    </insert>
</mapper>

6. Test verification

At int a=1/0; break point.

When it is executed, the database will change the data, and the undo_log table will store the logs of the original data and the modified data.

Continue to execute the next line of code and report an error.

At this point, the transaction is rolled back, and the undo_log data is cleared after the rollback.

If int a=1/0; change to int a=1;

Then the code execution to this line is the same as before,

Proceed to the next line, as normal.

At this point, commit the transaction and clear the undo_log data.

So far, the distributed transaction environment has been built

Guess you like

Origin blog.csdn.net/Spring_possible/article/details/131516693