千家信息网

面试官问我,使用Dubbo有没有遇到一些坑?我笑了。

发表于:2026-11-02 作者:千家信息网编辑
千家信息网最后更新 2026年11月02日,前言17年的时候,因为一时冲动没把持住(当然最近也有粉丝叫我再冲动一把再更新一波),结合面试题写了一个系列的Dubbo源码解析.目前公众号大部分粉丝都是之前的粉丝,这里不过多介绍.根据我的面试经验而言
千家信息网最后更新 2026年11月02日面试官问我,使用Dubbo有没有遇到一些坑?我笑了。

前言

17年的时候,因为一时冲动没把持住(当然最近也有粉丝叫我再冲动一把再更新一波),结合面试题写了一个系列的Dubbo源码解析.目前公众号大部分粉丝都是之前的粉丝,这里不过多介绍.

根据我的面试经验而言,能在简历上写上原理、源码等关键词的,是非常具备核心竞争力的.上周和一个公众号粉丝交流面试情况如下

面试的时候,把源码一波分析,令面试官虎躯一震!在一阵前戏过后,以为接下来无非就是身体的一顿抽搐一切变得索然无味,不料面试官来了句令剧情发生了反转

"你对Dubbo源码这么熟悉,那请问你使用的时候,有没有遇到什么坑"

我擦,毫无准备的他,菊花顿时一紧!此时就面临唬住了50K,唬不住就只能5K的局面,慌了!

论如何反杀

相信大家面试都遇到过类似问题,因为源码解析网上很多,很多人"考前突击"一下,但是遇到喜欢问细节的面试官,终究难逃法眼,无处遁形.遇到这个问题,我们如何反杀一波?那么我就从一次聊天记录说起,毕竟只有关注肥朝公众号,拥有真实场景的源码实战(非常重要),遇到这类问题,才不至于出现猛虎落泪的情形

真实场景描述

那么我们把业务相关去掉,抽取一个最简模型.我们在公司,一般都会有自己的自定义异常,然后这个自定义异常一般放在common.jar给其他模块依赖,比如我这里定义一个HelloException

1public class HelloException extends RuntimeException {23    public HelloException() {4    }56    public HelloException(String message) {7        super(message);8    }910}

然后我们写一个最简单的Dubbo的demo,如下

interface

1public interface DemoService {23    String sayHello(String name);45}

provider

1public class DemoServiceImpl implements DemoService {23    public String sayHello(String name) {4        throw new HelloException("公众号:肥朝");5    }67}

consumer

1public class DemoAction {23    private DemoService demoService;45    public void setDemoService(DemoService demoService) {6        this.demoService = demoService;7    }89    public void start() throws Exception {10        try {11            String hello = demoService.sayHello("公众号:肥朝");12        } catch (HelloException helloException) {13            System.out.println("这里捕获helloException异常");14        }15    }1617}

按照聊天记录的描述,此时consumer调用provider,provider抛出HelloException.但是consumer捕获到的,却不是HelloException.

那么我们运行看看

果然如该同事所言.为什么会这样呢?之前没看过肥朝Dubbo源码解析系列的同学这种时候往往采用最低效的解决办法,把异常栈往微信群一丢,各种求助.但是往往毫无收获,然后感叹社会为何如此冷漠!

但是相信公众号的老粉丝们早已掌握阅读源码的技能,和肥朝一样坐怀不乱,九浅一深直入源码.出现异常我们首先看一下异常栈

除非撸多了看不清(建议戒撸),否则这行异常和肥朝一样,就像漆黑中的萤火虫一样,那么鲜明,那么出众

1com.alibaba.dubbo.rpc.filter.ExceptionFilter.invoke(ExceptionFilter.java:108)

那么我们一探究竟

1    public Result invoke(Invoker invoker, Invocation invocation) throws RpcException {2        try {3            Result result = invoker.invoke(invocation);4            if (result.hasException() && GenericService.class != invoker.getInterface()) {5                try {6                    Throwable exception = result.getException();78                    // 如果是checked异常,直接抛出9                    if (! (exception instanceof RuntimeException) && (exception instanceof Exception)) {10                        return result;11                    }12                    // 在方法签名上有声明,直接抛出13                    try {14                        Method method = invoker.getInterface().getMethod(invocation.getMethodName(), invocation.getParameterTypes());15                        Class[] exceptionClassses = method.getExceptionTypes();16                        for (Class exceptionClass : exceptionClassses) {17                            if (exception.getClass().equals(exceptionClass)) {18                                return result;19                            }20                        }21                    } catch (NoSuchMethodException e) {22                        return result;23                    }2425                    // 未在方法签名上定义的异常,在服务器端打印ERROR日志26                    logger.error("Got unchecked and undeclared exception which called by " + RpcContext.getContext().getRemoteHost()27                            + ". service: " + invoker.getInterface().getName() + ", method: " + invocation.getMethodName()28                            + ", exception: " + exception.getClass().getName() + ": " + exception.getMessage(), exception);2930                    // 异常类和接口类在同一jar包里,直接抛出31                    String serviceFile = ReflectUtils.getCodeBase(invoker.getInterface());32                    String exceptionFile = ReflectUtils.getCodeBase(exception.getClass());33                    if (serviceFile == null || exceptionFile == null || serviceFile.equals(exceptionFile)){34                        return result;35                    }36                    // 是JDK自带的异常,直接抛出37                    String className = exception.getClass().getName();38                    if (className.startsWith("java.") || className.startsWith("javax.")) {39                        return result;40                    }41                    // 是Dubbo本身的异常,直接抛出42                    if (exception instanceof RpcException) {43                        return result;44                    }4546                    // 否则,包装成RuntimeException抛给客户端47                    return new RpcResult(new RuntimeException(StringUtils.toString(exception)));48                } catch (Throwable e) {49                    logger.warn("Fail to ExceptionFilter when called by " + RpcContext.getContext().getRemoteHost()50                            + ". service: " + invoker.getInterface().getName() + ", method: " + invocation.getMethodName()51                            + ", exception: " + e.getClass().getName() + ": " + e.getMessage(), e);52                    return result;53                }54            }55            return result;56        } catch (RuntimeException e) {57            logger.error("Got unchecked and undeclared exception which called by " + RpcContext.getContext().getRemoteHost()58                    + ". service: " + invoker.getInterface().getName() + ", method: " + invocation.getMethodName()59                    + ", exception: " + e.getClass().getName() + ": " + e.getMessage(), e);60            throw e;61        }62    }
1.如果是checked异常,直接抛出.很明显,我们的HelloException是RuntimeException,不符合2.在方法签名上有声明,直接抛出.很明显,我们接口并未声明该异常,不符合3.异常类和接口类在同一jar包里,直接抛出.很明显,我们的异常类是在common.jar的,接口是在api.jar的,不符合4.是JDK自带的异常,直接抛出.很明显,这个HelloException是我们自定义的,不符合5.是Dubbo本身的异常(RpcException),直接抛出.很明显,这个HelloException是我们自定义的,和RpcException几乎没有半毛钱关系.6.否则,包装成RuntimeException抛给客户端.因为以上5点均不满足,所以该异常会被包装成RuntimeException异常抛出(重要)

这也就是为什么我们catchHelloException是catch不到的,因为他包装成RuntimeException了

Dubbo为什么这么设计

也许你看到这里会觉得这个判断好坑.Dubbo为什么要这么设计?我们看源码,最重要的是知道作者为什么这么设计,只有知道为什么这么设计才是经过了深度的思考,否则看时高潮,看后就忘.讲清楚为什么这么设计,也是大家关注肥朝公众号的一个重要原因.

其实Dubbo的这个考虑,是基于序列化来考虑的.你想想,如果provider抛出一个仅在provider自定义的一个异常,那么该异常到达consumer,明显是无法序列化的.所以你注意看Dubbo的判断.我们来看下他的判断

1.如果是checked异常,直接抛出.很明显,我们的HelloException是RuntimeException,不符合2.在方法签名上有声明,直接抛出.很明显,我们接口并未声明该异常,不符合3.异常类和接口类在同一jar包里,直接抛出.很明显,我们的异常类是在common.jar的,接口是在api.jar的,不符合4.是JDK自带的异常,直接抛出.很明显,这个HelloException是我们自定义的,不符合5.是Dubbo本身的异常(RpcException),直接抛出.很明显,这个HelloException是我们自定义的,和RpcException几乎没有半毛钱关系.6.否则,包装成RuntimeException抛给客户端.因为以上5点均不满足,所以该异常会被包装成RuntimeException异常抛出(重要)

如何解决

既然都知道了原理了,那么很好解决,我随便列举一下,比如从规范上要求业务方接口声明HelloException

写在最后

当然肥朝面试的时候,也曾经被问过类似问题,你用XXX有没有遇到过什么坑.在一波操作猛如虎的分析下,面试官说

"你真帅".

肥朝会心一笑

结果他却说

"你笑起来更帅"!

免费Java资料领取,涵盖了Java、Redis、MongoDB、MySQL、Zookeeper、Spring Cloud、Dubbo/Kafka、Hadoop、Hbase、Flink等高并发分布式、大数据、机器学习等技术。 传送门: https://jq.qq.com/?_wv=1027&k=5F79bMq

明显 源码 接口 公众 重要 时候 粉丝 设计 方法 是在 问题 一波 包装 客户 客户端 冲动 业务 原理 只有 场景 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 互联网科技有限公司 金诺互联网科技 互联网公司 科技公司 互联网科技集团 杭州互联网科技公司 九亚互联网科技 易通互联网络科技有限公司 互联网金融 科技创新 互联网高科技股票 居家互联网科技有限公司 滨湖区互联网智能科技产品供应 成都仁贤领冠互联网科技有限公司 济南华为互联网科技产业总部基地 温州喔噻互联网科技有限公司 互联网企业和科技型企业 民营互联网公司国防科技 互联网科技实习生岗位 杭州披云加互联网科技有限公司 互联网科技机房 青岛易易互联网科技 美国互联网科技巨头监管 互联网科技排名 衡水科技产业互联网平台 银川新华互联网科技职业技术培训学校图片 金融科技与互联网金融相同和不同 西安小鹰速贷互联网科技有限公司 山东星卡互联网科技有限公司官网 互联网科技实习生岗位 互联网金融金融科技 山东亿川互联网科技有限责任公司
0