JAVA互聯網架構師專題/分佈式/高併發/微服務(二)

【嚴選】JAVA互聯網架構師專題/分佈式/高併發/微服務

點點我:JAVA互聯網架構師專題/分佈式/高併發/微服務 提取馬:xb2kjava

  1. 啓動Seata Server

1.1 環境準備 1)指定nacos做爲配置中心和註冊中心 修改registry.conf文件 VcmL46679910mysql

image.png

image.png 注意:客戶端配置registry.conf使用nacos時也要注意group要和seata server中的 group一致,默認group是"DEFAULT_GROUP"redis

2)同步seata server的配置到nacosspring

獲取/seata/script/config-center/config.txt,修改配置信息sql

image.png 配置事務分組, 要與客戶端配置的事務分組一致 (客戶端properties配置:spring.cloud.alibaba.seata.tx‐servicegroup= my_test_tx_group)shell

image.png 配置參數同步到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交流VcmL46679910) -p: port,默認值 8848 -g: 配置分組,默認值爲 'SEATA_GROUP' -t: 租戶信息,對應 Nacos 的命名空間ID字段, 默認值爲空 ''apache

image.png 3) 啓動Seata Servermarkdown

啓動Seata Server命令 bin/seata‐server.sh 啓動成功,默認端口8091session

image.png 在註冊中心中能夠查看到seata-server註冊成功

image.png

  1. Seata如何整合到Spring Cloud微服務

業務場景:

用戶下單,整個業務邏輯由三個微服務構成: 倉儲服務:對給定的商品扣除庫存數量。 訂單服務:根據採購需求建立訂單。 賬戶服務:從用戶賬戶中扣除餘額。 點點我:JAVA互聯網架構師專題/分佈式/高併發/微服務 提取馬:xb2k

image.png 環境準備: 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)

image.png

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,交流VcmL46679910log_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代理本身的數據源

複製代碼

/**

  • @author Fox
  • 須要用到分佈式事務的微服務都須要使用seata DataSourceProxy代理本身的數據源

*/ @Configuration @MapperScan("com.tuling.datasource.mapper") public class MybatisConfig {

/**

  • 從配置文件獲取屬性構造datasource,注意前綴,這裏用的是druid,根據本身狀況配置,
  • 原生datasource前綴取"spring.datasource"
  • @return

/ @Bean @ConfigurationProperties(prefix = "spring.datasource") public DataSource druidDataSource() { DruidDataSource druidDataSource = new DruidDataSource(); return druidDataSource; } 交流VcmL46679910) /*

  • 構造datasource代理對象,替換原來的datasource
  • @param druidDataSource
  • @return

*/ @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 {交流VcmL46679910

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-seataorg.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;
 }
複製代碼
相關文章
相關標籤/搜索