點點我:JAVA互聯網架構師專題/分佈式/高併發/微服務 提取馬:xb2kjava
1.1 環境準備 1)指定nacos做爲配置中心和註冊中心 修改registry.conf文件 V(cmL46679910)mysql
注意:客戶端配置registry.conf使用nacos時也要注意group要和seata server中的 group一致,默認group是"DEFAULT_GROUP"redis
2)同步seata server的配置到nacosspring
獲取/seata/script/config-center/config.txt,修改配置信息sql
配置事務分組, 要與客戶端配置的事務分組一致 (客戶端properties配置:spring.cloud.alibaba.seata.tx‐servicegroup= my_test_tx_group)shell
配置參數同步到Nacos數據庫
shell: sh ${SEATAPATH}/script/config‐center/nacos/nacos‐config.sh ‐h localhost ‐p 8848 ‐g SEATA_GROUP ‐t 5a3c7d6c‐f497‐4d68‐a71a‐2e5e3340b3ca 參數說明: -h: host,默認值 localhost交流V(cmL46679910) -p: port,默認值 8848 -g: 配置分組,默認值爲 'SEATA_GROUP' -t: 租戶信息,對應 Nacos 的命名空間ID字段, 默認值爲空 ''apache
3) 啓動Seata Servermarkdown
啓動Seata Server命令 bin/seata‐server.sh 啓動成功,默認端口8091session
在註冊中心中能夠查看到seata-server註冊成功
業務場景:
用戶下單,整個業務邏輯由三個微服務構成: 倉儲服務:對給定的商品扣除庫存數量。 訂單服務:根據採購需求建立訂單。 賬戶服務:從用戶賬戶中扣除餘額。 點點我:JAVA互聯網架構師專題/分佈式/高併發/微服務 提取馬:xb2k
環境準備: seata: v1.4.0 spring cloud&spring cloud alibaba: 1 <spring‐cloud.version>Greenwich.SR3</spring‐cloud.version> 2 <spring‐cloud‐alibaba.version>2.1.1.RELEASE</spring‐cloud‐alibaba.version> 注意版本選擇問題: spring cloud alibaba 2.1.2 及其以上版本使用seata1.4.0會出現以下異常 (支持seata 1.3.0)
2.1 導入依賴
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring‐cloud‐starter‐alibaba‐seata</artifactId>
<exclusions>
<exclusion>
<groupId>io.seata</groupId>
<artifactId>seata‐all</artifactId>
</exclusion>
</exclusions>
</dependency>
**交流V**(**cmL46679910**)
<dependency>
<groupId>io.seata</groupId>
<artifactId>seata‐all</artifactId>
<version>1.4.0</version>
</dependency>
<!‐‐nacos 註冊中心‐‐>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring‐cloud‐starter‐alibaba‐nacos‐discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring‐cloud‐starter‐openfeign</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid‐spring‐boot‐starter</artifactId>
<version>1.1.21</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql‐connector‐java</artifactId>
<scope>runtime</scope>
<version>8.0.16</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis‐spring‐boot‐starter</artifactId>
<version>2.1.1</version>
</dependency>
複製代碼
2.2 微服務對應數據庫中添加undo_log表
```CREATE TABLE undo_log
( id
bigint(20) NOT NULL AUTO_INCREMENT, branch_id
bigint(20) NOT NULL, xid
varchar(100) NOT NULL, context
varchar(128) NOT NULL, rollback_info
longblob NOT NULL, log_status
int(11) NOT NULL,交流V(cmL46679910) log_created
datetime NOT NULL, log_modified
datetime NOT NULL, PRIMARY KEY (id
), UNIQUE KEY ux_undo_log
(xid
,branch_id
) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
2.3 微服務須要使用seata DataSourceProxy代理本身的數據源
複製代碼
/**
*/ @Configuration @MapperScan("com.tuling.datasource.mapper") public class MybatisConfig {
/**
/ @Bean @ConfigurationProperties(prefix = "spring.datasource") public DataSource druidDataSource() { DruidDataSource druidDataSource = new DruidDataSource(); return druidDataSource; } 交流V(cmL46679910) /*
*/ @Primary @Bean("dataSource") public DataSourceProxy dataSourceProxy(DataSource druidDataSource) { return new DataSourceProxy(druidDataSource); }
@Bean(name = "sqlSessionFactory") public SqlSessionFactory sqlSessionFactoryBean(DataSourceProxy dataSourcePro xy) throws Exception { SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean(); //設置代理數據源 factoryBean.setDataSource(dataSourceProxy); ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); factoryBean.setMapperLocations(resolver.getResources("classpath*:mybatis/**/ *‐mapper.xml"));
org.apache.ibatis.session.Configuration configuration=new org.apache.ibatis.session.Configuration(); //使用jdbc的getGeneratedKeys獲取數據庫自增主鍵值 configuration.setUseGeneratedKeys(true); //使用列別名替換列名 configuration.setUseColumnLabel(true); //自動使用駝峯命名屬性映射字段,如userId ‐‐‐> user_id configuration.setMapUnderscoreToCamelCase(true); factoryBean.setConfiguration(configuration);
return factoryBean.getObject(); }
} 注意: 啓動類上須要排除DataSourceAutoConfiguration,不然會出現循環依賴的問題
啓動類排除DataSourceAutoConfiguration.class
@SpringBootApplication(scanBasePackages = "com.tuling",exclude = DataSourceAut oConfiguration.class) public class AccountServiceApplication {交流V(cmL46679910)
public static void main(String[] args) { SpringApplication.run(AccountServiceApplication.class, args); }
}
4. 添加seata的配置
)將registry.conf文件拷貝到resources目錄下,指定註冊中心和配置中心都是nacos
```registry {
# file 、nacos 、eureka、redis、zk、consul、etcd三、sofa
type = "nacos"
nacos {
serverAddr = "192.168.65.232:8848"
namespace = ""
cluster = "default"
group = "SEATA_GROUP"
}
}
config {
# file、nacos 、apollo、zk、consul、etcd三、springCloudConfig
type = "nacos"**交流V**(**cmL46679910**)
nacos {
serverAddr = "192.168.65.232:8848"
namespace = "29ccf18e‐e559‐4a01‐b5d4‐61bad4a89ffd"
group = "SEATA_GROUP"
}
}
複製代碼
在 org.springframework.cloud:spring-cloud-starter-alibaba-seata
的 org.springframework.cloud.alibaba.seata.GlobalTransactionAutoConfiguration
類中,默認會使用 ${spring.application.name}-seata-service-group
做爲服務名注 冊到 Seata Server上,若是和service.vgroup_mapping配置不一致,會提示 no available server to connect
錯誤 也能夠經過配置 spring.cloud.alibaba.seata.tx-service-group
修改後綴,可是必須 和file.conf
中的配置保持一致
2)在yml中指定事務分組(和配置中心的service.vgroup_mapping 配置一一對應)
application:
name: account‐service
cloud:
nacos:
discovery:
server‐addr: 127.0.0.1:8848
alibaba:
seata:
tx‐service‐group:
my_test_tx_group # seata 服務事務分組
複製代碼
參考源碼: io.seata.core.rpc.netty.NettyClientChannelManager#getAvailServerList 》NacosRegistryServiceImpl#lookup 》String clusterName = getServiceGroup(key); #獲取seata server集羣名稱 》List firstAllInstances = getNamingInstance().getAllInstances(getServiceName(), getServiceGroup(), clusters)
spring cloud alibaba 2.1.4 以後支持yml中配置seata屬性,能夠用來替換registry.conf文件
配置支持實如今seata-spring-boot-starter.jar中,也能夠引入依賴 1 2 io.seata 3 seata‐spring‐boot‐starter 4 1.4.0 5
在yml中配置
# seata 服務分組,要與服務端nacos‐config.txt中service.vgroup_mapping的後綴對應
tx‐service‐group: my_test_tx_group
registry:
# 指定nacos做爲註冊中心
type: nacos
nacos:
server‐addr: 127.0.0.1:8848
namespace: ""
group: SEATA_GROUP
config:
# 指定nacos做爲配置中心
type: nacos
nacos:
server‐addr: 127.0.0.1:8848
namespace: "54433b62‐df64‐40f1‐9527‐c907219fc17f"
group: SEATA_GROUP
複製代碼
3) 在事務發起者中添加@GlobalTransactional註解 核心代碼
//@Transactional
@GlobalTransactional(name="createOrder")
public Order saveOrder(OrderVo orderVo){
log.info("=============用戶下單=================");
log.info("當前 XID: {}", RootContext.getXID());
// 保存訂單
Order order = new Order();
order.setUserId(orderVo.getUserId());
order.setCommodityCode(orderVo.getCommodityCode());
order.setCount(orderVo.getCount());
order.setMoney(orderVo.getMoney());**交流V**(**cmL46679910**)
order.setStatus(OrderStatus.INIT.getValue());**交流V**(**cmL46679910**)
Integer saveOrderRecord = orderMapper.insert(order);
log.info("保存訂單{}", **交流V**(**cmL46679910**)saveOrderRecord > 0 ? "成功" : "失敗");
//扣減庫存
storageFeignService.deduct(orderVo.getCommodityCode(),orderVo.getCount());
//扣減餘額
accountFeignService.debit(orderVo.getUserId(),orderVo.getMoney());
//更新訂單
Integer updateOrderRecord = orderMapper.updateOrderStatus(order.getId(),Orde
rStatus.SUCCESS.getValue());
log.info("更新訂單id:{} {}", order.getId(), updateOrderRecord > 0 ? "成功" :
"失敗");
return order;
}
複製代碼