最近在使用Spring Cloud
整合分布式事务seata
,项目启动之后,控制台一直报错:
can not get cluster name in registry config 'service.vgroupMapping.nacos-provide-order-seata-service-group', please make sure registry config correct
can not get cluster name in registry config 'service.vgroupMapping.nacos-provide-order-seata-service-group', please make sure registry config correct
can not get cluster name in registry config 'service.vgroupMapping.nacos-provide-order-seata-service-group', please make sure registry config correct
无法在注册配置上找到
service.vgroupMapping.nacos-provide-order-seata-service-group
配置。
问题分析
搭建seata
服务,需要用到配置中心,将配置文件config.txt
上传到Nacos
配置中心,其中有一项配置是:
service.vgroupMapping.default_tx_group=default
这个配置和控制台报错信息很像:
service.vgroupMapping.nacos-provide-order-seata-service-group
这个配置就是事务分组,从 官网文档 看到事务分组的配置:
总结就是需要在客户端的配置文件添加配置seata.tx-service-group=xxx
,seata
通过这个配置去Nacos
配置中心寻找配置service.vgroupMapping.xxx
。
上面导入的配置为service.vgroupMapping.default_tx_group
,所以在application.yml
文件添加配置:
seata:
tx-service-group: default_tx_group
项目重新启动,还是同样的报错
既然提示找不到配置,在配中心添加配置文件nacos-provide-order-seata-service-group
:
添加配置之后,就不报错了,文档有说明:
获取事务分组(服务启动时加载配置)
spring/springboot
可配置在yml、properties
中,对应值”my_test_tx_group”即为事务分组名,若不配置则默认以:spring.application.name
值+-seata-service-group
拼接后的字符串作为分组名。
seata还是按照默认的配置spring.application.name
+ -seata-service-group
去配置中心找配置,上面的配置没有生效。
调式源码
报错是在NettyClientChannelManager
类的176
行:
transactionServiceGroup
表示事务分组名,调式到分组名值为nacos-provide-stock-seata-service-group
,说明配置seata.tx-service-group
没有生效,就需要找到transactionServiceGroup
来源。
一般调式代码,都是调式下一步
,往上调式就用到了调式的上一步
:
从上面的断点调式上一步,就定位到RmNettyRemotingClient
类的第194
行:
transactionServiceGroup
是一个实例变量,需要唯一赋值该变量的地方就在RmNettyRemotingClient
类的第140
行:
setTransactionServiceGroup
方法被本类的getInstance
方法调用,也就是RmNettyRemotingClient
类99
行,添加断点,重启服务:
调式上一步,定位到RMClient
类的init
方法:
调式上一步,定位到GlobalTransactionScanner
类的201
行:
此时txServiceGroup
又是一个实例变量,找到变量赋值的位置:
添加断点之后,重启服务,到了断点,再点击上一步,一直定位到GlobalTransactionAutoConfiguration
:
@Bean
public GlobalTransactionScanner globalTransactionScanner() {
String applicationName = applicationContext.getEnvironment()
.getProperty("spring.application.name");
String txServiceGroup = seataProperties.getTxServiceGroup();
if (StringUtils.isEmpty(txServiceGroup)) {
txServiceGroup = applicationName + "-seata-service-group";
seataProperties.setTxServiceGroup(txServiceGroup);
}
return new GlobalTransactionScanner(applicationName, txServiceGroup);
}
txServiceGroup
首先通过seataProperties.getTxServiceGroup
获取,如果为null
,就使用applicationName
+ -seata-service-group
。
从最终报错位置看,seataProperties.getTxServiceGroup
无法获取txServiceGroup
,先看getTxServiceGroup
获取数据:
@ConfigurationProperties("spring.cloud.alibaba.seata")
public class SeataProperties {
// todo support config Seata server information
/**
* Seata tx service group.default is ${spring.application.name}-seata-service-group.
*/
private String txServiceGroup;
public String getTxServiceGroup() {
return txServiceGroup;
}
public void setTxServiceGroup(String txServiceGroup) {
this.txServiceGroup = txServiceGroup;
}
}
最终发现
txServiceGroup
是通过配置spring.cloud.alibaba.seata.tx-service-group
内容获取。
问题解决
在application.yml
文件配置配置,
spring:
cloud:
alibaba:
seata:
tx-service-group: default_tx_group
seata
获取到default_tx_group
属性后,在nacos
配置中心找到service.vgroupMapping.default_tx_group
配置。
总结
-
Spring Cloud
整合seata
,控制台报错can not get cluster name in registry config 'service.vgroupMa
- 查询文档,nacos添加了
service.vgroupMapping.xxx
配置,就需要在yml
文件上seata.tx-service-group=xxx
配置。添加后控制台还是报错。 - 调式源码,找到报错代码位置,一步一步向上调试,找到分组事务无法设置的原因,最后发现分组事务是根据
spring.cloud.alibaba.seata.tx-service-group
属性来设置。
官方文档更新不及时的时候,这就需要我们调式源码的能力。前段时间一直在写解析源码的文章,所以也在尝试一步步调式代码,最终解决了问题,对自己能力也是一次提高。平时开发遇到问题,通过调式源码,可以快速的定位问题。
授人以鱼不如授人以渔,作为程序员,重要的不是找到问题,而是找到问题的解决方案。要追根溯源,做到心中有数,遇问题也不慌。