Dubbo自适应拓展学习笔记

本文主要探讨Dubbo的自适应拓展特性,通过提问方式引导读者思考如何实现该特性。作者聚焦于Dubbo的自适应扩展与SPI,解释了自适应拓展的动态性和灵活性。在实现过程中,讨论了动态代理的使用,特别是Javassist和jdk编译代码的步骤。此外,还简要介绍了Javassist库的作用和功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

关于阅读开源代码的一些想法

在编写本文前,其实已经写了一篇关于Dubbo 自适应拓展特性的草稿,但是通篇写下来,所做的也不过是copy-write的过程,这样的文章对于我来说,又有什么意义呢?
尽管我多次想编写一篇详尽有效的文档,试图如同大神一样去理清Dubbo源码的脉络,但是深入其间才发现力有所不逮。因此便重新把那篇文章给删了,推倒重来,将阅读人群从别人转向自己。
这样一来,就变得清晰简单的许多。我只需要问自己以下几个问题,便能得到我想要的东西:

  • 你最想了解的时Dubbo的哪个特性?
  • 基于这个特性如果让你来实现,你会怎么实现?遇到哪些问题?
  • 你无法解决的问题别人的解决思路是什么?
  • 里面最有价值的算法或者思路是什么?

只要能解决这些问题,那么对于我来说,就是大有收获,至于别人的收获,又与我何干?

我最想了解Dubbo的哪个特性?

Dubbo的特性很多,如果一股脑的写成一篇文章,那么势必陷入僵局。围绕Dubbo一系列的特性,本文只针对Dubbo的自适应扩展与SPI部分进行解析。

那么这里顺带一提Dubbo的自适应扩展是什么?
一般情况下,Dubbo都通过SPI进行拓展,但对于有些拓展,希望在拓展方法被调用时,才灵活地根据运行时参数进行加载对应的拓展。这时候我们就称之为自适应拓展,其实就是动态拓展。

这里直接拿官网的例子来进行理解:

public interface WheelMaker {
    Wheel makeWheel(URL url);
}

//WheelMaker 接口的自适应实现类如下:
public class AdaptiveWheelMaker implements WheelMaker {
    public Wheel makeWheel(URL url) {
        if (url == null) {
            throw new IllegalArgumentException("url == null");
        }
        
    	// 1.从 URL 中获取 WheelMaker 名称
        String wheelMakerName = url.getParameter("Wheel.maker");
        if (wheelMakerName == null) {
            throw new IllegalArgumentException("wheelMakerName == null");
        }
        
        // 2.通过 SPI 加载具体的 WheelMaker
        WheelMaker wheelMaker = ExtensionLoader
            .getExtensionLoader(WheelMaker.class).getExtension(wheelMakerName);
        
        // 3.调用目标方法
        return wheelMaker.makeWheel(URL url);
    }
}

从上面可以看出,实际的服务实现是通过URL远程传过来的参数来动态获取的,这也就是自适应拓展。区别于直接采用SPI进行拓展加载,采用这样的方式会更加灵活。

基于这个特性如果让你来实现,你会怎么实现?遇到哪些问题?

那么解决完我想要学习什么特性的问题,第二个问题,我们姑且先不要急着去看Dubbo的实现原理,我们可以闭着眼睛,想假如是我们自己去实现,我们会怎么实现,以及遇到哪些问题?

  • 1.采用什么方式去标记需要动态拓展的方法?
  • 2.由于框架的开发者是不应该去关注业务以及具体业务的实现,但是又一定程度的需要将调用拦截下来,做一定的路由引导,这时候就应该要有一层简单的代理。但是由于服务的多样性以及灵活性,只能采用动态代理的方式去实现包装。那么会采用什么技术去实现动态代理?
  • 假设我们已经选定了动态代理了,那么我们需要构建代理方法的相关代码,如何去构建一个完整的代理方法,分几部分,其中需要注意些什么?

当然我们并没有真正自己亲手去实现这个功能,我们不过是围绕这个特性或者这个问题,即如何动态地通过参数去适配到对应的实现方法去?(其实最low的方法就是if else),基于这个问题,我们展开了一系列的探讨。

ok,我们已经粗略地想了下这个实现过程了,乍一看,就两个点我们需要关注的:
(1)是否真的如我们所想采用了动态代理的方式?如果是,采用了哪些动态代理的技术?引申开来,当前有哪些具体的动态代理技术?他们的优缺点是什么?
(2)构建一个完整的代理方法的细节有哪些?

带着以下问题,我们开始去解剖代码。

你无法解决的问题别人的解决思路是什么?里面最有价值的算法或者思路是什么?

当然我们不可能一下子扎入到源码当中,源码是汪洋大海啊,我们得找一个路标,那就是Dubbo的官网源码导读了,它是怎么说明这个问题的解决方案的呢?

自适应拓展机制的实现逻辑比较复杂,首先 Dubbo 会为拓展接口生成具有代理功能的代码。然后通过 javassist 或 jdk 编译这段代码,得到 Class 类。最后再通过反射创建代理类

有了这个路标,我们就可以比较快捷地把握住源码的方向了。Dubbo本身提供了一系列丰富的Demo,我们可以通过已经有的Demo进行源码解读。
Demo见dubbo-common ExtensionLoader_Adaptive_Test测试类

 @Test
    public void test_getAdaptiveExtension_defaultAdaptiveKey() throws Exception {
        {
            SimpleExt ext = ExtensionLoader.getExtensionLoader(SimpleExt.class).getAdaptiveExtension();

            Map<String, String> map = new HashMap<String, String>();
            URL url = new URL("p1", "1.2.3.4", 1010, "path1", map);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值