springboot dubbo配置不识别yml端口配置

springboot dubbo配置不识别yml端口配置

问题:springboot dubbo 自定义了端口,但还是默认启用zookeeper的默认端口 20880,在启动一个的时候就发现20880 端口被占用

先贴上解决方案:springboot dubbo版本的问题,参数值必须使用字符串,而不是数字

或者使用 application.propertiesproperties 的方式进行配置

问题:在springboot yml中配置了dubbo端口,但未生效,但其它参数生效

yml配置

dubbo:
  application:
    name: test-dubbo
  registry:
    protocol: zookeeper
    address: 127.0.0.1:2181
  protocol:
      name: dubbo
      port: 12345

使用的版本

spring-boot 1.5.21 版本

 <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.21.RELEASE</version>
        <!--        <version>2.5.2</version>-->
        <relativePath/>
    </parent>

dubbo-spring-boot-starter 2.0版本

 <dependency>
      <groupId>com.alibaba.spring.boot</groupId>
      <artifactId>dubbo-spring-boot-starter</artifactId>
      <version>2.0.0</version>
</dependency>

zookeeper 3.4.11

<dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-recipes</artifactId>
            <version>2.8.0</version>
        </dependency>


        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.4.11</version>
            <type>pom</type>
        </dependency>

        <dependency>
            <groupId>com.101tec</groupId>
            <artifactId>zkclient</artifactId>
            <version>0.10</version>
        </dependency>

问题比较怪异,如果我把 dubbo.application.name 去掉,那启动会报错,没有设置applicationname名称,那说明有加载这个配置

我在把dubbo.registry.address 删掉,也会报错,说明也加载了该配置

但是 dubbo.protocol.port 去掉、增加都没影响,就很奇怪

后来初步尝试,在springboot的resources 中增加 dubbo.properties 配置,里面就一个配置

#配置dubbo启动端口
dubbo.protocol.port=12345

发现可以按12345 的端口启动 ,唯独不能再yml中设置成功

初步排除

方式一:源代码调试装配情况

后来看源码查看,难道是以前版本prot 属性不对?不是dubbo.protocol.prot 的方式?那为什么dubbo.properties 又可以,难道不应该是数值 应该是字符串? 找到源代码验证下

找装配的时候怎么赋值的 找到 DubboConfigBindingBeanPostProcessorpostProcessBeforeInitialization

image

其中这里也有个port 不要误解了,首先得了解 dubbo最开始的方式 xml

<!-- 注册中心配置 -->
<!-- 这个端口不是必须的,只有当你的 ZooKeeper 服务器配置在非默认端口上时,你才需要指定 port-->
<dubbo:registry protocol="zookeeper" address="zookeeper://127.0.0.1" port="2888"/>

<!--通常这样配置-->
<dubbo:registry protocol="zookeeper" address="zookeeper://127.0.0.1:2888"/>

<!-- 协议配置 port 也不是必须的,-1 表示自动递增,避免影响端口用情况 ,20880为默认端口-->
<dubbo:protocol name="dubbo" port="20880"/>

所以 RegistryConfig 并不是我们要找的对象,这个是注册中心的相关配置,端口是注册中心的端口

image

在继续找,我们要找的是 ProtocolConfig 中的 port,ProtocolConfig中 port 也是Integer 类型的

image

继续,这里只读取到 protocol 的 name属性,没有port ,从这一步就没有读到了

image

方式二:日志查看装配情况

上面这个方法太笨了,通过上面源代码方式查看,如果开启了日志会打印日子

image

我们查看日志分析下也可以得出结论,没有装配上


1702602011513.jpg

没有装配上使用了默认的端口 20880,在继续往上找,看那个步骤读取了配置

排查可疑点:查询装配情况(结论:未在此,但不会调试的可以看看)

为了更好的看日志情况,把logging 改为DEBUG 模式,打印尽可能详尽的日志

logging:
  level:
    org.springframework: DEBUG

先启动,然后查看日志 筛选刚才我们找到的 DubboConfigBindingBeanPostProcessor 类 在看上面打印的日子,有没有可疑的地方

看到MutablePropertySources 添加了 application.yml 配置文件

image

那我们找下 idea按两下shift,查找 MutablePropertySources,然后在搜索 Adding PropertySource

image

可以看到配置文件中,读取的话 是读取到了这个20897的端口的,这个地方没问题

image-20231213145305-d1j3qbd.png

那继续往下看日志,看到附近代码,创建

Creating shared instance of singleton bean 'com.alibaba.dubbo.config.spring.ServiceBean#0'

然后在调用了ServiceBean 里面的 afterPropertiesSet 方法

Invoking afterPropertiesSet() on bean with name 'com.alibaba.dubbo.config.spring.ServiceBean#0'
image

我们看下这个afterPropertiesSe方法做了什么

同样搜索ServiceBean

image

因为我们是dubbo上有问题,我们先排查dubbo的配置问题,所以打开第一个com.alibab:dubbo的 ServiceBean

然后发现,就是这里有问题,鸡冻啊

image

关键代码找到了


Map<String, ProtocolConfig> protocolConfigMap = this.applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(this.applicationContext, ProtocolConfig.class, false, false);

进去BeanFactoryUtils.beansOfTypeIncludingAncestors 看下

public static <T> Map<String, T> beansOfTypeIncludingAncestors(ListableBeanFactory lbf, Class<T> type, boolean includeNonSingletons, boolean allowEagerInit) throws BeansException {
        Assert.notNull(lbf, "ListableBeanFactory must not be null");
        Map<String, T> result = new LinkedHashMap(4);
        result.putAll(lbf.getBeansOfType(type, includeNonSingletons, allowEagerInit));
        if (lbf instanceof HierarchicalBeanFactory) {
            HierarchicalBeanFactory hbf = (HierarchicalBeanFactory)lbf;
            if (hbf.getParentBeanFactory() instanceof ListableBeanFactory) {
                Map<String, T> parentResult = beansOfTypeIncludingAncestors((ListableBeanFactory)hbf.getParentBeanFactory(), type, includeNonSingletons, allowEagerInit);
                Iterator var7 = parentResult.entrySet().iterator();

                while(var7.hasNext()) {
                    Map.Entry<String, T> entry = (Map.Entry)var7.next();
                    String beanName = (String)entry.getKey();
                    if (!result.containsKey(beanName) && !hbf.containsLocalBean(beanName)) {
                        result.put(beanName, entry.getValue());
                    }
                }
            }
        }

        return result;
    }

重启后打断点在这,会有很多断点进来,只认准这个,其他的都释放跳过(其他断点放开,只留上面ServiceBean 断点进去后改逐步调试)进入 BeanFactoryUtilsbeansOfTypeIncludingAncestors

image

找到 进入ServiceBean 断点后

在这打个断点result.putAll(lbf.getBeansOfType(type, includeNonSingletons, allowEagerInit));

image

再进入断点 getBeansOfType 怎么获取result的

Step Over :我暂且叫逐行调试吧

Step into :我暂且叫步调试吧

image

到这步的时候用逐步调试,会是这样的美景如getBeansOfType

image

在往下逐行跳过第一个,然后逐步跳过getBeanFactory

image

会进入getBeansOfType

image

在getBeansOfType中,先获取对应className名称,然后在给该对象赋值,在result.put方法中打个断点,我们看下这个getBean做了什么

image

进入doGetBean 方法

image

在找到关键代码

Object sharedInstance = this.getSingleton(beanName);

image

在逐步调试,看 getSingleton 做了什么

image

很遗憾,这里只是装配了下bean,并没有赋值的地方

image

这个地方只负责获取转载好的bean,这里只是根据className 获取对应属性内容

结论其实很早就给出了,最开始:我们看下这个afterPropertiesSe方法做了什么?

这一步骤 是设置属性后的意思,这给我蠢的

再次找问题所在

根据上2次经验,获取yml配置没问题,但设置属性后就没这个端口了,那出现意外就在这中间了,在找下日志吧

我们在debug日志中直接搜索,ProtocolConfig ,因为按上次拍错来看,是有创建这个对象的,先看下

尴尬:由于日志太多,被刷掉了,看日志文件吧

image

先配置下日志文件记录吧

logging:
  level:
    org.springframework: DEBUG
  file:
    #重点代码,再这里记录日志
    name: logs/test.log
  pattern:
    console: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"
    file: "%d{yyyy-MM-dd} [%thread] %-5level %logger{35} - %msg%n"
  encoder:
    pattern:
      console: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"
      file: "%d{yyyy-MM-dd} [%thread] %-5level %logger{35} - %msg%n"
  rollingpolicy:
    file:
#      max-history: 7
      total-size-cap: 1GB
      clean-history-on-start: true

然后再启动,项目所在文件夹下有个logs/test.log文件,再搜索ProtocolConfig

好家伙 找到了,是这个打的日志,DubboConfigBindingRegistrar,盘它

image

有2个,选择一样的就好了,选第一个,第二个明显多了个s

image

根据日志提示:The dubbo config bean definition,那就搜索这个

image

这个和日志打印结果一致

image

但是吧,根据前车之鉴,我们定位下这个属于哪个包下面的

image

发现是com.alibab 2.6 是我们在用的版本,类名 DubboConfigBindingRegistrar 大概意思也是 Dubbo配置绑定注册器 所以这个时候千万别客气,给他掐断,再重启

这个我们就过,我们要的是 com.alibaba.dubbo.config.ProtocolConfig

image

逮着了

image

然后在这打断点,registerBeanDefinition 注册Bean定义 ,然后逐步断点

image

前面是一些断言,我们看下面的代码比较符合

image

发现这并没有可疑之处,返回数据是空的
image

逐行调试,最后返回了上面

image

这个逐行结束后,日志打印了,但跳到了上面的代码中

image

原来是上面代码中调用了registerDubboConfigBean 方法,这个方法结束后,要继续运行接下来的代码,所以返回到了上面,那也就是上面那个方法 registerDubboConfigBeans 是先执行的,那我们在打断点在此处,且看到了熟悉的 PropertySources 这里是获取系统参数配置的地方,看来接近真相了

image

同样的,我们只要 com.alibaba.dubbo.config.ProtocolConfig 类,其他的都放行,看下有哪些配置

image

applicationConfigurationProperties ,这个熟悉吧,应用程序配置属性

image

接下来就是怎么去获取参数了,下面这个关键代码才是,通过属性名称 去匹配 prefix 传入进来的属性名称,获取对应的参数值

image

逐步进入 PropertySourcesUtils.getSubProperties

这里大概就是从上面PropertySources 所有属性中 匹配 dubbo.protocol 配置

image

获取参数过程

image

获取dubbo.protocol.name 的值

image

过分了,这里判断是否是字符串,是字符串才加入进去,不是的话就不配值!!!!

image

按道理,里面还会又个端口配置,下一个遍历,可以获取到我们配置的自定义端口 20897端口

image

但是,它是integer 数值类型的,所以被无情的抛弃了

是的,非字符串不配!!!

原因找到了,那我们就改为字符串吧,看来所有关于dubbo的数字类的都要是字符串,不然没办法加入到配置中,

#目前版本 数字参数一定要用字符串格式,不能直接用数字,否则装配补上
dubbo:
  application:
    name: test-dubbo
  registry:
    protocol: zookeeper
    address: 127.0.0.1:2181
  protocol:
      name: dubbo
    #圈重点:该属性值要为字符串,后面的也要,后面贴图
      port: "20897"
  provider:
    #group: "biao"
    timeout: "10000"
    threadpool: fixed
    threads: "100"
    accepts: "1000"
  consumer:
    timeout: "10000"  # 消费者超时时间,单位:毫秒
    retries: "0"  # 默认重试都为0次
    check: false  # 不检查消费服务有没有启用

看来是com.alibab.dubbo 2.6.0的版本问题

image

看下,是dubbo-spring-boot-starter 2.0.0 版本里自带的

image
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,752评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,100评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,244评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,099评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,210评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,307评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,346评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,133评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,546评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,849评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,019评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,702评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,331评论 3 319
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,030评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,260评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,871评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,898评论 2 351

推荐阅读更多精彩内容