• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

nacos环境下seata配置

武飞扬头像
「已注销」
帮助1

seata是笔者遇到的spring技术栈中配置相对麻烦的一个,而且按官方案例都不一定成功,有不少错误产生。所以这里记录一下:

本文选择seata 1.3.0版本,项目添加依赖也是这个版本。Release v1.3.0 · seata/seata · GitHub

配置seata服务端: 下载seata-server和source code。 解压ource code,找到script文件里config-center文件,修改config.txt

  1.  
     
  2.  
    ...
  3.  
    service.vgroup-mapping.my_test_tx_group=default
  4.  
    ...
  5.  
    store.mode=db
  6.  
    store.db.datasource=druid
  7.  
    store.db.dbType=mysql
  8.  
    store.db.driverClassName=com.mysql.cj.jdbc.Driver
  9.  
    store.db.url=jdbc:mysql://127.0.0.1:3306/seata_server?useUnicode=true&serverTimezone=UTC
  10.  
    store.db.user=root
  11.  
    store.db.password=123456
  12.  
    ...

注意把vgroupMapping改成vgroup-mapping这是seata版本的问题。 新建nacos命名空间seata 运行写入配置中心

sh nacos-config.sh -h localhost -p 8848 -g SEATA_GROUP -t seata_namespace_id -u nacos -w nacos

打开script->server->db将里面mysql.sql写入seata_server数据库

将seata-server解压找到conf,按照官网配置file.conf和registry.conf,模式db,类型nacos, 命名空间同为seata_namespace_id。

启动seata-server服务。

然后配置seata-client服务,首先说明按照官网配置,不像其他技术栈那么简单明了,笔者尝试多种方法有不少坑要踩,另外还结合了官方给出的案例:GitHub - seata/seata-samples: seata-samples

找到里面的springcloud-nacos-seata文件,我们可以拿它的stock和order模块测试,在需要用到seata服务的不同库里我们都需要引入undo_log这个表,建表语句在官网和给出案例的readme.md里都能容易找到。 遗憾是按照其案例配置依然会报错,这大概和最新依赖配置不能匹配,所以按照idea工具的配置方式,配置了spring web/nacos/seata依赖。启动会报错,这是因为spring-cloud-starter-alibaba-seata这个包seata版本不是1.3.0或是缺少了seata-all这个包的依赖,最终引入依赖为:

  1.  
    <dependencies>
  2.  
    <dependency>
  3.  
    <groupId>org.springframework.boot</groupId>
  4.  
    <artifactId>spring-boot-starter-web</artifactId>
  5.  
    </dependency>
  6.  
    <dependency>
  7.  
    <groupId>com.alibaba.cloud</groupId>
  8.  
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
  9.  
    </dependency>
  10.  
    <dependency>
  11.  
    <groupId>com.alibaba.cloud</groupId>
  12.  
    <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
  13.  
    <exclusions>
  14.  
    <exclusion>
  15.  
    <artifactId>seata-all</artifactId>
  16.  
    <groupId>io.seata</groupId>
  17.  
    </exclusion>
  18.  
    </exclusions>
  19.  
    </dependency>
  20.  
    <dependency>
  21.  
    <groupId>io.seata</groupId>
  22.  
    <artifactId>seata-all</artifactId>
  23.  
    </dependency>
  24.  
    <dependency>
  25.  
    <groupId>org.springframework.boot</groupId>
  26.  
    <artifactId>spring-boot-starter-test</artifactId>
  27.  
    <scope>test</scope>
  28.  
    <exclusions>
  29.  
    <exclusion>
  30.  
    <groupId>org.junit.vintage</groupId>
  31.  
    <artifactId>junit-vintage-engine</artifactId>
  32.  
    </exclusion>
  33.  
    </exclusions>
  34.  
    </dependency>
  35.  
     
  36.  
    <dependency>
  37.  
    <groupId>org.springframework.cloud</groupId>
  38.  
    <artifactId>spring-cloud-starter-openfeign</artifactId>
  39.  
    </dependency>
  40.  
    <dependency>
  41.  
    <groupId>org.projectlombok</groupId>
  42.  
    <artifactId>lombok</artifactId>
  43.  
    </dependency>
  44.  
    <dependency>
  45.  
    <groupId>org.example</groupId>
  46.  
    <artifactId>mysql-config</artifactId>
  47.  
    <version>1.0-SNAPSHOT</version>
  48.  
    </dependency>
  49.  
    </dependencies>
学新通

在父pom里处理好了所以版本问题:

  1.  
     
  2.  
    <properties>
  3.  
    <java.version>1.8</java.version>
  4.  
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  5.  
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
  6.  
    <spring-boot.version>2.3.7.RELEASE</spring-boot.version>
  7.  
    <spring-cloud-alibaba.version>2.2.2.RELEASE</spring-cloud-alibaba.version>
  8.  
    </properties>
  9.  
    <dependencyManagement>
  10.  
    <dependencies>
  11.  
    <dependency>
  12.  
    <groupId>org.springframework.boot</groupId>
  13.  
    <artifactId>spring-boot-dependencies</artifactId>
  14.  
    <version>${spring-boot.version}</version>
  15.  
    <type>pom</type>
  16.  
    <scope>import</scope>
  17.  
    </dependency>
  18.  
    <dependency>
  19.  
    <groupId>com.alibaba.cloud</groupId>
  20.  
    <artifactId>spring-cloud-alibaba-dependencies</artifactId>
  21.  
    <version>${spring-cloud-alibaba.version}</version>
  22.  
    <type>pom</type>
  23.  
    <scope>import</scope>
  24.  
    </dependency>
  25.  
    <dependency>
  26.  
    <groupId>com.alibaba</groupId>
  27.  
    <artifactId>druid-spring-boot-starter</artifactId>
  28.  
    <version>1.1.10</version>
  29.  
    </dependency>
  30.  
     
  31.  
    <dependency>
  32.  
    <groupId>mysql</groupId>
  33.  
    <artifactId>mysql-connector-java</artifactId>
  34.  
    <version>8.0.27</version>
  35.  
    </dependency>
  36.  
     
  37.  
    <dependency>
  38.  
    <groupId>com.baomidou</groupId>
  39.  
    <artifactId>mybatis-plus-boot-starter</artifactId>
  40.  
    <version>3.1.1</version>
  41.  
    </dependency>
  42.  
    <!-- https://mvnrepository.com/artifact/io.seata/seata-all -->
  43.  
    <dependency>
  44.  
    <groupId>io.seata</groupId>
  45.  
    <artifactId>seata-all</artifactId>
  46.  
    <version>1.3.0</version>
  47.  
    </dependency>
  48.  
     
  49.  
    <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-openfeign -->
  50.  
    <dependency>
  51.  
    <groupId>org.springframework.cloud</groupId>
  52.  
    <artifactId>spring-cloud-starter-openfeign</artifactId>
  53.  
    <version>2.2.10.RELEASE</version>
  54.  
    </dependency>
  55.  
    <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
  56.  
    <dependency>
  57.  
    <groupId>org.projectlombok</groupId>
  58.  
    <artifactId>lombok</artifactId>
  59.  
    <version>1.18.22</version>
  60.  
    <scope>provided</scope>
  61.  
    </dependency>
  62.  
    </dependencies>
  63.  
    </dependencyManagement>
学新通

引入的mysql-config模块配置:

  1.  
    @Configuration
  2.  
    public class config {
  3.  
    /**
  4.  
    * @param sqlSessionFactory SqlSessionFactory
  5.  
    * @return SqlSessionTemplate
  6.  
    */
  7.  
    @Bean
  8.  
    public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
  9.  
    return new SqlSessionTemplate(sqlSessionFactory);
  10.  
    }
  11.  
     
  12.  
    /**
  13.  
    * 从配置文件获取属性构造datasource,注意前缀,这里用的是druid,根据自己情况配置,
  14.  
    * 原生datasource前缀取"spring.datasource"
  15.  
    *
  16.  
    * @return
  17.  
    */
  18.  
    @Bean
  19.  
    @ConfigurationProperties(prefix = "spring.datasource.druid")
  20.  
    public DataSource druidDataSource() {
  21.  
    DruidDataSource druidDataSource = new DruidDataSource();
  22.  
    return druidDataSource;
  23.  
    }
  24.  
     
  25.  
    /**
  26.  
    * 构造datasource代理对象,替换原来的datasource
  27.  
    *
  28.  
    * @param druidDataSource
  29.  
    * @return
  30.  
    */
  31.  
    @Primary
  32.  
    @Bean("dataSource")
  33.  
    public DataSourceProxy dataSourceProxy(DataSource druidDataSource) {
  34.  
    return new DataSourceProxy(druidDataSource);
  35.  
    }
  36.  
     
  37.  
    @Bean(name = "sqlSessionFactory")
  38.  
    public SqlSessionFactory sqlSessionFactoryBean(DataSourceProxy dataSourceProxy) throws Exception {
  39.  
    MybatisSqlSessionFactoryBean bean = new MybatisSqlSessionFactoryBean();
  40.  
    bean.setDataSource(dataSourceProxy);
  41.  
    ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
  42.  
    // bean.setConfigLocation(resolver.getResource("classpath:mybatis-config.xml"));
  43.  
    bean.setMapperLocations(resolver.getResources("classpath*:mybatis/**/*-mapper.xml"));
  44.  
     
  45.  
    SqlSessionFactory factory = null;
  46.  
    try {
  47.  
    factory = bean.getObject();
  48.  
    } catch (Exception e) {
  49.  
    throw new RuntimeException(e);
  50.  
    }
  51.  
    return factory;
  52.  
    }
  53.  
     
  54.  
    /**
  55.  
    * MP 自带分页插件
  56.  
    *
  57.  
    * @return
  58.  
    */
  59.  
    @Bean
  60.  
    public PaginationInterceptor paginationInterceptor() {
  61.  
    PaginationInterceptor page = new PaginationInterceptor();
  62.  
    page.setDialectType("mysql");
  63.  
    return page;
  64.  
    }
  65.  
    }
学新通

同时在启动类上把DataSourceAutoConfiguration默认配置排除

  1.  
     
  2.  
    @EnableFeignClients
  3.  
    @EnableDiscoveryClient
  4.  
    @SpringBootApplication(scanBasePackages = {"com.example"}, exclude = DataSourceAutoConfiguration.class)
  5.  
    public class OrderServiceApplication {
  6.  
     
  7.  
    public static void main(String[] args) {
  8.  
    SpringApplication.run(OrderServiceApplication.class, args);
  9.  
    }
  10.  
     
  11.  
    }

application.yml:

  1.  
     
  2.  
    server:
  3.  
    port: 8000
  4.  
    spring:
  5.  
    application:
  6.  
    name: order-service
  7.  
    cloud:
  8.  
    nacos:
  9.  
    discovery:
  10.  
    username: nacos
  11.  
    password: nacos
  12.  
    server-addr: 127.0.0.1:8848
  13.  
    group: SEATA_GROUP
  14.  
    alibaba:
  15.  
    seata:
  16.  
    # seata 服务分组,要与服务端nacos-config.txt中service.vgroup_mapping的后缀对应
  17.  
    tx-service-group: my_test_tx_group
  18.  
    datasource:
  19.  
    druid:
  20.  
    url: jdbc:mysql://localhost:3306/seata_order?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC
  21.  
    driverClassName: com.mysql.cj.jdbc.Driver
  22.  
    username: root
  23.  
    password: 123456
  24.  
     
  25.  
    logging:
  26.  
    level:
  27.  
    io:
  28.  
    seata: debug
  29.  
     
  30.  
    seata:
  31.  
    registry:
  32.  
    type: nacos
  33.  
    nacos:
  34.  
    application: seata-server
  35.  
    server-addr: 127.0.0.1:8848
  36.  
    group : "SEATA_GROUP"
  37.  
    namespace: "seata_namespace_id"
  38.  
    username: "nacos"
  39.  
    password: "nacos"
  40.  
    config:
  41.  
    type: nacos
  42.  
    nacos:
  43.  
    server-addr: 127.0.0.1:8848
  44.  
    group: "SEATA_GROUP"
  45.  
    namespace: "seata_namespace_id"
  46.  
    username: "nacos"
  47.  
    password: "nacos"
  48.  
    application-id: ${spring.application.name}
学新通

StockService.java:

  1.  
    @Service
  2.  
    public class StockService {
  3.  
     
  4.  
    @Resource
  5.  
    private StockDAO stockDAO;
  6.  
     
  7.  
    /**
  8.  
    * 减库存
  9.  
    *
  10.  
    * @param commodityCode
  11.  
    * @param count
  12.  
    */
  13.  
    @Transactional(rollbackFor = Exception.class)
  14.  
    public void deduct(String commodityCode, int count) {
  15.  
    QueryWrapper<Stock> wrapper = new QueryWrapper<>();
  16.  
    wrapper.setEntity(new Stock().setCommodityCode(commodityCode));
  17.  
    Stock stock = stockDAO.selectOne(wrapper);
  18.  
    stock.setCount(stock.getCount() - count);
  19.  
     
  20.  
    stockDAO.updateById(stock);
  21.  
    if (commodityCode.equals("product-2")) {
  22.  
    throw new RuntimeException("异常:模拟业务异常:stock branch exception");
  23.  
    }
  24.  
    }
  25.  
    }
学新通

StockFeignClient.java:

  1.  
    @FeignClient(name = "stock-service")
  2.  
    public interface StockFeignClient {
  3.  
     
  4.  
    @GetMapping("stock/deduct")
  5.  
    Boolean deduct(@RequestParam("commodityCode") String commodityCode, @RequestParam("count") Integer count);
  6.  
    }

OrderService.java:

  1.  
    @Service
  2.  
    public class OrderService {
  3.  
     
  4.  
    @Resource
  5.  
    private StockFeignClient stockFeignClient;
  6.  
    @Resource
  7.  
    private OrderDAO orderDAO;
  8.  
     
  9.  
    //启用seata全局事务
  10.  
    @GlobalTransactional
  11.  
    @Transactional(rollbackFor = Exception.class)
  12.  
    public void placeOrder(String userId, String commodityCode, Integer count) {
  13.  
    BigDecimal orderMoney = new BigDecimal(count).multiply(new BigDecimal(5));
  14.  
    Order order = new Order().setUserId(userId).setCommodityCode(commodityCode).setCount(count).setMoney(
  15.  
    orderMoney);
  16.  
    orderDAO.insert(order);
  17.  
    stockFeignClient.deduct(commodityCode, count);
  18.  
     
  19.  
    }
  20.  
     
  21.  
    }
学新通

OrderController.java:

  1.  
     
  2.  
    @RestController
  3.  
    @RequestMapping("order")
  4.  
    public class OrderController {
  5.  
     
  6.  
    @Resource
  7.  
    private OrderService orderService;
  8.  
     
  9.  
    /**
  10.  
    * 下单:插入订单表、扣减库存
  11.  
    *
  12.  
    * @return
  13.  
    */
  14.  
    @RequestMapping("/placeOrder/commit")
  15.  
    public Boolean placeOrderCommit() {
  16.  
     
  17.  
    orderService.placeOrder("1", "product-1", 1);
  18.  
    return true;
  19.  
    }
  20.  
     
  21.  
    /**
  22.  
    * 下单:插入订单表、扣减库存,模拟回滚
  23.  
    *
  24.  
    * @return
  25.  
    */
  26.  
    @RequestMapping("/placeOrder/rollback")
  27.  
    public Boolean placeOrderRollback() {
  28.  
    // product-2 扣库存时模拟了一个业务异常,
  29.  
    orderService.placeOrder("1", "product-2", 1);
  30.  
    return true;
  31.  
    }
  32.  
     
  33.  
    @RequestMapping("/placeOrder")
  34.  
    public Boolean placeOrder(String userId, String commodityCode, Integer count) {
  35.  
    orderService.placeOrder(userId, commodityCode, count);
  36.  
    return true;
  37.  
    }
  38.  
    }
学新通

测试: 1.分布式事务成功,模拟正常下单、扣库存

localhost:8000/order/placeOrder/commit

2.分布式事务失败,模拟下单成功、扣库存失败,最终同时回滚

localhost:8000/order/placeOrder/rollback

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhfhjfka
系列文章
更多 icon
同类精品
更多 icon
继续加载