2021-08-26Dubbo踩坑笔记

Dubbo开发的时候,如果有相同接口,多个不同实现的服务同时需要发布的时候,如何处理?如果有多个同名服务,需要同时发布的时候,如何处理?如果请求参数或响应结果,数据容量过大(超过8M),如何 Dubbo开发的时候,如果有相同接口,多个不同实现的服务同时需要发布的时候,如何处理?如果有多个同名服务,需要同时发布的时候,如何处理?如果请求参数或响应结果,数据容量过大(超过8M),如何处理? ... 阅读详情

背景

由于项目是多人协作,服务调用使用的dubbo,在定义接口出入参的时候,我自己定义了一个基本入参xxxReq,包含了两个分页属性,后续有其他同事将此类继承了一个BaseReq。base中包含分页字段。
本地单元测试,接口都能根据分页数据的值查询出对应的数据,但是dubbo Consumer端查出的数据一直是走的默认数据。而且服务器上,根据分页条目的属性名查询日志,根本查不到日志输出,由于默认数据与数据库条目还是一致的,所以错误的以为触发了dubbo的缓存机制,并没有真正的将请求打到服务器上,也导致排查错误浪费了很多时间。

结果

后来停掉所有服务请求,仅保留出问题的请求,发送请求后,发现日志有打印输出,只不过分页字段的值都是null。所以将目光转向了出入参,发现了父子类的字段重复了,猜测是序列化问题,去除子类中的分页属性后,重新请求,Consumer正常,问题解决。

深入学习与分析

采用的是dubbo缺省协议,序列化方式是Hessian序列化,在反序列化时会出现父类的同名属性覆盖子类的同名属性问题,所以就变成null,解析不到了。
查看dubbo源码hessian下面,有很多Serializer。
在这里插入图片描述
以JavaSerializer为例学习一下序列化过程:

public JavaSerializer(Class cl, ClassLoader loader) {
        this.introspectWriteReplace(cl, loader);
        if (this._writeReplace != null) {
            this._writeReplace.setAccessible(true);
        }

        ArrayList primitiveFields = new ArrayList();

        ArrayList compoundFields;
        int i;
        for(compoundFields = new ArrayList(); cl != null; cl = cl.getSuperclass()) {
            Field[] fields = cl.getDeclaredFields();

            for(i = 0; i < fields.length; ++i) {
                Field field = fields[i];
                if (!Modifier.isTransient(field.getModifiers()) && !Modifier.isStatic(field.getModifiers())) {
                    field.setAccessible(true);
                    if (!field.getType().isPrimitive() && (!field.getType().getName().startsWith("java.lang.") || field.getType().equals(Object.class))) {
                        compoundFields.add(field);
                    } else {
                        primitiveFields.add(field);
                    }
                }
            }
        }

        ArrayList fields = new ArrayList();
        fields.addAll(primitiveFields);
        fields.addAll(compoundFields);
        this._fields = new Field[fields.size()];
        fields.toArray(this._fields);
        this._fieldSerializers = new JavaSerializer.FieldSerializer[this._fields.length];

        for(i = 0; i < this._fields.length; ++i) {
            this._fieldSerializers[i] = getFieldSerializer(this._fields[i].getType());
        }

    }

没怎么看懂,但是for循环的大致意思就是先遍历子类的属性进行存储,然后再进行父类的属性。

以JavaDeserializer为例学习一下序列化过程:

    public JavaDeserializer(Class cl) {
        this._type = cl;
        this._fieldMap = this.getFieldMap(cl);
        this._readResolve = this.getReadResolve(cl);
        if (this._readResolve != null) {
            this._readResolve.setAccessible(true);
        }

        Constructor[] constructors = cl.getDeclaredConstructors();
        long bestCost = 9223372036854775807L;

        for(int i = 0; i < constructors.length; ++i) {
            Class[] param = constructors[i].getParameterTypes();
            long cost = 0L;

            for(int j = 0; j < param.length; ++j) {
                cost = 4L * cost;
                if (Object.class.equals(param[j])) {
                    ++cost;
                } else if (String.class.equals(param[j])) {
                    cost += 2L;
                } else if (Integer.TYPE.equals(param[j])) {
                    cost += 3L;
                } else if (Long.TYPE.equals(param[j])) {
                    cost += 4L;
                } else if (param[j].isPrimitive()) {
                    cost += 5L;
                } else {
                    cost += 6L;
                }
            }

            if (cost < 0L || cost > 65536L) {
                cost = 65536L;
            }

            cost += (long)param.length << 48;
            if (cost < bestCost) {
                this._constructor = constructors[i];
                bestCost = cost;
            }
        }

        if (this._constructor != null) {
            this._constructor.setAccessible(true);
            Class[] params = this._constructor.getParameterTypes();
            this._constructorArgs = new Object[params.length];

            for(int i = 0; i < params.length; ++i) {
                this._constructorArgs[i] = getParamArg(params[i]);
            }
        }

    }

后面一大堆很难懂,就看到一行this._fieldMap = this.getFieldMap(cl);这个是获取属性集合的一个方法,跟进去看一下:

protected HashMap getFieldMap(Class cl) {
        HashMap fieldMap;
        for(fieldMap = new HashMap(); cl != null; cl = cl.getSuperclass()) {
            Field[] fields = cl.getDeclaredFields();

            for(int i = 0; i < fields.length; ++i) {
                Field field = fields[i];
                if (!Modifier.isTransient(field.getModifiers()) && !Modifier.isStatic(field.getModifiers()) && fieldMap.get(field.getName()) == null) {
                    try {
                        field.setAccessible(true);
                    } catch (Throwable var8) {
                        var8.printStackTrace();
                    }

                    Class type = field.getType();
                    Object deser;
                    if (String.class.equals(type)) {
                        deser = new JavaDeserializer.StringFieldDeserializer(field);
                    } else if (Byte.TYPE.equals(type)) {
                        deser = new JavaDeserializer.ByteFieldDeserializer(field);
                    } else if (Short.TYPE.equals(type)) {
                        deser = new JavaDeserializer.ShortFieldDeserializer(field);
                    } else if (Integer.TYPE.equals(type)) {
                        deser = new JavaDeserializer.IntFieldDeserializer(field);
                    } else if (Long.TYPE.equals(type)) {
                        deser = new JavaDeserializer.LongFieldDeserializer(field);
                    } else if (Float.TYPE.equals(type)) {
                        deser = new JavaDeserializer.FloatFieldDeserializer(field);
                    } else if (Double.TYPE.equals(type)) {
                        deser = new JavaDeserializer.DoubleFieldDeserializer(field);
                    } else if (Boolean.TYPE.equals(type)) {
                        deser = new JavaDeserializer.BooleanFieldDeserializer(field);
                    } else if (Date.class.equals(type)) {
                        deser = new JavaDeserializer.SqlDateFieldDeserializer(field);
                    } else if (Timestamp.class.equals(type)) {
                        deser = new JavaDeserializer.SqlTimestampFieldDeserializer(field);
                    } else if (Time.class.equals(type)) {
                        deser = new JavaDeserializer.SqlTimeFieldDeserializer(field);
                    } else {
                        deser = new JavaDeserializer.ObjectFieldDeserializer(field);
                    }

                    fieldMap.put(field.getName(), deser);
                }
            }
        }

        return fieldMap;
    }

把序列化中的属性List放到HashMap中,HashMap: fieldMap.put(field.getName(), deser);由于map的key是field.getName(),由于父类后遍历,所以在最后把父类属性的null,传给了fieldMap。因此在反序列化时,将map读出来时出现了null值。

根据情况分析,仅代表个人愚见,有偏颇之处还望指出~

根据IP动态路由调用Dubbo服务 一、前言 前面我们探讨了如何获取某一个Dubbo的服务的提供者列表,本节我们探讨如何使用Dubbo的扩展,实现指定IP调用。 二、实现 在Dubbo中集群容错策略Cluster是SPI扩展接口,DUbbo框架提供了丰富的集群容错策略实现,本节我们就基于扩展接口实现指定IP调用功能。 首先我们实现扩展接口Cluster: [Java]纯文本查看复制代码 ? 1 ... 阅读详情

相关推荐

【实战指南】WinPE环境下360系统急救箱的病毒查杀全流程解析

本文详细解析了在WinPE环境下使用360系统急救箱进行病毒查杀的全流程。从制作WinPE启动盘到进入PE环境,再到360急救箱的深度使用和系统修复,提供了实用技巧和常见问题解决方案,帮助用户高效清除顽固病毒。

weixin_28568819的博客 535

dubbo

文章目录dubbo是什么?Dubbo 架构什么是 RPC?dubbo-admin的下载安装dubbo+springboot快速入门1.使用zookeeper来作为注册中心2.搭建公共接口(API)模块3.搭建服务提供者(provider)4.搭建服务消费者(consumer)5.源码地址 dubbo是什么? Dubbo是阿里巴巴公司开源的一个高性能优秀的服务框架,使得应用可通过高性能的 RPC 实现服务的输出和输入功能,可以和Spring框架无缝集成。 Dubbo是一款高性能、轻量级的开源Java RPC

qq_42418169的博客 682

记一次处理Spring-boot使用dubbo类型转换失败的问题

3、使用Bootstrap或Extension的ClassLoader做返回,这样也能正常返回,比如用Object接收,但对Dubbo返回的对象,使用强转,也存在加载器不同,不能强转的问题,之后就需要借助反射,反射针对的是属性和方法,不同的加载器也是可以处理的,这样就处理了一个,但每个地方都需要反射,就提炼出一个公共的类处理。第三步、查看报错信息,同一个类型转换失败,但后面加了个RestartClassLoader,没有引入自己实现过这个ClassLoader啊,一般用的是。

熊浪的博客 1063

AXI4-Stream FIFO IP核实战指南——从配置到跨时钟域处理

本文是AXI4-Stream FIFO IP核的实战指南,详细讲解了其作为数据流缓冲核心的作用。文章重点涵盖从Vivado环境下的IP核配置、关键参数(如深度与宽度)设定,到跨时钟域处理的完整流程。深入解析了TVALID/TREADY握手协议及TLAST等信号,并提供了常见问题排查与调试技巧,帮助开发者高效实现FPGA/SoC系统中可靠的数据流缓冲与同步。

weixin_29251567的博客 480

别再只放按钮了!巧用微信小程序‘长按识别’功能,打造无缝加群体验

本文深入探讨了微信小程序'长按识别'功能在社群运营中的创新应用,通过简化加群流程至一步操作,显著提升用户转化率。文章详细解析了技术实现细节、UI/UX设计策略,并对比了与企业微信API的适用场景,为开发者提供打造无缝加群体验的完整解决方案。

weixin_42627853的博客 434

dubbo同名方法的问题及思考

背景 今天小伙伴问我一个问题 分析 我们系统中一直存在该种实践 似乎从来都稳稳的运行,没有任何问题呢…… 比如 * * 查询客户List * @param customerCarVO * @param curPage * @return * @throws Exception */ @Deprecated PageResult&lt;CustomerCarVO&gt;...

技术分享 9085

基于PSO-BP神经网络的风电功率预测研究论文复现

风电功率预测。基于PSO-BP神经网络的风电功率预测论文复现。matlab程序,注释清晰。

weixin_825487230的博客 2295

dubbo缺省协议父类和子类拥有相同属性导致的反序列化为null问题排查

今天在工作中遇到一个问题:由于自己的疏忽,定义dubbo接口入参时,WareQueryPageDTO继承了一个父类BizCodeBaseDTO,但是有个属性String bizCode,父类和子类中都存在。本地单元测试,接口都能根据bizCode值查询出对应的数据,但是dubbo Consumer端查出的数据一直是错误的。 检查日志发现,接口消费端明明传入了bizCo...

灵颖桥人的博客 3485

基于NB-IoT的智慧路灯监控系统(NB-IoT专栏—实战篇1:项目简介)

基于NB-IoT技术的城市道路智慧路灯监控系统,在每个照明节点上安装一个集成了NB-IoT模组的单灯控制器,单灯控制器再经运营商的网络,与路灯控制平台实现双向通信,路灯控制平台直接对每个灯进行控制,包括开关灯控制、光照检测、自动调节明暗、电耗分析等操作。

不脱发的程序猿 5万+

【YOLO系列】YOLOv8详解:模型结构、损失函数、训练方法及代码实现

YOLOv8是Ultralytics团队2023年推出的高效目标检测框架,在速度与精度平衡、多任务支持和易用性方面实现突破。模型采用改进的CSPDarknet主干网络、C2f模块和SPPF加速结构,结合PAN-FPN特征融合和解耦检测头设计,支持目标检测、实例分割和关键点检测任务。创新性地使用CIoU定位损失、Focal Loss置信度损失和动态样本分配策略,显著提升检测性能。实验表明,YOLOv8较前代模型mAP提升5-10%,在TensorRT加速下可达1000FPS,提供5种尺寸灵活选择,成为实时目标

一碗白开水一 2779

一路踩坑构建Dubbo源码

dubbo构建源码环境构建快速启动总结 源码环境 随着溪源目前对技术栈的求知欲,也开始入手Dubbo源码啦!!! 构建源码第一步: 必备开发环境:Java 1.5 以上的版本;Maven 2.2.1 或者以上的版本; 官网下载源代码 官网构建文档学习一下; 构建 上面part介绍了dubbo源码环境,下面溪源将一步步踩坑构建源码。虽然上面附属了官方文档连接,此处溪源再重复说一下下载步骤: git下载 命令git clone https://github.com/apache/dubbo.git; mav

增量星球 1万+

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

Dubbo面试题及答案整理,Dubbo面试题大全带答案(2021最新版)

本套Dubbo面试题分了6套,都有Dubbo面试题汇总带答案 Dubbo面试题及答案【最新版】Dubbo高级面试题大全(2021版),发现网上很多Dubbo面试题及答案整理都没有答案,所以花了很长时间搜集,本套Dubbo面试题大全,Dubbo面试题大汇总,有大量经典的Dubbo面试题以及答案,包含Dubbo语言常见面试题、Dubbo工程师高级面试题及一些大厂Dubbo开发面试宝典,面试经验技巧等,应届生,实习生,企业工作过的,都可参考学习! 这套Dubbo面试题汇总大全,希望对大家有帮助哈~ 博主已将

架构师专栏 2803

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

dubbo 注册公网_技术分享——一路踩坑构建Dubbo源码

写在前面:2020年面试必备的Java后端进阶面试题总结了一份复习指南在Github上,内容详细,图文并茂,有需要学习的朋友可以Star一下!GitHub地址:abel-max/Java-Study-Note源码环境随着目前对技术栈的求知欲,也开始入手Dubbo源码啦!!!构建源码第一步:必备开发环境:Java 1.5 以上的版本;Maven 2.2.1 或者以上的版本;官网下载源代码官网构建文档...

weixin_39598069的博客 121

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

dubbo 单元测试_技术分享——一路踩坑构建Dubbo源码

源码环境随着目前对技术栈的求知欲,也开始入手Dubbo源码啦!!!构建源码第一步:必备开发环境:Java 1.5 以上的版本;Maven 2.2.1 或者以上的版本;官网下载源代码官网构建文档学习一下;构建上面part介绍了dubbo源码环境,下面将一步步踩坑构建源码。虽然上面附属了官方文档连接,此处再重复说一下下载步骤:git下载命令git clone https://github.com/ap...

weixin_30649185的博客 192

关于dubbo服务启动后自动停止的解决办法

周末两天在家准备把dubbo相关知识系统过一下,顺便写个demo以备以后不时之需,什么时候写demo都是先在网上找一下有没有别人总结好的,有的话直接拿过来修改修改就ok了。通过《一个简单的dubbo服务》 这篇文章在github上找到了对应的demo示例,直接clone下来对照着文章看了一遍没问题尝试着启动dubbo服务。 启动provider: C:\Program Files\Ja...

gangsijay888的博客 3275

Dubbo环境搭建 管理控制台

1.下载incubator-dubbo-ops-master.zip incubator-dubbo-ops-master.zip下载地址 2.将文件解压到当前文件夹

qq_46198929的博客 2006

Dubbo

这些面试题覆盖了 Dubbo 的关键概念、配置、工作原理和性能优化等多个方面。准备这些问题可以帮助应对关于 Dubbo 的面试,并展现对分布式系统架构的理解。在实际面试中,结合自己的经验和项目案例进行解答,能够更加深入和具体地展示你的能力。:::tipsDubbo是一个开源的高性能 Java RPC(Remote Procedure Call)框架,由阿里巴巴在 2009 年开发,并于 2011 年开源。它主要用于构建微服务架构,简化分布式服务之间的通信和管理。

Jak的博客 1274

2021-08-28

你应该知道的RPC原理   在学校期间大家都写过不少程序,比如写个hello world服务类,然后本地调用下,如下所示。这些程序的特点是服务消费方和服务提供方是本地调用关系。   而一旦踏入公司尤其是大型互联网公司就会发现,公司的系统都由成千上万大大小小的服务组成,各服务部署在不同的机器上,由不同的团队负责。这时就会遇到两个问题:1)要搭建一个新服务,免不了需要依赖他人的服务,而现在他人的服务都在远端,怎么调用?2)其它团队要使用我们的新服务,我们的服务该怎么发布以便他人调用?下文将对这两个问题展开探

wr_java的博客 9109

Dubbo依赖

必须依赖 JDK 1.6+ 缺省依赖(即系统默认状态) 通过 mvn dependency:tree > dep.log 命令分析,Dubbo 缺省依赖以下三方库: [INFO] +- com.alibaba:dubbo:jar:2.5.9-SNAPSHOT:compile [INFO] | +- org.springframework:spring-context:jar:4.3...

weixin_34319999的博客 1513

dubbo项目启动过程报错

场景:     dubbo项目在自己的电脑上启动没有问题,在服务器启动就报错。 报错信息如下: [WARN] [main] [2019-08-26 20:44:04,689] getLocalAddress0(193) | [DUBBO] Failed to retrieving ip address, host-172-17-33-172: host-172-17-33-172: Name ...

weixin_43451374的博客 1136
上一篇: Dubbo原理学习(二)
下一篇: 20210907生产问题记录
CodersCoder
博客等级 码龄10年 90粉丝 258原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值