spring cloud集成seata报错Read timed out问题解决

本文介绍了一种在SpringCloud中集成Seata分布式事务时遇到ReadTimeout问题的解决方案。通过源码分析定位到Ribbon配置未能正确加载的原因,并调整配置文件格式成功解决了调用超时的问题。

spring cloud集成seata报错Read timed out问题解决

问题

最近做项目,需要集成seata实现分布式事务。遇到一个很麻烦的问题,异常能回滚,但是总是测试正常调用时会出现 “ReadTimeOut” 调用超时的异常。异常信息如下:

feign.RetryableException: Read timed out executing POST http://test/test?status=false
	at feign.FeignException.errorExecuting(FeignException.java:213)
	at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:115)
	at feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:80)
	at feign.ReflectiveFeign$FeignInvocationHandler.invoke(ReflectiveFeign.java:103)
	at com.sun.proxy.$Proxy169.test(Unknown Source)
	at com.personal.record.handler.UserHandler.insertUser(UserHandler.java:30)
	at com.personal.record.handler.UserHandler$$FastClassBySpringCGLIB$$5e19999f.invoke(<generated>)
	at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:749)
	...

解决

在网上看了很多方法,试了都不行,于是决定Debug,从源码分析试一试。

通过报错一路追溯,发现是ribben调用时超时报错。
因为之前也配置了ribben的ReadTimedOut参数,但是始终不生效,于是找到ribben的ReadTimedOut注入的位置。

public FeignLoadBalancer(ILoadBalancer lb, IClientConfig clientConfig, ServerIntrospector serverIntrospector) {
        super(lb, clientConfig);
        this.setRetryHandler(RetryHandler.DEFAULT);
        this.clientConfig = clientConfig;
        this.ribbon = RibbonProperties.from(clientConfig);
        RibbonProperties ribbon = this.ribbon;
        this.connectTimeout = ribbon.getConnectTimeout();
        this.readTimeout = ribbon.getReadTimeout();
        this.serverIntrospector = serverIntrospector;
    }
public Integer getReadTimeout() {
        return (Integer)this.get(CommonClientConfigKey.ReadTimeout);
    }
public <T> T get(IClientConfigKey<T> key) {
        return this.config.get(key);
    }
@Override
    public <T> T get(IClientConfigKey<T> key) {
        Object obj = getProperty(key.key());
        if (obj == null) {
            return null;
        }
        Class<T> type = key.type();
        if (type.isInstance(obj)) {
            return type.cast(obj);
        } else {
            if (obj instanceof String) {
                String stringValue = (String) obj;
                if (Integer.class.equals(type)) {
                    return (T) Integer.valueOf(stringValue);
                } else if (Boolean.class.equals(type)) {
                    return (T) Boolean.valueOf(stringValue);
                } else if (Float.class.equals(type)) {
                    return (T) Float.valueOf(stringValue);
                } else if (Long.class.equals(type)) {
                    return (T) Long.valueOf(stringValue);
                } else if (Double.class.equals(type)) {
                    return (T) Double.valueOf(stringValue);
                } else if (TimeUnit.class.equals(type)) {
                    return (T) TimeUnit.valueOf(stringValue);
                }
                throw new IllegalArgumentException("Unable to convert string value to desired type " + type);
            }
             
            throw new IllegalArgumentException("Unable to convert value to desired type " + type);
        }
    }
protected Object getProperty(String key) {
        if (enableDynamicProperties) {
            String dynamicValue = null;
            DynamicStringProperty dynamicProperty = dynamicProperties.get(key);
            if (dynamicProperty != null) {
                dynamicValue = dynamicProperty.get();
            }
            if (dynamicValue == null) {
                dynamicValue = DynamicProperty.getInstance(getConfigKey(key)).getString();
                if (dynamicValue == null) {
                    dynamicValue = DynamicProperty.getInstance(getDefaultPropName(key)).getString();
                }
            }
            if (dynamicValue != null) {
                return dynamicValue;
            }
        }
        return properties.get(key);
    }
String getDefaultPropName(String propName) {
        return getNameSpace() + "." + propName;
    }
@Override
	public String getNameSpace() {
		return propertyNameSpace;
	}
public static final String DEFAULT_PROPERTY_NAME_SPACE = "ribbon";
private String propertyNameSpace = DEFAULT_PROPERTY_NAME_SPACE;

通过Debug及源码分析,程序注入的一直是默认值:1000,配置未注入。而注入ribben的ReadTimedOut的方式是读取 “ribben.ReadTimedOut”配置。在之前的配置中,此项配置一直放在yml文件中:

ribbon:
  ReadTimeout: 10000
  ConnectTimeout: 10000

之后将此项配置放入properties配置文件中

ribbon.ReadTimeout = 10000
ribbon.ConnectTimeout = 10000

重启项目再次调用,发现配置正常注入,不再报超时错误。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值