dubbo源码怎么看

Posted shysheng

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了dubbo源码怎么看相关的知识,希望对你有一定的参考价值。

从去年年中开始,断断续续看了一些dubbo源码。刚开始方式很简单,就是在网上找一些博主的文章跟着一起学,应该说看得很痛苦,说很多东西跟看天书一样也不为过。为什么会有这种感觉?现在回想起来,最大的原因可能是当时对dubbo并没有一个系统的了解,完全不知从何入手,而且网上的很多文章往往只是讲了其中一个点,我并不知道这个东西有什么用,为什么要这么写,以及各模块之间到底是个什么关系。

现在回过头来看,如果当时能有一份类似dubbo学习进阶路线图的资料,也许这源码看起来会轻松很多。

如果现在让我从头开始,我一定不会一开始就闷头扎到源码中去。首先我会从dubbo框架设计入手,从整体设计上对它有个印象。

然后具体到源码部分,一定会从SPI入手,了解自适应扩展机制,接下来会看服务导出和服务引用,到这里,基本上hello world的demo你就知道大概是怎么跑起来的了。

当然知其然还要知其所以然,想更深入地了解其运行原理,还必须要了解其协议是怎么设计的,通信过程中的编解码、序列化都做了哪些工作。至此,简单的服务调用过程,你就有了基本的概念。

dubbo源码怎么看

扩展到集群的场景,自然而然,你需要去了解多个生产者如何组成服务目录,消费者如何通过路由和负载均衡来选择生产者,以及相应的集群容错机制。

dubbo源码怎么看

到这里就结束了吗?当然没有。在最新的2.7版本中,dubbo已经形成了三大中心的管理机制,即2.7之前就有的注册中心,以及在2.7中新增的元数据中心和配置中心,在dubbo进阶之路上,这三个中心你当然也需要有所了解。

除此之外,dubbo也一直在演进,在上周参加的dubbo社区开发者大会上,小马哥说将来可能会去掉元数据中心和配置中心(如果我没听错的话),以及在现在很火的云原生方面,dubbo将何去何从?如果你对dubbo感兴趣,这些都是你可以关注的一些话题。

这里给出一张自己简单整理的dubbo学习路径脑图吧。


当然,随着去年dubbo进入Apache孵化项目,官方文档上已经有了很多很有价值的资料,里面有很多dubbo commiter以及PMC成员的技术博客,甚至还有dubbo核心模块的源码解析(http://dubbo.apache.org/zh-cn/index.html),我相信这些资料可以帮助初学者更快地入门dubbo框架。

另外,一直以来,我略感困惑的一点是,作为一款优秀的开源框架,为什么市面上一直缺少一本系统介绍dubbo、适合初学者入门和进阶的图书?那么现在,这个困惑可以消除了。因为dubbo PMC成员诣极刚刚出版了这样一本书,我上面提到的一切,这本书里基本都作了详细深入的讲解,干货满满。回想起来,在上一家公司,还跟本书作者诣极大牛有过几次交流,那时候只知道他是dubbo的commiter,如今已是dubbo PMC成员了,还出了这么一本好书,果然,比我优秀的人比我还努力。

题外话

坊间一直有一种说法,说dubbo的代码写得不好,跟Spring等优秀的开源框架有不少差距。官方应该也看到这一点了,所以在dubbo重新开始维护之后,除了新特性的开发,官方也对已有功能的代码作了大量的重构和优化。这里以生成自适应扩展类代码的代码来略窥一二。

重构之前的版本是这样的,5+个for循环,15+个if分支,嵌套深度 > 5,单个函数超过300行。

 
   
   
 
  1. private String createAdaptiveExtensionClassCode() {

  2. ...

  3. for (Method method : methods) {

  4. ...

  5. if (adaptiveAnnotation == null) {

  6. ...

  7. } else {

  8. ...

  9. if (urlTypeIndex != -1) {

  10. ...

  11. }

  12. else {

  13. ...

  14. if (attribMethod == null) {

  15. ...

  16. }

  17. ...

  18. for (int i = value.length - 1; i >= 0; --i) {

  19. if (i == value.length - 1) {

  20. if (null != defaultExtName) {

  21. if (!"protocol".equals(value[i])) {

  22. if (hasInvocation) {

  23. ...

  24. } else {

  25. ...

  26. }

  27. } else {

  28. ...

  29. }

  30. } else {

  31. if (!"protocol".equals(value[i])) {

  32. if (hasInvocation) {

  33. ...

  34. } else {

  35. ...

  36. }

  37. } else {

  38. ...

  39. }

  40. }

  41. } else {

  42. if (!"protocol".equals(value[i])) {

  43. if (hasInvocation) {

  44. ...

  45. } else {

  46. ...

  47. }

  48. } else {

  49. ...

  50. }

  51. }

  52. }

  53. ...

  54. for (int i = 0; i < pts.length; i++) {

  55. if (i != 0) {

  56. ...

  57. }

  58. ...

  59. }

  60. ...

  61. }

  62. ...

  63. for (int i = 0; i < pts.length; i++) {

  64. if (i > 0) {

  65. ...

  66. }

  67. ...

  68. }

  69. if (ets.length > 0) {

  70. ...

  71. for (int i = 0; i < ets.length; i++) {

  72. if (i > 0) {

  73. ...

  74. }

  75. ...

  76. }

  77. }

  78. ...

  79. }

  80. ...

  81. }

老实说,当初看到这段代码的时候,我也是一眼蒙圈,不敢相信这真的是dubbo的代码,可以说很好地诠释了如何写出让同事不好维护的代码这一反模式。

好在今年年初,这段代码终于被重构了,重构之后的版本是这样的:

 
   
   
 
  1. public String generate() {

  2. // no need to generate adaptive class since there's no adaptive method found.

  3. if (!hasAdaptiveMethod()) {

  4. throw new IllegalStateException("No adaptive method exist on extension " + type.getName() + ", refuse to create the adaptive class!");

  5. }


  6. StringBuilder code = new StringBuilder();

  7. code.append(generatePackageInfo());

  8. code.append(generateImports());

  9. code.append(generateClassDeclaration());


  10. Method[] methods = type.getMethods();

  11. for (Method method : methods) {

  12. code.append(generateMethod(method));

  13. }

  14. code.append("}");


  15. if (logger.isDebugEnabled()) {

  16. logger.debug(code.toString());

  17. }

  18. return code.toString();

  19. }



  20. private String generateMethod(Method method) {

  21. String methodReturnType = method.getReturnType().getCanonicalName();

  22. String methodName = method.getName();

  23. String methodContent = generateMethodContent(method);

  24. String methodArgs = generateMethodArguments(method);

  25. String methodThrows = generateMethodThrows(method);

  26. return String.format(CODE_METHOD_DECLARATION, methodReturnType, methodName, methodArgs, methodThrows, methodContent);

  27. }

整个过程被抽到了一个单独的类中,并按照类文件的格式被拆分成了十几个短小的方法,基本上每个方法不超过20行,这样的代码层次分明,一目了然,基本上从方法名上你就能知道他要干什么。看了下提交记录,这个重构是在今年2.11(大年初七)提交的,看来作者过年期间也没闲着

以上是关于dubbo源码怎么看的主要内容,如果未能解决你的问题,请参考以下文章

临摹源码 | 一比一手写Dubbo源码中的SPI(内附git地址)

dubbo源码阅读-阅读前的准备

Dubbo源码阅读系列之远程服务调用(上)

源码实战 | 从线程池理论聊聊为什么要看源码

dubbo面试题!会这些,说明你真正看懂了dubbo源码

dubbo面试题,会这些说明你真正看懂了dubbo源码