Dubbo explore expansion mechanism: on

This blog is recorded at the time I was determined to learn the depth of the framework notes Dubbo, Dubbo theme is the expansion point, the following sections are relatively fragmented, looks like and is not linked to the theme, and some very unpopular knowledge, but they are really in-depth study of pre-knowledge Dubbo

A knowledge base: Dubbo architecture diagram

architecture

Refinement about the various components of the graph:

  • service providers
    • Provide service interface implementation class
    • Registration Service (Remote Registry, locally registered)
    • External exposure services
  • Registry
    • Save mapping between the service name & address service
    • When the service address changed, take the initiative to inform consumers
  • Consumer Services
    • Address pull service providers from the registry when you start, in the local cache
    • Choose a service based on load balancing strategy for remote call (Dubbo will be the following information into an object is sent to the service provider over a network)
      • Parameter 1: Interface name
      • Parameter 2: Method name
      • Parameter 3: Parameter List Type
      • Parameter 4: The parameter value list
  • monitoring Center
    • Statistical data details RPC process, such as: the number of service calls, call time

The core concept of Dubbo: knowledge base two

URL

Dubbo he has a wrapper class called URL below: URL: Uniform Resources Loactor stands for Uniform Resource Locator, which is immutable, is thread-safe

url

  • The role of the URL

In fact, Dubbo it as an RPC communication framework, the main feature is responsible for transferring data across a cluster service between various points, such as playing an example: Consumers call service provider services, the process of communication is Dubbo framework the format of communication like the custom protocol to achieve the same ratio, Dubbo service protocol information / data transfer port number information needed / request that interface / parameter information / account / password information between the two kinds of consumers and service providers. and a series of information packages, then the above figure URL born

  • Understanding of the URL

The most intuitive understanding of the URL: URL is encapsulated dobbo series data, write transfer code, the parameters to facilitate

很多人也将URL称为Dubbo的消息总线, 说URL贯穿于Dubbo的上下文, 我感觉到这个结论也许是这样得出的, 就是说 Dubbo作为一款RPC框架, 首要的任务就是 RPC 远程过程调用, 怎么样找到提供服务的机器呢? 无论是发起socket 还是借助Thrift或者Netty这种框架实现也罢, 前提是得知道提供服务的机器在哪里, 它的哪些接口对外暴露服务 , 没错! 这些信息都被Dubbo封装在了URL中

  • URL常见的组成
    • protobuf - 协议信息, 如 zk / Dubbo / http / Thrift
    • host/port - 目标主机端口信息
    • path - 接口的名称
    • parameters - 参数键值对信息
  • 典型的Dubbo URL格式
# 描述 Dubbo 协议的服务
Dubbo://192.168.1.6:20880/moe.cnkirito.sample.HelloService?timeout=3000

# 描述 zookeeper 注册中心
zookeeper://127.0.0.1:2181/org.apache.Dubbo.registry.RegistryService?application=demo-consumer&Dubbo=2.0.2&interface=org.apache.Dubbo.registry.RegistryService&pid=1214&qos.port=33333&timestamp=1545721981946

# 描述消费者 服务
consumer://30.5.120.217/org.apache.Dubbo.demo.DemoService?application=demo-consumer&category=consumers&check=false&Dubbo=2.0.2&interface=org.apache.Dubbo.demo.DemoService&methods=sayHello&pid=1209&qos.port=33333&side=consumer&timestamp=1545721827784

# for this case, url protocol = null, url host = 192.168.1.3, port = 20880, url path = null
192.168.1.3:20880

# for this case, url protocol = file, url host = null, url path = home/user1/router.js
file:///home/user1/router.js?type=script

... 更多参照URL源码

Invoker

invoker 直译调用者

  • 在服务提供方: invoker 对象被构造出来去调用提供服务的函数
  • 在服务的消费方: invoker用于调用 执行远程过程调用的类

Invocation

指代程序中的调用对象, 包含了 接口名 / 方法名 / 参数类型列表 / 参数值列表 等

知识储备三: Java SPI (Service Provider Interface )

怎么理解SPI机制呢?

如果说SPI是java提供的一种拓展机制, 其实是不明确的, 结合java本身的语言特性来说, SPI直观的看就是 基于接口的编程 + 策略模式 + 配置文件 组合实现的动态加载机制, 用大白话解释就是说, 一个框架的设计为了后期的拓展性, 肯定先会在顶层设计接口, 然后再为这些接口提供一些默认的实现类, 未了良好的拓展性, 如果想让, 如果想实现允许当前框架 识别 / 加载 / 使用 第三方提供的jar包时 , 就可以使用SPI实现接口的动态加载, 只要遵循SPI的规范, java就能将我们自己的类也加载进JVM供我们使用

说起来总归是模糊的, 看下面的小Demo自然就懂了

// 接口
public interface Person {
    String getName();
}
// 实现类一: 
public class Student implements Person {
    @Override
    public String getName() {
        return "Student";
    }
}
//  实现类二: 
public class Teacher implements Person {
    @Override
    public String getName() {
        return "Teacher";
    }
}

resource/META-INF/services/ 目录下面添加配置文件, 文件名称为 Person接口的全限定名, 内容如下

com.changwu.javaspi.api.Student
com.changwu.javaspi.api.Teacher

测试程序:

public class Test {
    public static void main(String[] args) {
        // 加载接口中的实现类
        ServiceLoader<Person> load = ServiceLoader.load(Person.class);
        Iterator<Person> iterator = load.iterator();
        while (iterator.hasNext()){
            Person next = iterator.next();
            System.out.println(next.getName());
        }
    }
}

测试结果控制台输出如下:

Student
Teacher

Dubbo SPI

Dubbo自己也封装了一套SPI机制, 并将此作为它的扩展点,如果我们有更好的想法, 可以使用Dubbo这个特性加将我们自己的类注入给Dubbo, 它用法和JDK原生的SPI相似, 不同点在哪里呢? Dubbo的更强大, 比如相对于JDK的SPI , 它支持根据名称获取出指定的拓展类

一个小demo

  • 接口如下 , 注意点 Dubbo的SPI需要在接口上标注注解 @SPI
@SPI
public interface PersonInterface {
   String getName();
}
  • 两个实现类
public class Student implements PersonInterface {
    @Override
    public String getName() {
        return "Student";
    }
}

public class Teacher implements PersonInterface {
    @Override
    public String getName() {
        return "Teacher";
    }
}
  • 配置文件

Profiles

  • 测试类 可以根据名称明确指出使用哪一个实现类
public class Test {
    public static void main(String[] args) {
        // todo 第一点:  Dubbo 的SPI算作是他的一个可扩展的机制
        ExtensionLoader<PersonInterface> extensionLoader = ExtensionLoader.getExtensionLoader(PersonInterface.class);
        PersonInterface carInterface = extensionLoader.getExtension("student");
        System.out.println(carInterface.getName());
    }
}

Dubbo IOC

Spring 的IOC肯定是鼎鼎大名的, 很直接的能想到Spring的 @Autowired 注解, 或者的配置文件版本的 <bean>标签中可以帮我们自动维护bean之间的相互的依赖的关系

Dubbo 也实现了自己的IOC

比如下面的代码这样: Human.java 中依赖了 PersonInterface 类型的对象, 打眼看上去, 这个对象肯定是借助我们提供的setter方法完成的注入

public class Human implements PersonInterface {

    private PersonInterface carInterface;

    //todo 第一个关注点: 我们的关注点就是说, BeazCar 会帮我们将哪一个实现类当成入参注入进来呢?
    //todo 答案是 URL ,Dubbo自己封装的URL,  统一资源定位符, Dubbo 会解析入参位置的 url中封装的map
    //todo map中的key 与 CarInteface中的使用   @Adaptive("car") 注解标记的value对应, 那么值就是将要注入的实际类型
    //todo 第二个关注点: Dubbo底层很可能是通过反射使用构造方法完成的属性注入
    public void setCarInterface(PersonInterface carInterface) {
        this.carInterface = carInterface;
    }

    @Override
    public String getColor(URL url) {
        System.out.println("i am Human ");
        return "i am Human + " + carInterface.getColor(url);
    }
}

那么问题来了, 假如我们在配置文件中添加了多个PersonInterface接口的实现类, 那Dubbo是如何得知需要注入哪一个的呢? 答案就在入参位置的URL中, 也就是我在 知识储备二中提到的概念URL

可以看下面这段测试代码, 怎么读下面的这段代码呢?

单独看 (PersonInterface) extensionLoader.getExtension("human"); 其实就是前面所说的 Dubbo的SPI机制, 但是在这个基础上多出来的逻辑是啥呢? 是我们构建了一个URL, 那为什么加进去一个URL? 因为上面的示例代码说了, human依赖了一个 PersonInterface 类型的变量, Dubbo就是根据这个URL变量, 进而得知自己到底该该注入哪一个变量Personinterface实例的 (因为我提供了两个 一个是Student , 另一个是Teacher)

此外, 他需要的是map , 我们给它的也是一个hashmap , 特性就是HashMap的key是不重复的, 用大白话说, 它的底层肯定是 key=value 唯一绑定, 并且key也不会出现重复的情况

public class Test {
    public static void main(String[] args) {
        // todo 源码的入口, 进入 getExtensionLoader()
        ExtensionLoader extensionLoader = ExtensionLoader.getExtensionLoader(PersonInterface.class);
        HashMap<String, String> map = new HashMap<>();
        map.put("human", "student");
        URL url = new URL("", "",1,map);
        // todo 继续跟进这个方法
        PersonInterface carInterface = (PersonInterface) extensionLoader.getExtension("human");
        System.out.println(carInterface.getName(url));
    }
}

那说了这么多, 到底注入的是哪一个对象呢? 从map.put("human", "student"); 也能很清楚的看出来, 不就是Student吗? 是的, 确实是它, 但是还少了点东西, 就是Personinterface怎么编写呢? 如下:

// @SPI("stu") 可以给注解添加参数, 参数表示 CarInterface 的默认实现类
@SPI
public interface PersonInterface {
    // todo 下面的注解很重要, 啥意思呢?  可以点进这个注解, 我有一些翻译
    // 验证AOP, 依然注入的信息从 url中获取出来
    @Adaptive("human")
    String getName(URL url);
}

看上面的代码, 除了@SPI注解, 还有一个注解就是@Adaptive注解, 这个注解的value部分决定了Dubbo到底需要注入哪一个 ExtensionObject

因为Dubbo在启动的过程中会去读取/META-INF/services/ Dubbo-SPI配置文件, 并将每行数据读取维护在一个map中, key就是我们自定义的名字, 值就是左边的全类名

看下面我们传递进去的是 human , 表示告诉Dubbo, 让Dubbo拿着human去查找, 很显然Dubbo把我们前面传递给它的student 找出来, 有了Student 进一步再从上下文中所有的 ExtensionObject中(包含了我们在配置文件中添加进去的Personinterface的两个实现) 找到具体的注入对象

Dubbo AOP

Or, AOP is an aspect-oriented programming ideas, Spring implements a set of their own, Dubbo also achieved a

Verify Dubbo AOP implementation classes are as follows:

  • Dubbo's AOP implementation and enhancement similar to the static agent encoding, such as we enhancement PersonInterface in, so we inherit PersonInterface, provides the constructor, leaving Dubbo by reflecting the completion of the injection target object, and inject the incoming target the method of the target object before and after implantation enhanced logic
public class PersonWrapper implements PersonInterface {

    // todo 验证Dubbo的自动注入
    private PersonInterface carInterface;
    // todo 根据构造方法进行注入
    public PersonWrapper(PersonInterface in){ // 假设传递进来的就是具体的实现类
        this.carInterface=in;
    }

    // todo 当我们将 CarWrapper 配置进 Dubbo的 spi中时, 通过Dubbo的Spi获取CarInterface执行时,下面的方法就会被执行
    @Override
    public String getName() {
        System.out.println("before... ");
        String color = carInterface.getName();
        System.out.println("after... ");
        return "getName";
    }
}
  • Dubbo know how to make that contains our Enhanced Logic PersonWrapper objects do the same, through the configuration file is completed, the following?:

Profile 2

  • Tests are as follows:
 public static void main(String[] args) {
        // todo 第一点:  Dubbo 的SPI算作是他的一个可扩展的机制
        ExtensionLoader<PersonInterface> extensionLoader = ExtensionLoader.getExtensionLoader(PersonInterface.class);
        PersonInterface carInterface = extensionLoader.getExtension("student");
        System.out.println(carInterface.getName());
    }

The results are as follows:

before...
after...
getName  

The AOP enhanced through multiple classes, the order from top to bottom such that w1 w2 ... appear order of addition so enhanced logic before2 before1

Conclusion:

Next post is to explore the underlying point of the Dubbo to expand these implementation details, or of very interesting ...

Finally playing a small ad: I am bloger give me daydream, read in junior college, eager java development, Java expect to have a work-related internship positions, internships and full-time about six months, the best cities are Beijing, seeking Gangster interpolation wow

Guess you like

Origin www.cnblogs.com/ZhuChangwu/p/12174031.html