2

Arthas 定位 Dubbo 手动注册 Eureka 异常

 3 years ago
source link: http://dockone.io/article/1448839
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

作者 | java_keith

来源| 阿里巴巴云原生公众号

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

使用背景

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

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

解决思路

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

但是针对问题 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 '#[email protected]@loader,#loader.cachedInstances' 这里发现了问题,如果是正常被 Load 的 Container 会被存在到 ExtensionLoader 的 CachedInstances 域中(默认的 Spring,log4j存在),但是我自定义的 Container 竟然没找到。
  • ognl '#[email protected]@loader,#loader.exceptions' 这里发现了之所有没有加载成功的原因,在 Exceptions 中有声明。
ZJ7BZ3B.png!mobile

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

结束

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

Arthas 有奖征文正在进行中!

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


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK