一、下载Seata,地址:下载中心

二、解压部署

      1、进入conf目录修改配置文件,依据 application.example.yml  文件为样例,修改application.yml       

server:
  port: 7091

spring:
  application:
    name: seata-server

logging:
  config: classpath:logback-spring.xml
  file:
    path: ${user.home}/logs/seata
  extend:
    logstash-appender:
      destination: 127.0.0.1:4560
    kafka-appender:
      bootstrap-servers: 127.0.0.1:9092
      topic: logback_to_logstash

console:
  user:
    username: seata
    password: seata

seata:
  # 配置中心,以下是以nacos为配置中心
  config:
    # support: nacos, consul, apollo, zk, etcd3
    type: nacos
    nacos:
      server-addr: 192.168.3.133:8848
      # 以下namespace命名空间,需要在nacos中手动创建
      namespace: 53e24698-1032-41cc-966f-129931d10ec9
      group: SHOP_GROUP
      username: nacos
      password: nacos
      context-path:
      ##if use MSE Nacos with auth, mutex with username/password attribute
      #access-key:
      #secret-key:
      data-id: seataServer.properties
  # 注册中共新,以下以nacos为注册中心
  registry:
    # support: nacos, eureka, redis, zk, consul, etcd3, sofa
    type: nacos
    nacos:
      application: seata-server
      server-addr: 192.168.3.133:8848
      group: SHOP_GROUP
      # 以下namespace命名空间,需要在nacos中手动创建
      namespace: 53e24698-1032-41cc-966f-129931d10ec9
      cluster: default
      username: nacos
      password: nacos
      context-path:
      ##if use MSE Nacos with auth, mutex with username/password attribute
      #access-key:
      #secret-key:
  # 选择存储模式
  store:
    # support: file 、 db 、 redis
    mode: db
    db:
      datasource: druid
      dbType: mysql
      driverClassName: com.mysql.cj.jdbc.Driver
      url: jdbc:mysql://127.0.0.1:3306/seata?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true
      user: root
      password: root
#  server:
#    service-port: 8091 #If not configured, the default is '${server.port} + 1000'
  security:
    secretKey: SeataSecretKey0c382ef121d778043159209298fd40bf3850a017
    tokenValidityInMilliseconds: 1800000
    ignore:
      urls: /,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.ico,/console-fe/public/**,/api/v1/auth/login

2. 进入script目录下的config-center对文件config.txt进行修改后,将其远程部署到nacos上,执行以下命令(如果windows,执行:nacos-config.py 命令来部署)     

nacos-config.sh -h localhost -p 8848 -g SEATA_GROUP -t 在nacos上的命名空间id  -u nacos账号 -w nacos密码

   部署成功如下:

 3. 新建seata数据库,进入script目录下server->db,选择对应的数据库文件

 4. 启动seata服务,进入bin目录,点击相应的启动脚本

三、 springCloud加入seata

  1. pom中引入依赖

<dependency>
            <groupId>io.seata</groupId>
            <artifactId>seata-spring-boot-starter</artifactId>
            <version>1.6.1</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
            <version>2021.1</version>
            <exclusions>
                <exclusion>
                    <groupId>io.seata</groupId>
                    <artifactId>seata-spring-boot-starter</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        
        <!-- 我这边测试发下,如果不引入以下依赖的话,默认自己引入的版本比较低,然后会出现兼容问题 -->
        <dependency>
            <groupId>io.seata</groupId>
            <artifactId>seata-core</artifactId>
            <version>1.6.1</version>
        </dependency>

2. 新建多个微服务项目,如下:

    

3. 在nacos上配置三个微服务对应的参数(演示的微服务以nacos为注册配置中心) ,配置如下(三个微服务的配置基本一致,其中application.name的名字不 一样,数据库不一样,此处演示用了3个不同的数据库):    

mybatis-plus:
  mapper-locations: classpath:mapper/*.xml
  config-location: classpath:mapper/config/sqlMapConfig.xml

spring:
  servlet:
    multipart:
      enabled: true
      max-file-size: 100MB
      max-request-size: 100MB
  application:
    name: open-seata-demo1
  profiles:
    active: dev
  cloud:
    inetutils:
      preferred-networks: ^192\.168\.3\.[\d]+$
    nacos:
      config:
        server-addr: 192.168.3.133:8848
        group: gongshang_open_api
        file-extension: yml
        enabled: true
      discovery:
        server-addr: 192.168.3.133:8848
        group: gongshang_open_api
    sentinel:
      transport:
        # 配置Sentinel dashborad地址
        dashboard: http://192.168.3.133:8080
        port: 8719
  datasource:
    dynamic:
      primary: master #设置默认的数据源或者数据源组,默认值即为master
      strict: false #严格匹配数据源,默认false. true未匹配到指定数据源时抛异常,false使用默认数据源
      datasource:
        #业务中台主库
        master:
          url: jdbc:mysql://127.0.0.1:3306/business_platform_demo?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&zeroDateTimeBehavior=convertToNull
          username: root
          password: root
          driver-class-name: com.mysql.cj.jdbc.Driver  

  redis:
    database: 0
    host: 127.0.0.1
    port: 6379
    password: 
    max-active: 100
    max-wait: 1000

management:
  endpoints:
    web:
      exposure:
        include: '*'

swagger:
  title: open-seata-demo1
  scanpackages: com.cn

logging:
  level:
    com.cn: error

servlet:
  multipart:
    enabled: true
    max-file-size: 100MB
    max-request-size: 100MB

# 打开sentinel对feign的支持
feign:
  sentinel:
    enabled: true

# 服务超时时间设置
ribbon:
  #读超时时间
  ReadTimeout: 5000
  #连接超时时间
  ConnectTimeout: 1000
  #同一台实例最大重试次数,不包括首次调用
  MaxAutoRetries: 1
  #重试负载均衡其他的实例最大重试次数,不包括首次调用
  MaxAutoRetriesNextServer: 1
  #是否所有操作都重试
  OkToRetryOnAllOperations: false

rocketmq:
  nameServer: 192.168.3.133:9876
  group: openapi-logs

global:
  fileDomain: xxxxx

# seata配置
seata:
  enabled: true
  # Seata 应用编号,默认为 ${spring.application.name}
  application-id: ${spring.application.name}
  # Seata 事务组编号,用于 TC 集群名
  tx-service-group: ${spring.application.name}-group
  # 开启自动代理
  enable-auto-data-source-proxy: true
  # 服务配置项
  service:
    # 虚拟组和分组的映射
    vgroup-mapping:
      gulimall-order-group: default

  config:
    type: nacos
    nacos:
      serverAddr: 192.168.3.133:8848
      group: SHOP_GROUP
      # 以下命名空间ID与上文的均保持一致
      namespace: 53e24698-1032-41cc-966f-129931d10ec9
  registry:
    type: nacos
    nacos:
      application: seata-server
      server-addr: 192.168.3.133:8848
      # 以下命名空间ID与上文的均保持一致
      namespace: 53e24698-1032-41cc-966f-129931d10ec9
      group: SHOP_GROUP

demo:
  exception: false

 

4. 在naocs上增加以下三个配置:service.vgroupMapping.open-seata-demo1-group、service.vgroupMapping.open-seata-demo2-group、service.vgroupMapping.open-seata-demo3-group

 5. 编写微服务: open-seata-demo3

     mapper文件

package com.cn.web.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.cn.web.entity.OnlineMessageEntity;
import org.apache.ibatis.annotations.Mapper;

/**
 * description: IOnmessageMapper <br>
 * date: 23.3.20 16:28 <br>
 * author: cn_yaojin <br>
 * version: 1.0 <br>
 */
@Mapper
public interface IOnmessageMapper extends BaseMapper<OnlineMessageEntity> {
}

    service文件

package com.cn.web.service;

import com.cn.exception.MyException;
import com.cn.util.DateUtil;
import com.cn.util.SnowflakeIdWorkerUtil;
import com.cn.web.entity.GlobalDemoConfig;
import com.cn.web.entity.OnlineMessageEntity;
import com.cn.web.mapper.IOnmessageMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * description: OnMessageService <br>
 * date: 23.3.20 16:28 <br>
 * author: cn_yaojin <br>
 * version: 1.0 <br>
 */
@Service
@Slf4j
public class OnMessageService {

    @Autowired
    private IOnmessageMapper onmessageMapper;


    @Autowired
    private GlobalDemoConfig globalDemoConfig;

    @Transactional
    public void add(OnlineMessageEntity msg) {
        msg.setId(SnowflakeIdWorkerUtil.getId());
        msg.setCreateDate(DateUtil.getTime("yyyy-MM-dd HH:mm:ss"));
        if (StringUtils.isEmpty(msg.getImgs())) {
            msg.setImgs("");
        }
        this.onmessageMapper.insert(msg);
        //动态控制抛出异常
        if (globalDemoConfig.isException()) {
            throw new MyException("在线留言失败");
        }
    }

}

  controller

package com.cn.web.controller;

import com.cn.msg.ResultMsg;
import com.cn.web.entity.OnlineMessageEntity;
import com.cn.web.service.OnMessageService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * description: OnMessageController <br>
 * date: 23.3.22 16:08 <br>
 * author: cn_yaojin <br>
 * version: 1.0 <br>
 */
@RestController
@RequestMapping(value = "seata3")
public class OnMessageController {

    @Autowired
    private OnMessageService onMessageService;

    @PostMapping(value = "save")
    public ResultMsg save(
            @RequestBody OnlineMessageEntity info
    ) {
        this.onMessageService.add(info);
        return ResultMsg.builder();
    }

}

6. 编写微服务:open-seata-demo2

    mapper

package com.cn.web.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.cn.web.entity.MsgEntity;
import org.apache.ibatis.annotations.Mapper;

/**
 * description: IMsgMapper <br>
 * date: 23.3.17 17:29 <br>
 * author: cn_yaojin <br>
 * version: 1.0 <br>
 */
@Mapper
public interface IMsgMapper extends BaseMapper<MsgEntity> {
}

   service文件

package com.cn.web.service;

import com.cn.exception.MyException;
import com.cn.util.DateUtil;
import com.cn.util.SnowflakeIdWorkerUtil;
import com.cn.web.entity.GlobalDemoConfig;
import com.cn.web.entity.MsgEntity;
import com.cn.web.entity.OnlineMessageEntity;
import com.cn.web.mapper.IMsgMapper;
import com.cn.web.plugin.OpenSeataDemo2Service;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * description: MsgService <br>
 * date: 23.3.17 17:28 <br>
 * author: cn_yaojin <br>
 * version: 1.0 <br>
 */
@Service
@Slf4j
public class MsgService {

    @Autowired
    private IMsgMapper msgMapper;

    @Autowired
    private OpenSeataDemo2Service openSeataDemo2Service;


    @Autowired
    private GlobalDemoConfig globalDemoConfig;

    @Transactional
    public void saveTmp(MsgEntity info) {
        info.setId(SnowflakeIdWorkerUtil.getId());
        info.setCreateTime(DateUtil.getTime("yyyy-MM-dd HH:mm:ss"));
        this.msgMapper.insert(info);


        //调用微服务open-seata-demo3
        OnlineMessageEntity msg = new OnlineMessageEntity();
        msg.setTitle("在线留言").setContent("在线留言内容啊啊啊");
        var result = openSeataDemo2Service.save(msg);
        if (result.getCode() != 200) {
            throw new MyException(result.getMsg());
        }
        if (globalDemoConfig.isException()) {
            throw new MyException("保存通知失败");
        }
    }

}

  controller

package com.cn.web.controller;

import com.cn.msg.ResultMsg;
import com.cn.web.entity.MsgEntity;
import com.cn.web.service.MsgService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * description: MsgController <br>
 * date: 23.3.22 16:01 <br>
 * author: cn_yaojin <br>
 * version: 1.0 <br>
 */
@RestController
@RequestMapping(value = "seata2")
public class MsgController {

    @Autowired
    private MsgService msgService;

    @PostMapping(value = "save")
    public ResultMsg save(
            @RequestBody MsgEntity info
    ) {
        msgService.saveTmp(info);
        return ResultMsg.builder();
    }

}

  微服务open-seata-demo3

package com.cn.web.plugin;

import com.cn.msg.ResultMsg;
import com.cn.web.entity.MsgEntity;
import com.cn.web.entity.OnlineMessageEntity;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;

/**
 * description: OpenSeataDemo2Service <br>
 * date: 23.3.22 16:00 <br>
 * author: cn_yaojin <br>
 * version: 1.0 <br>
 */
@FeignClient(value = "open-seata-demo3", fallback = OpenSeataDemo2FallbackImpl.class)
public interface OpenSeataDemo2Service {

    @PostMapping(value = "seata3/save")
    ResultMsg save(@RequestBody OnlineMessageEntity info);

}



package com.cn.web.plugin;

import com.cn.exception.MyException;
import com.cn.msg.ResultMsg;
import com.cn.web.entity.OnlineMessageEntity;
import org.springframework.stereotype.Component;

/**
 * description: OpenSeataDemo2FallbackImpl <br>
 * date: 23.3.22 16:04 <br>
 * author: cn_yaojin <br>
 * version: 1.0 <br>
 */
@Component
public class OpenSeataDemo2FallbackImpl implements OpenSeataDemo2Service {

    @Override
    public ResultMsg save(OnlineMessageEntity info) {
        throw new MyException("添加msg失败");
    }
}

 结构如下:

 7. 编写微服务:open-seata-demo1

      mapper

package com.cn.web.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.cn.web.entity.PortalUserEntity;
import org.apache.ibatis.annotations.Mapper;

/**
 * description: IUserMapper <br>
 * date: 23.3.16 9:50 <br>
 * author: cn_yaojin <br>
 * version: 1.0 <br>
 */
@Mapper
public interface IUserMapper extends BaseMapper<PortalUserEntity> {
}

    service

package com.cn.web.service;

import com.cn.exception.MyException;
import com.cn.util.DateUtil;
import com.cn.util.SnowflakeIdWorkerUtil;
import com.cn.web.entity.GlobalDemoConfig;
import com.cn.web.entity.MsgEntity;
import com.cn.web.entity.PortalUserEntity;
import com.cn.web.mapper.IUserMapper;
import com.cn.web.plugin.OpenSeataDemo2Service;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * description: UserService <br>
 * date: 23.3.16 9:51 <br>
 * author: cn_yaojin <br>
 * version: 1.0 <br>
 */
@Service
@Slf4j
public class UserService {

    @Autowired
    private IUserMapper userMapper;

    @Autowired
    private OpenSeataDemo2Service openSeataDemo2Service;

    @Autowired
    private GlobalDemoConfig globalDemoConfig;

    @Transactional
    @GlobalTransactional(rollbackFor = Exception.class)
    public void saveTmp(PortalUserEntity info) {
        info.setId(SnowflakeIdWorkerUtil.getId());
        info.setAddTime(DateUtil.getTime("yyyy-MM-dd HH:mm:ss"));
        this.userMapper.insert(info);

        //调用微服务:open-seata-demo2
        MsgEntity msg = new MsgEntity();
        msg.setTitle("xxx测试啊").setContent("开始的发哈检索到访哈酒");
        var result = openSeataDemo2Service.save(msg);
        if (result.getCode() != 200) {
            throw new MyException(result.getMsg());
        }
        if (globalDemoConfig.isException()) {
            throw new MyException("回滚人员信息");
        }
    }

}

controller

package com.cn.web.controller;

import com.cn.msg.ResultMsg;
import com.cn.web.entity.PortalUserEntity;
import com.cn.web.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * description: DemoController <br>
 * date: 23.3.22 16:06 <br>
 * author: cn_yaojin <br>
 * version: 1.0 <br>
 */
@RestController
@RequestMapping(value = "seata1")
public class DemoController {

    @Autowired
    private UserService userServices;

    @PostMapping(value = "save")
    public ResultMsg save(
            @RequestBody PortalUserEntity info
    ) {
        this.userServices.saveTmp(info);
        return ResultMsg.builder();
    }

}

微服务open-seata-demo2

package com.cn.web.plugin;

import com.cn.msg.ResultMsg;
import com.cn.web.entity.MsgEntity;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;

/**
 * description: OpenSeataDemo2Service <br>
 * date: 23.3.22 16:00 <br>
 * author: cn_yaojin <br>
 * version: 1.0 <br>
 */
@FeignClient(value = "open-seata-demo2", fallback = OpenSeataDemo2FallbackImpl.class)
public interface OpenSeataDemo2Service {

    @PostMapping(value = "seata2/save")
    ResultMsg save(@RequestBody MsgEntity info);

}

package com.cn.web.plugin;

import com.cn.exception.MyException;
import com.cn.msg.ResultMsg;
import com.cn.web.entity.MsgEntity;
import org.springframework.stereotype.Component;

/**
 * description: OpenSeataDemo2FallbackImpl <br>
 * date: 23.3.22 16:04 <br>
 * author: cn_yaojin <br>
 * version: 1.0 <br>
 */
@Component
public class OpenSeataDemo2FallbackImpl implements OpenSeataDemo2Service {

    @Override
    public ResultMsg save(MsgEntity info) {
        throw new MyException("添加失败");
    }
}

结构如下

8. 启动三个微服务,以微服务open-seata-demo1为入口,然后在nacos中动态修改参数:demo.exception来控制抛出异常,测试实际效果。

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐