首先本文是基于tx-lcn5.0.2release基础写的,springboot2.1.8 cloud版本Greenwich.SR3,如果是其他版本,你可以参考下本文,然后做对应的修改。
tx-lcn会在redis中生成两个key,主要的tmmanager的key是这个tm.instances;如果你配置好tm集群可以看到
一般tc客户端会在配置文件中配置
#是否启动LCN负载均衡策略
tx-lcn.ribbon.loadbalancer.dtx.enabled=true
#-----tx-lcn配置----------
#这个地址其实已经没有用了,但是保留着,防止报错
#已经从redis读取tm信息
tx-lcn.client.manager-address=192.168.1.138:11318,192.168.1.138:11319
但是这样的配置并不灵活,每次要修改配置文件很麻烦。
那我们就直接在redis中读取tm不就行了吗?
首先 建目录 com.codingapi.txlcn.tc.config
建上面目录非常重要!
在该目录中建 TxClientConfig.java
package com.codingapi.txlcn.tc.config;
import com.codingapi.txlcn.common.runner.TxLcnApplicationRunner;
import com.codingapi.txlcn.common.util.ApplicationInformation;
import com.codingapi.txlcn.common.util.id.ModIdProvider;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
/**
* @description: 让tc从redis中读取tm,下面的注解都很重要,不能随便删除,特别是primary
* @author: MuYi Yang
* @create: 2020-01-20 13:46
**/
@Slf4j
@Primary
@ConfigurationProperties(prefix = "tx-lcn.client")
@Component
@Data
public class TxClientConfig {
@Autowired
private StringRedisTemplate stringRedisTemplate;
private static final String REDIS_TM_LIST = "tm.instances";
public TxClientConfig() {
this.dtxAspectOrder = 0;
this.dtxTime = 30 * 1000;
this.managerAddress = Collections.singletonList("127.0.0.1:8070");
}
public List<String> getManagerAddress() {
List<String> managerAddress = stringRedisTemplate.opsForHash().entries(REDIS_TM_LIST).entrySet().stream()
.map(entry -> entry.getKey().toString()).collect(Collectors.toList());
if (CollectionUtils.isEmpty(managerAddress)) {
throw new RuntimeException("在redis没有找到可用的tx-manager地址");
}
if (log.isInfoEnabled()) {
managerAddress.forEach(b -> {
log.info("tm集群地址:-------->" + b);
});
}
return managerAddress;
}
@Bean
public ApplicationRunner txLcnApplicationRunner(ApplicationContext applicationContext) {
return new TxLcnApplicationRunner(applicationContext);
}
@Bean
@ConditionalOnMissingBean
public ModIdProvider modIdProvider(ConfigurableEnvironment environment,
@Autowired(required = false) ServerProperties serverProperties) {
return () -> ApplicationInformation.modId(environment, serverProperties);
}
/**
* aspect order
*/
private Integer dtxAspectOrder;
/**
* aspect connection order
*/
private int resourceOrder;
/**
* txManager check heart time (s)
*/
private int txManagerHeart;
/**
* txManager max delay time (s)
*/
private int txManagerDelay;
/**
* manager hosts
*/
private List<String> managerAddress;
/**
* 调用链长度等级
*/
private int chainLevel = 3;
/**
* Distributed Transaction Time
*/
private long dtxTime;
private long tmRpcTimeout;
private long machineId;
private void setMachineId(long machineId) {
this.machineId = machineId;
}
private void setDtxTime(long dtxTime) {
this.dtxTime = dtxTime;
}
private void setTmRpcTimeout(long timeout) {
this.tmRpcTimeout = timeout;
}
public void applyTmRpcTimeout(long timeout) {
setTmRpcTimeout(timeout);
}
public void applyDtxTime(long dtxTime) {
setDtxTime(dtxTime);
}
public void applyMachineId(long machineId) {
setMachineId(machineId);
}
}
OK,顺利工作!不管是客户端挂掉还是服务端挂掉,都会从redis中剔除,放心开始用吧!