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;
 }
复制代码
相关文章
相关标签/搜索