DUBBO 2.6.5 升级到 2.6.8

 

dubbo升级遇到问题

近期对@Reference修饰的consumer接口进行设置超时时间,之前所用dubbo版本是2.6.5

遇到问题是想对具体方法设置超时时间。xml配置有个<method> 可设置,现项目Springboot 配置注解化了,以前的xml此处就不说明了。

开始找的方法是在 @Reference 注解的 param下添加参数

parameters = {"searchExerciseRelevant.timeout", "10", "searchExerciseByDrawers.timeout", "10"}

@ignore(10ms 是方便测试下是否有效)

dubbo导出服务的时候就是把这些配置拼到组成的url链接上,在invoke的时候会取相应的参数取做处理,此处直接拼上去即可解决问题。

后来查看dubbo github上版本,2.6.6之后的版本已经加上了 methods参数,于是升级了下dubbo版本。最终配置成如下

@Reference(timeout = 1200000,
        methods = {@Method(name = "searchExerciseRelevant", timeout = 10000),
            @Method(name = "searchExerciseByDrawers", timeout = 10000)}
        )

代码是配置好了,但是在启动的时候发现项目起不来了.

问题1

java.lang.IllegalStateException: Invalid name="com.alibaba.dubbo.config.ProtocolConfig#0" contains illegal character, only digit, letter, '-', '_' or '.' is legal

大致意思就是设置名字不合法

找了找解决方法是给dubbo.protocol.name 设置个名字,

protocol:
    port: 20919
    name: dubbo

经查看代码为啥会有名字不合法,问题出在com.alibaba.dubbo.config.spring.context.config.NamePropertyDefaultValueDubboConfigBeanCustomizer#customize方法上,这个类的这个方法意思是如果有name属性 且存在get set 方法,参数是string,但name属性的值为空时,会给设置个名字,此处取beanName作为name属性名称。ProtocolConfig 是通过springBean起名的方式获取的,具体方法com.alibaba.dubbo.config.spring.context.annotation.DubboConfigBindingRegistrar#resolveSingleBeanName

private String resolveSingleBeanName(Map<String, Object> properties, Class<? extends AbstractConfig> configClass,
                                         BeanDefinitionRegistry registry) {

        String beanName = (String) properties.get("id");

        if (!StringUtils.hasText(beanName)) {
            BeanDefinitionBuilder builder = rootBeanDefinition(configClass);
            beanName = BeanDefinitionReaderUtils.generateBeanName(builder.getRawBeanDefinition(), registry);
        }

        return beanName;

    }
BeanDefinitionReaderUtils.generateBeanName 返回的beanname是带#的。

customize 方法在执行setName的时候会调用父类AbstractConfig的checkName方法,对name值做检测抛出异常。

    private static final Pattern PATTERN_NAME = Pattern.compile("[\\-._0-9a-zA-Z]+");
    protected static void checkName(String property, String value) {
        checkProperty(property, value, MAX_LENGTH, PATTERN_NAME);
    }
    protected static void checkProperty(String property, String value, int maxlength, Pattern pattern) {
        if (value == null || value.length() == 0) {
            return;
        }
        if (value.length() > maxlength) {
            throw new IllegalStateException("Invalid " + property + "=\"" + value + "\" is longer than " + maxlength);
        }
        if (pattern != null) {
            Matcher matcher = pattern.matcher(value);
            if (!matcher.matches()) {
                throw new IllegalStateException("Invalid " + property + "=\"" + value + "\" contains illegal " +
                        "character, only digit, letter, '-', '_' or '.' is legal.");
            }
        }
    }

问题2

The bean 'dubboConfigConfiguration.Single', defined in null, could not be registered. A bean with that name has already been defined in null and overriding is disabled.

Action:

Consider renaming one of the beans or enabling overriding by setting spring.main.allow-bean-definition-overriding=true
按提示设置allow-bean-definition-overriding=true 报错可解决

main:
    allow-bean-definition-overriding: true
2.6.5之前是使用 DubboConfigConfigurationSelector 实现ImportSelector 返回类名称去加载的
2.6.8是使用 DubboConfigConfigurationRegistrar 实现ImportBeanDefinitionRegistrar 使用Spring工具类注
册加载的

为什么会重复注册呢,跟进代码发现由于上面2个类的实现区别和@EnableDubboConfig 的默认值为true导致。

Springboot集成dubbo DubboAutoConfiguration类里定义了2个@EnableDubboConfig修饰的内部类,分别代表单配置和多配置,根据这个注解,分别去注册相对应的bean

在版本2.6.5 @EnableDubboConfig 的multiple 的默认属性为false

DubboConfigConfigurationSelector 代码中对muliple 为true和false时分别只注册一个bean

    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {

        AnnotationAttributes attributes = AnnotationAttributes.fromMap(
                importingClassMetadata.getAnnotationAttributes(EnableDubboConfig.class.getName()));

        boolean multiple = attributes.getBoolean("multiple");

        if (multiple) {
            return of(DubboConfigConfiguration.Multiple.class.getName());
        } else {
            return of(DubboConfigConfiguration.Single.class.getName());
        }
    }

在版本2.6.8 @EnableDubboConfig 的multiple 的默认属性为true

DubboConfigConfigurationRegistrar 代码就有点意思了,默认注册单配置的bean,根据multiple参数去注册多配置的bean

public class DubboConfigConfigurationRegistrar implements ImportBeanDefinitionRegistrar {

    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

        AnnotationAttributes attributes = AnnotationAttributes.fromMap(
                importingClassMetadata.getAnnotationAttributes(EnableDubboConfig.class.getName()));

        boolean multiple = attributes.getBoolean("multiple");

        // Single Config Bindings
        registerBeans(registry, DubboConfigConfiguration.Single.class);

        if (multiple) { // Since 2.6.6 https://github.com/apache/incubator-dubbo/issues/3193
            registerBeans(registry, DubboConfigConfiguration.Multiple.class);
        }
    }
}

根据目前的DubboAutoConfiguration,会执行2次此逻辑,bean会重复注册,所以Spring会报错提示。

后来升级了dubbo 2.7.4.1 在这个版本 @EnableDubboConfig注解是放在@EnableDubbo 注解上,DubboConfigConfigurationRegistrar的逻辑只会执行一次,不用配置Spring覆盖为true也没事。

相对应的版本Springboot集成dubbo的boot-start jar包中的 DubboAutoConfiguration 采用了@Import 直接导入bean

本次dubbo使用问题分析到此,有疑问可留言,继续更新😄

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值