🎀dubbo 2.7.2 启动报错【Unsupported generic type false】排查

1.问题现象
dubbo服务启动时抛出异常Unsupported generic type false,但不影响服务正常发布。
Caused by: java.lang.IllegalArgumentException: Unsupported generic type false
2. 版本信息
SpringBoot 2.1.3 + Dubbo 2.7.2
3. 问题根因
项目中使用了Spring Boot Actuator模块,Spring Boot Actuator配置独立的管理端口时会创建特殊子上下文(项目中会存在两个上下文实例),导致dubbo对spring上下文刷新事件监控触发两次;
同时开启了dubbo延迟发布(dubbo.provider.delay=3000),由于dubbo 2.7.2中的BUG,两次均会进行了export动作;
同时由于dubbo 2.7.2版本中对generic的判断问题而在第二次export时抛出异常。
4.分析过程
由
message中可以看出:Unsupported generic type false是dubbo泛化调用配置错误告警


4.1. 检查配置是否有误
检查全局中dubbo配置是否存在generic="false"
<dubbo:service generic="false" />
经过检查,项目中无该问题配置
4.2. 堆栈分析
通过检查未发现人为错误配置,进一步分析异常堆栈
具体堆栈如下:
level: ERRORthreadName: mainclassName: o.a.d.c.AbstractConfig - [DUBBO] Failed to override , dubbo version: 2.7.2, current host: xxx.xxx.xxx.xxx
java.lang.reflect.InvocationTargetException: null
at sun.reflect.GeneratedMethodAccessor864.invoke(Unknown Source) ~[?:?]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_412]
at java.lang.reflect.Method.invoke(Method.java:498) ~[?:1.8.0_412]
at org.apache.dubbo.config.AbstractConfig.refresh(AbstractConfig.java:567) ~[dubbo-2.7.2.jar!/:2.7.2]
at org.apache.dubbo.config.ServiceConfig.checkAndUpdateSubConfigs(ServiceConfig.java:304) ~[dubbo-2.7.2.jar!/:2.7.2]
at org.apache.dubbo.config.ServiceConfig.export(ServiceConfig.java:369) ~[dubbo-2.7.2.jar!/:2.7.2]
at org.apache.dubbo.config.spring.ServiceBean.export(ServiceBean.java:336) ~[dubbo-2.7.2.jar!/:2.7.2]
at org.apache.dubbo.config.spring.ServiceBean.onApplicationEvent(ServiceBean.java:114) ~[dubbo-2.7.2.jar!/:2.7.2]
at org.apache.dubbo.config.spring.ServiceBean.onApplicationEvent(ServiceBean.java:60) ~[dubbo-2.7.2.jar!/:2.7.2]
at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172) ~[spring-context-5.1.5.RELEASE.jar!/:5.1.5.RELEASE]
at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:165) ~[spring-context-5.1.5.RELEASE.jar!/:5.1.5.RELEASE]
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139) ~[spring-context-5.1.5.RELEASE.jar!/:5.1.5.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:402) ~[spring-context-5.1.5.RELEASE.jar!/:5.1.5.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:359) ~[spring-context-5.1.5.RELEASE.jar!/:5.1.5.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:896) ~[spring-context-5.1.5.RELEASE.jar!/:5.1.5.RELEASE]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.finishRefresh(ServletWebServerApplicationContext.java:163) ~[spring-boot-2.1.3.RELEASE.jar!/:2.1.3.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:552) ~[spring-context-5.1.5.RELEASE.jar!/:5.1.5.RELEASE]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:142) ~[spring-boot-2.1.3.RELEASE.jar!/:2.1.3.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:775) ~[spring-boot-2.1.3.RELEASE.jar!/:2.1.3.RELEASE]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397) ~[spring-boot-2.1.3.RELEASE.jar!/:2.1.3.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:316) ~[spring-boot-2.1.3.RELEASE.jar!/:2.1.3.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1260) ~[spring-boot-2.1.3.RELEASE.jar!/:2.1.3.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1248) ~[spring-boot-2.1.3.RELEASE.jar!/:2.1.3.RELEASE]
at com.xxx.xxx.xxx.xxx.xxxApiStartUp.main(xxxApiStartUp.java:26) ~[classes!/:?]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_412]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_412]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_412]
at java.lang.reflect.Method.invoke(Method.java:498) ~[?:1.8.0_412]
at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:48) ~[xxx.jar:?]
at org.springframework.boot.loader.Launcher.launch(Launcher.java:87) ~[xxx.jar:?]
at org.springframework.boot.loader.Launcher.launch(Launcher.java:50) ~[xxx.jar:?]
at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:51) ~[xxx.jar:?]
Caused by: java.lang.IllegalArgumentException: Unsupported generic type false
at org.apache.dubbo.config.ServiceConfig.setGeneric(ServiceConfig.java:1015) ~[dubbo-2.7.2.jar!/:2.7.2]
从堆栈上可以看出在ServiceBean这里有对spring事件的监控
查看源码如下:

可以看出dubbo是在spring ApplicationContext 上下文刷新时进行了发布动作export
这里引起思考:为什么实际dubbo服务没有发布失败了?
4.3. 官方issues
前往github检索官方可发现有相同的issues
https://github.com/apache/dubbo/issues/3629

4.4. 源码分析
为什么export两次ServiceConfig会有问题了?
再回到dubbo源码,可以发现在export中有对generic赋默认值false的动作;
在第一次refresh后进行赋值,在第二次refresh时由于generic="false"报错

然而这里并没有结束
在前面duubo serviceBean 对spring上下文刷新事件的监控源码中可以看到,dubbo有对重复发布的屏蔽处理动作

那为什么还能发布两次了?
继续看该发布属性的更新可知,是在serviceConfig doExport之后更新

往上寻找调用栈可以发现:在dubbo export时有两种发布模式:直接发布、延迟发布

看过dubbo源码的同学可以看出,直接发布模式下,应该会被发布属性拦截

可以看出异步发布模式下,第一次异步发布后,第二次上下文刷新事件监控进入时发布属性会无法拦截

前往配置中心也可以看到有相关延迟发布的配置
dubbo.provider.delay=3000
到这里我们取消了延迟发布后,重启后不再报错。
虽然表象问题解决,但根本原因是为什么会触发两次发布动作了?
看源码这里是对spring ApplicationContext上下文刷新事件的监控,触发两次说明有两个个上下文实例。
可以写个工具检测输出下:
@Component
public class ContextRefreshCounter implements ApplicationListener<ContextRefreshedEvent> {
private static int count = 0;
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
System.out.println("Context refreshed, total times: " + ++count);
System.out.println("ApplicationContext instance: " + System.identityHashCode(event.getApplicationContext()));
System.out.println("ApplicationContext id: " + event.getApplicationContext().getId());
}
}

看到有两个上下文:application、application:management


application是根上下文
application:management是Spring Boot Actuator管理端点的子上下文
查看配置中心,发现有配置独立的管理端口
management.server.port=8081
由此可知由于引入了Spring Boot Actuator且配置了独立的管理端口,导致生成多个上下文实例,从而触发了多次spring上下文刷新事件的监控。
5. 官方修复
后续版本官方已针对generic值的判断以及dubbo服务发布逻辑进行了优化,具体可前往github官网查看。
https://github.com/apache/dubbo
结束
🎀dubbo 2.7.2 启动报错【Unsupported generic type false】排查的更多相关文章
- 启动报错 Unsupported major.minor version 51.0
Unsupported major.minor version 51.0错误, 是使用jdk6启动jdk7编译的项目,更换jdk7就好了,或者用jdk6重新打包项目. 解决起来也很方便:打开excli ...
- java 启动报错 Unsupported major.minor version 52.
这是java 版本问题,主要是版本不统一,你看看你开发工具用的java版本(编译的java版本和开发的java版本)是否统一,如果没有统一就会报这个错误.
- jetty启动报错Unsupported major.minor version 51.0
主要是JDK版本的问题,需要将Eclipse的Jdk版本设置为1.7的才可以,编译级别也设置为1.7,然后删除maven项目路径,D:\WORK\workspace\xxx\target下的所有文件, ...
- Linux下Tomcat项目启动报错
Linux下Tomcat项目启动报错 org.springframework.beans.factory.CannotLoadBeanClassException: Error loading cla ...
- docker启动报错iptables failed: -重建docker0网络恢复
# docker启动报错 [root@localhost mysqlconf]# docker run -d -p 8080:8080 --link zookeeper:zookeeper -e du ...
- hbase shell 启动报错
启动hbase之后,发现hbase shell启动报错: version 2.0.0-alpha4, r5c4b985f89c99cc8b0f8515a4097c811a0848835, Tue Oc ...
- Tomcat启动报错org.springframework.web.context.ContextLoaderListener类配置错误——SHH框架
SHH框架工程,Tomcat启动报错org.springframework.web.context.ContextLoaderListener类配置错误 1.查看配置文件web.xml中是否配置.or ...
- 【原】tomcat 7 启动报错:java.lang.NoSuchMethodError: javax.servlet.ServletContext.getSessionCookieConfig()Ljavax/servlet/SessionCookieConfig的解决
现象: tomcat 7 启动报错:java.lang.NoSuchMethodError: javax.servlet.ServletContext.getSessionCookieConfig() ...
- Oracle启动报错ORA-03113解决
环境:RHEL6.4 + Oracle 11.2.0.4 步骤摘要:1.启动报错ORA-031132.查看alert日志查找原因3.根据实际情况采取合理的措施,这里我们先增加闪回区大小,把库启动起来4 ...
- Oracle启动报错ORA-27102解决
环境:RHEL5.5 + Oracle 10.2.0.4 此错误一般是因为数据库的初始化参数文件的内存设置不当导致.本例是因为操作系统参数设置问题导致. 当前现象:Oracle启动报错ORA-2710 ...
随机推荐
- Nodify学习 四:预先连接
前置 预先连接 可以从连接器创建预先连接,并可以放置在ItemContainer或Connector上(如果AllowOnlyConnectors为false). 预先连接的Content可以使用Co ...
- THUWC2024 游记
省流:D1T3,Pretest 97,D2 和 4.so 决斗两小时(胜利). day 0 从成都早上坐火车,中午到了重庆. 坐轻轨到了酒店附近,虽然我不住酒店.lxs 带着吃了一碗面.重庆的面挺好吃 ...
- Java获取数据库的列名、列数、标题、类型等信息, ResultSetMetaData
import java.sql.*; public class jdbcTest { public static void main(String[] args) throws ClassNotFou ...
- python 爬取博客访问量
一.代码 """ Version: Python3.5 Author: OniOn Site: http://www.cnblogs.com/TM0831/ Time: ...
- kubsphere应用系列(三)-创建手动流水线
准备工作 1.1 创建凭证 1.2 添加代码仓库 第一步创建流水线 第二步配置流水线 1.1选择CI/CD模板 1.2删除多余阶段 1.3 配置git仓库信息 1.4配置docker仓库信 ...
- babel-loader 如何工作? 什么是babel-loader插件? babel-loader插件可以干什么? 如何制作一个babel-loader插件?
本文会介绍比较基本的编译知识和babel-loader运作原理 babel-loader 是什么? 作为老一派的打包工具, babel-loader 想必大家已经非常熟悉了.它长这样子 // webp ...
- STM32中如何使用printf()函数
STM32串口通信中使用printf发送数据配置方法(开发环境 Keil RVMDK) 在STM32串口通信程序中使用printf发送数据,非常的方便.可在刚开始使用的时候总是遇到问题,常见的是硬件访 ...
- tortoiseGit no git.exe found
运行tortoiseGit之后显示找不到git.exe 原因:没有安装git,tortoiseGit是在安装了git的基础上运行的 到这里下载git并安装:https://gitforwindows. ...
- Hive - [02] 安装部署
一.相关链接地址 Hive官网:https://hive.apache.org/ Hive下载页面:https://downloads.apache.org/hive/ 中科大镜像地址:http:// ...
- 大数据之路Week10_day07 (JavaAPI 操作Redis 模拟将redis当作缓存,从Mysql数据库中查询数据)
在现实生活中,当很多人去访问一个数据的时候,Mysql会很慢,甚至会挂掉,如果这里之间存在一个缓存的话,直接从内存中查询数据将会快很多. 这里就去模拟将redis看作是一个缓存,因为redis就是基于 ...