調式原始碼解決 seata 報錯 can not get cluster name 問題

2023-02-24 12:03:42

最近在使用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方法呼叫,也就是RmNettyRemotingClient99行,新增斷點,重啟服務:

調式上一步,定位到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屬性來設定。

官方檔案更新不及時的時候,這就需要我們調式原始碼的能力。前段時間一直在寫解析原始碼的文章,所以也在嘗試一步步調式程式碼,最終解決了問題,對自己能力也是一次提高。平時開發遇到問題,通過調式原始碼,可以快速的定位問題。

授人以魚不如授人以漁,作為程式設計師,重要的不是找到問題,而是找到問題的解決方案。要追根溯源,做到心中有數,遇問題也不慌。