Arthas 定位 Dubbo 手动注册 Eureka 异常

做者 | java_keith
来源|阿里巴巴云原生公众号java

好久没有写技术分享博客,由于发现一个好的工具确实有点忍不住分享一下,毕竟独乐乐不如众乐乐。> 这里须要说的主角就是 Artahs。> Arthas 使用文档很详细,我这里主要记录一下使用 Arthas 的一点总结。

使用背景

在一个大的团队里面,会由于不少历史缘由或客观因素致使技术栈并不统一,咱们就遇到这么一个问题。老项目是使用 Dubbo 框架的 Dubbo 协议进行服务交互,有新的项目是使用 Springcloud 体系的 Feignclient 框架的 Http 协议进行交互。那么就须要解决两个问题。spring

  • 问题 1 是 Dubbo 服务须要支持 Dubbo 协议又须要支撑 Http 协议。
  • 问题 2 是 Feignclient 框架可以无损调用 Dubbo 服务的 Http 协议(无损指的是 Dubbo 对 Feignclient 调用方可以作到服务动态感知,负载均衡不须要作二次开发)。

解决思路

有了以上的目标,咱们就须要想办法解决问题。解决第一个问题却是比较容易,Dubbo 自己就提供的 Http 协议暴漏。也就是将老工程 Dubbo 升级、配置两种协议问题一就这么解决了。apache

可是针对问题 2,咱们能够罗列一下遇到的问题。Dubbo 注册使用的是 zk 注册中心,Springcloud 工程使用 Eureka 注册中心。这里顺带也要赞美一下 Feignclient 框架,Feignclient 接入服务的门槛很低,这样兼容了不少语言、环境等带来的差别,也就是说只要是 http 协议的接口 Feignclient 就能调用。到这里实际上经过 Feignclient 直接调用 Dubbo 服务暴漏的 Http 协议接口是可以走的通,只不过无法作到负载均衡,失败转移等能力。说了这么多总结一下吧。负载均衡

  • 如今经过 Feignclient 直连 Dubbo 框架工程的 Http 协议可以正常执行。
  • 分布式环境下须要解决直连的弊端(没法负载均衡,没法失败转移,没法动态扩容等等) 好在经过分析了 Eureka 源码之后打开了另外一个大门,Eureka 其实是独立的组件,并且提供手动注册服务的能力(即便没有修改源码就有了)。如今解决思路就是在 Dubbo 工程里面引入 Eureka 组件,手动将服务注册到 Eureak 以便 Feignclient 可以无损调用。

主角(Arthas)登场

为了将 Dubbo 框架工程提供注册 Eureka 的能力,而且可以作到优雅上线和下线。咱们主要是借助了 Dubbo 的 Spi 扩展能力中的 Container 扩展。代码以下:框架

class EurekaDubboContainer implements Container {...}

有了以上代码还须要作一件重要的事情,就是声明 Container 的全路径。META-INF/dubbo/org.apache.dubbo.container.Container:xxx=com.xxx.XxxContainer,当时咱们配置这里的代码 spring=com.xxx.EurekaDubboContainer,当全部准备好了之后咱们启动工程,发现无异常输出,进程完美。可是 Deignclient 怎么也没法调用。最主要是启动过程当中没有任何异常输出,通过大量论证后,就在快绝望的时候,我发现了 Arthas,Arthas 能够查看内存中对象属性值以及执行对象的方法,我欣喜若狂。经过以前对 Dubbo 注册过程源码分析:分布式

com.alibaba.dubbo.common.extension.ExtensionLoader#loadFile
} catch (Throwable t) {
  IllegalStateException e = new IllegalStateException("Failed to load extension class(interface: " + type + ", class line: " + line + ") in " + url + ", cause: " + t.getMessage(), t);
  exceptions.put(line, e);
}

在 Dubbo 启动过程,会从 Jar 包中扫描配置的 META-INF 中配置的 Container,在加载的时候这个异常是直接存放在了 Loader 类的域中,猜想多是为了解决 Container 隔离因此异常并无抛出。当前主要目标仍是分析为啥我定义的扩展容易没有启动。部署 Arthas 之后我开始了分析之路。工具

  • sc -d *.EurekaDubboContainer 发现类已经正常加载,说明有被 Load 加载。
  • jad *.EurekaDubboContainer 发现加载的类代码也是在正常(排除包不对的可能)。
  • ognl '#loader=@com.alibaba.dubbo.container.Main@loader,#loader.cachedInstances' 这里发现了问题,若是是正常被 Load 的 Container 会被存在到 ExtensionLoader 的 CachedInstances 域中(默认的 Spring,log4j存在),可是我自定义的 Container 居然没找到。
  • ognl '#loader=@com.alibaba.dubbo.container.Main@loader,#loader.exceptions' 这里发现了之全部没有加载成功的缘由,在 Exceptions 中有声明。

0CA166B6-DF7E-41eb-B6D2-014A00AEABDB.png

经过以上分析,问题很是明显了,在 META-INF 中指定的 Key 重复了。仍是没深刻理解 Dubbo 中的 Spi 文档上的‘xxx’是自定义的意思。到这里修改 Key 之后一切按照计划执行。源码分析

结束

经过一波操做,咱们发现从技术角度出发,其实没有解决不了的问题,只是须要多想想,多想一想办法总能够找到的。包括使用 Arthas 上 Ognl 如何查看 Load 实例中的非静态域,直接获取是没法获取的,由于没有存在在 Arthas 上下文中,因此变通一下思路:经过 Main 的静态域获取实例,再经过实例变量获取非静态域的值。技术没有终止,愿你我一同进步。为开源贡献微薄的力量。若对细节有兴趣的朋友,可留言交流。url

Arthas 有奖征文正在进行中!

为了让更多开发者开始用上 Arthas 这个 Java 诊断神器,今年 3 月 26 日,Arthas 社区联合 JetBrains 推出 Arthas 有奖征文活动聊聊这些年你和 Arthas 之间的那些事儿。活动已进行至第七期,点击连接便可参与:http://alibabacloud.mikecrm.com/9khcRrs,欢迎你们踊跃投稿,参与即有可能获奖!spa

相关文章
相关标签/搜索