17年的时候,因为一时冲动没把持住(当然最近也有粉丝叫我再冲动一把再更新一波),结合面试题写了一个系列的Dubbo源码解析.目前公众号大部分粉丝都是之前的粉丝,这里不过多介绍.
  
  根据我的面试经验而言,能在简历上写上原理、源码等关键词的,是非常具备核心竞争力的.上周和一个公众号粉丝交流面试情况如下
  
  面试的时候,把源码一波分析,令面试官虎躯一震!在一阵前戏过后,以为接下来无非就是身体的一顿抽搐一切变得索然无味,不料面试官来了句令剧情发生了反转
  
  "你对Dubbo源码这么熟悉,那请问你使用的时候,有没有遇到什么坑"
  
  我擦,毫无准备的他,菊花顿时一紧!此时就面临唬住了50K,唬不住就只能5K的局面,慌了!
  
  论如何反杀
  
  相信大家面试都遇到过类似问题,因为源码解析网上很多,很多人"考前突击"一下,但是遇到喜欢问细节的面试官,终究难逃法眼,无处遁形.遇到这个问题,我们如何反杀一波?那么我就从一次聊天记录说起,毕竟只有关注肥朝公众号,拥有真实场景的源码实战(非常重要),遇到这类问题,才不至于出现猛虎落泪的情形
  
  真实场景描述
  
  那么我们把业务相关去掉,抽取一个最简模型.我们在公司,一般都会有自己的自定义异常,然后这个自定义异常一般放在common.jar给其他模块依赖,比如我这里定义一个HelloException
  
  1public class HelloException extends RuntimeException {
  
  2
  
  3 public HelloException() {
  
  4 }
  
  5
  
  6 public HelloException(String message) {
  
  7 super(message);
  
  8 }
  
  9
  
  10}
  
  然后我们写一个最简单的Dubbo的demo,如下
  
  interface
  
  1public interface DemoService {
  
  2
  
  3 String sayHello(String name);
  
  4
  
  5}
  
  provider
  
  1public class DemoServiceImpl implements DemoService {
  
  2
  
  3 public String sayHello(String name) {
  
  4 throw new HelloException("公众号:肥朝");
  
  5 }
  
  6
  
  7}
  
  consumer
  
  1public class DemoAction {
  
  2
  
  3 private DemoService demoService;
  
  4
  
  5 public void setDemoService(DemoService demoService) {
  
  6 this.demoService = demoService;
  
  7 }
  
  8
  
  9 public void start() throws Exception {
  
  10 try {
  
  11 String hello = demoService.sayHello("公众号:肥朝");
  
  12 } catch (HelloException helloException) {
  
  13 System.out.println("这里捕获helloException异常");
  
  14 }
  
  15 }
  
  16
  
  17}
  
  按照聊天记录的描述,此时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 www.taoyang2vip.com = result.getException();
  
  7
  
  8 // 如果是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(www.michenggw.com ).equals(exceptionClass)) {
  
  18 return result;
  
  19 }
  
  20 }
  
  21 } catch (NoSuchMethodException e) {
  
  22 return result;
  
  23 }
  
  24
  
  25 // 未在方法签名上定义的异常,在服务器端打印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(www.xinghenyule.com).getName() + ": " + exception.getMessage(), exception);
  
  29
  
  30 // 异常类和接口类在同一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(www.jiahuayulpt.com).getName();
  
  38 if (className.startsWith("java.") || className.startsWith("javax.")) {
  
  39 return result;
  
  40 }
  
  41 // 是Dubbo本身的异常,直接抛出
  
  42 if (exception www.thd178.com/ instanceof RpcException) {
  
  43 return result;
  
  44 }
  
  45
  
  46 // 否则,包装成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(www.yongshi123.cn) + ", 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: www.tiaotiaoylzc.com" + invoker.getInterface().getName() + ", method: " + invocation.getMethodName()
  
  59 + ", exception: www.myzx1.com " + e.getClass(www.dfgjpt.com).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://mp.weixin.qq.com/s/JzddfH-7yNudmkjT0IRL8Q
  
  Memory ordering obeys causality (memory ordering respects transitive visibility).
  
  Any two stores are seen in a consistent order www.078881.cn by processors other than those performing the stores
  
  Locked instructions have a total order
  
  examples
  
  Neither Loads Nor Stores Are Reordered with Like Operations
  
  Stores Are Not Reordered With www.yongxin7.com Earlier Loads
  
  Loads May Be Reordered with Earlier Stores to Different Locations
  
  Loads Are not Reordered with Older Stores to the Same Location

面试官问我,使用Dubbo有没有遇到一些坑?我笑了的更多相关文章

  1. 面试官问我,Redis分布式锁如何续期?懵了。

    前言 上一篇[面试官问我,使用Dubbo有没有遇到一些坑?我笑了.]之后,又有一位粉丝和我说在面试过程中被虐了.鉴于这位粉丝是之前肥朝的粉丝,而且周一又要开启新一轮的面试,为了回馈他长期以来的支持,所 ...

  2. 每日一问:面试结束时面试官问"你有什么问题需要问我呢",该如何回答?

    面试结束时面试官问"你有什么问题需要问我呢",该如何回答?

  3. 面试官问,说一个你在工作非常有价值的bug

    如果你去参考面试,做足了准备,面对面试官员从容不迫,吐沫横飞的大谈自己的工作经历.突然,面试官横插一句:说一个你在工作非常有价值的bug.顿时,整个空气都仿佛都凝固了!“What?”... 我想没几个 ...

  4. 面试官问:JS的this指向

    前言 面试官出很多考题,基本都会变着方式来考察this指向,看候选人对JS基础知识是否扎实.读者可以先拉到底部看总结,再谷歌(或各技术平台)搜索几篇类似文章,看笔者写的文章和别人有什么不同(欢迎在评论 ...

  5. 当面试官问你sql优化的时候。。。

    当面试官问你有关sql优化的问题时,直接拿笔写给他: 8-select 9-distinct<column_list> 1-from left_table 3-<join_type& ...

  6. 面试官问你JS基本类型时他想知道什么?

    面试的时候我们经常会被问答js的数据类型.大部分情况我们会这样回答包括:1.基本类型(值类型或者原始类型): Number.Boolean.String.NULL.Undefined以及ES6的Sym ...

  7. 面试官问线程安全的List,看完再也不怕了!

    最近在Java技术栈知识星球里面有球友问到了线程安全的 List: 扫码查看答案或加入知识星球 栈长在之前的文章<出场率比较高的一道多线程安全面试题>里面讲过 ArrayList 的不安全 ...

  8. 美团面试官问我一个字符的String.length()是多少,我说是1,面试官说你回去好好学一下吧

    本文首发于微信公众号:程序员乔戈里 public class testT { public static void main(String [] args){ String A = "hi你 ...

  9. 大厂面试官问你META-INF/spring.factories要怎么实现自动扫描、自动装配?

    大厂面试官问你META-INF/spring.factories要怎么实现自动扫描.自动装配?   很多程序员想面试进互联网大厂,但是也有很多人不知道进入大厂需要具备哪些条件,以及面试官会问哪些问题, ...

  10. 当阿里面试官问我:Java创建线程有几种方式?我就知道问题没那么简单

    这是最新的大厂面试系列,还原真实场景,提炼出知识点分享给大家. 点赞再看,养成习惯~ 微信搜索[武哥聊编程],关注这个 Java 菜鸟. 昨天有个小伙伴去阿里面试实习生岗位,面试官问他了一个老生常谈的 ...

随机推荐

  1. Ionic2 播放mp3功能实现

    在开发app的过程中有需要播放mp3的功能,一直想实现,但苦于具体的困难一直未能实现,经过一段时间的资料查询和测试,最终摸索出来,现记录如下: 1.最重要的是安装第三方插件ionic-audio,开源 ...

  2. Luogu P1477 [NOI2008]假面舞会

    一道非常神奇的图论题解法无比新奇清新 我们首先把图分成三种情况: 有环的,此时答案一定是环长的因数(否则不能满足题意) 存在入度大于1的DAG图的 一棵树/一条链 很容易发现,最后一种情况想怎么取就怎 ...

  3. OpenBLAS简介及在Windows7 VS2013上源码的编译过程

    OpenBLAS(Open Basic Linear Algebra Subprograms)是开源的基本线性代数子程序库,是一个优化的高性能多核BLAS库,主要包括矩阵与矩阵.矩阵与向量.向量与向量 ...

  4. C# 获取文件MD5值的方法

    可用于对比文件是否相同 /// <summary> /// 获取文件MD5值 /// </summary> /// <param name="fileName& ...

  5. (7)学习笔记 ) ASP.NET CORE微服务 Micro-Service ---- 利用Polly+AOP+依赖注入封装的降级框架

    创建简单的熔断降级框架 要达到的目标是: 参与降级的方法参数要一样,当HelloAsync执行出错的时候执行HelloFallBackAsync方法. public class Person { [H ...

  6. 解决 webpack-dev-server 不能自动刷新的问题

    原文发表于我的技术博客 此文主要帮助大家解决 webpack-dev-server 启动后修改源文件浏览器不能自动刷新的问题. 原文发表于我的技术博客 1. webpack 不能热加载的问题 主要的问 ...

  7. Webpack 2 视频教程 005 - Webpack 编译输出日志

    原文发表于我的技术博客 这是我免费发布的高质量超清「Webpack 2 视频教程」. Webpack 作为目前前端开发必备的框架,Webpack 发布了 2.0 版本,此视频就是基于 2.0 的版本讲 ...

  8. NumsCount (java)

    package com.home.test;       import java.util.Arrays;       public class NumsCount {       public vo ...

  9. SPRINT四则运算(第二天)

    1.小组成员: 李豌湄:master 江丹仪:产品负责人 2.现状: a.已经下载APP分析他们的界面.优缺点和闪光点  b.已改进代码添加功能 3.任务认领: 完成任务的第一个模块: a.下载五个类 ...

  10. CentOS(6.8)7 安装 Mysql 5.7

    https://blog.csdn.net/zyw_java/article/details/70949596 https://blog.csdn.net/yzl11/article/details/ ...