什么是泛化调用?怎么实现Dubbo的泛化调用?代码怎么写?如果有疑问,请进!!

05-01 1069阅读 0评论

最近无意中了解了泛化调用,起初云里雾里的,后面跟着官方的示例走了一遍,通过思考知道它是什么了。

什么是泛化调用?

它主要应对一种场景的,我要调用某些服务的某些接口,但是我并不知道有哪些系统,所以也就没有办法通过Jar包方式依赖,这种解决方案呢,除了HTTP呢,也可以RPC,但是前提呢就需要被调用的某些服务通过某种方式主动注册到注册中心,也就是服务提供者,而这边呢从注册中心拿到注册的信息以及接口信息(相当于消费端),拿到以后可以使用Dubbo泛化调用方式(也可以用其他方式)来调用服务端的接口。 

通俗来讲就是你需要启动你的服务注册中心(本节用zookeeper),然后你需要将服务放入到注册中心中,消费端(网关、测试平台等情形)使用时则去注册中心找到信息,通过Dubbo泛化调用GenericService.$invoke()调用到对应的服务接口中。

我们会讲下代码,不过首先要安装zookeper,本地版本有可以跳过,注意代码里的版本和你安装的版本,如果差太多,启动服务会连不上zookeper。

 2.安装zookerper

Windows安装Zookeeper,链接如下,我下载安装的是3.6.4的 apache-zookeeper-3.6.4-bin.tar.gz 包

https://archive.apache.org/dist/zookeeper/zookeeper-3.6.4/

 下载后解压压缩包,然后添加data文件

什么是泛化调用?怎么实现Dubbo的泛化调用?代码怎么写?如果有疑问,请进!!

接着进入conf文件, 讲zoo_sample.cfg复制一份,然后将复制的那份更改为zoo.cfg文件什么是泛化调用?怎么实现Dubbo的泛化调用?代码怎么写?如果有疑问,请进!!

然后编辑 zoo.cfg文件,将dataDir属性更改为我们的data目录地址

什么是泛化调用?怎么实现Dubbo的泛化调用?代码怎么写?如果有疑问,请进!!

然后配置环境变量,点击环境变量,点击新建,名字为:ZOOKEEPER_HOME,然后填写我们的目的路径

什么是泛化调用?怎么实现Dubbo的泛化调用?代码怎么写?如果有疑问,请进!!

然后点击path进去编辑 ,把ZOOKEEPER_HOME写上,按如下的就可以啦,退出时全部选确定。

什么是泛化调用?怎么实现Dubbo的泛化调用?代码怎么写?如果有疑问,请进!!

 然后打开cmd,输入zkserver,就启动成功啦,端口号是2181

什么是泛化调用?怎么实现Dubbo的泛化调用?代码怎么写?如果有疑问,请进!!

3.代码

大家可以借鉴dubbo官网的搭建方式,链接如下,还是很详细的。

https://cn.dubbo.apache.org/zh-cn/overview/quickstart/java/spring-boot/

 你按官方文档安装你就会有如下的代码结构。

dubbo-springboot-demo-provider:为服务提供者

dubbo-springboot-demo-interface:服务接口,共享的接口

dubbo-springboot-demo-consumer:服务消费者

什么是泛化调用?怎么实现Dubbo的泛化调用?代码怎么写?如果有疑问,请进!!什么是泛化调用?怎么实现Dubbo的泛化调用?代码怎么写?如果有疑问,请进!!

3.1 dubbo-springboot-demo-interface

咱们先来说下服务共享者,很简单,我们只定义了一个接口叫DemoService,并定义了方法sayHello

/**
 * @Author df
 * @Description: TODO
 * @Date 2024/3/5 10:47
 */
public interface DemoService {
    String sayHello(String name);
}

它的pom.xml


    
        dubbo-spring-boot-demo
        org.example
        1.0-SNAPSHOT
    
    4.0.0
    dubbo-spring-boot-demo-interface
    
        8
        8
    

3.2 dubbo-springboot-demo-provider

然后服务提供者,类DemoServiceImpl,实现DemoService,也就是说它依赖dubbo-springboot-demo-interface的jar。

/**
 * @Author df
 * @Description: TODO
 * @Date 2024/3/5 10:56
 */
@DubboService
public class DemoServiceImpl implements DemoService {
    @Override
    public String sayHello(String name) {
        return "Hello " + name;
    }
}

服务提供者还要提供启动服务的入口,所以需要下面这个代码,因为只有启动代码,才能把自己的接口注册到服务中心里。

/**
 * @Author df
 * @Description: TODO
 * @Date 2024/3/5 11:26
 */
@SpringBootApplication
@EnableDubbo
public class ProviderApplication {
    public static void main(String[] args) {
        SpringApplication.run(ProviderApplication.class, args);
    }
}

 它的application.yml文件

dubbo:
  application:
    name: dubbo-springboot-demo-provider
  protocol:
    name: dubbo
    port: -1
  registry:
    address: zookeeper://169.254.165.11:2181

它的pom.xml文件


    
        dubbo-spring-boot-demo
        org.example
        1.0-SNAPSHOT
    
    4.0.0
    dubbo-spring-boot-demo-provider
    
        8
        8
    
    
        
            org.example
            dubbo-spring-boot-demo-interface
            ${project.parent.version}
        
        
        
            org.apache.dubbo
            dubbo-spring-boot-starter
        
        
            org.apache.dubbo
            dubbo-dependencies-zookeeper-curator5
            pom
            
                
                    slf4j-reload4j
                    org.slf4j
                
            
        
        
        
            org.springframework.boot
            spring-boot-starter
        
        
            org.example
            dubbo-spring-boot-interface
            1.0-SNAPSHOT
            compile
        
    

3.3 dubbo-springboot-demo-consume

在消费者中我们定义了Task类,实现CommandLineRunner,代表项目启动执行一次run方法,然后我们取DemoService,当然这里要用 @DubboReference,拿到以后直接调用方法就ok了。

在定义一个循环线程一直执行方法拿到结果打印来做测试。

/**
 * @Author df
 * @Description: TODO
 * @Date 2024/3/5 11:44
 */
@Component
public class Task implements CommandLineRunner {
    @DubboReference
    private DemoService demoService;
    // 消费者调用RPC生产者消息
    // CommandLineRunner在程序启动后执行run方法,
    @Override
    public void run(String... args) throws Exception {
        String result = demoService.sayHello("world");
        System.out.println("two-Receive result ======> " + result);
       new Thread(()-> {
           while (true) {
                try {
                    Thread.sleep(1000);
                    System.out.println(new Date() + " Receive result ======> " + demoService.sayHello("world"));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    Thread.currentThread().interrupt();
                }
            }
        }).start();
    }
}

消费者也需要启动程序,所以我们也加一个程序的启动入口。

/**
 * @Author df
 * @Description: TODO
 * @Date 2024/3/5 11:27
 */
@SpringBootApplication
@EnableDubbo
public class ConsumerApplication {
    public static void main(String[] args) {
        SpringApplication.run(ConsumerApplication.class, args);
    }
}

消费者的 application.yml,也是需要将自己本身服务注册到服务中心。

dubbo:
  application:
    name: dubbo-springboot-demo-consumer
  protocol:
    name: dubbo
    port: -1
  registry:
    address: zookeeper://${zookeeper.address:127.0.0.1}:2181

pom.xml


    
        dubbo-spring-boot-demo
        org.example
        1.0-SNAPSHOT
    
    4.0.0
    dubbo-spring-boot-demo-consumer
    
        
            org.example
            dubbo-spring-boot-demo-interface
            ${project.parent.version}
        
        
        
            org.apache.dubbo
            dubbo-spring-boot-starter
        
        
            org.apache.dubbo
            dubbo-dependencies-zookeeper-curator5
            pom
            
                
                    slf4j-reload4j
                    org.slf4j
                
            
        
        
        
            org.springframework.boot
            spring-boot-starter
        
    

他们的父类pom.xml


    4.0.0
    org.example
    dubbo-spring-boot-demo
    pom
    1.0-SNAPSHOT
    
        dubbo-spring-boot-demo-interface
        dubbo-spring-boot-demo-provider
        dubbo-spring-boot-demo-consumer
    
    
        3.0.8
        2.7.7
        1.8
        1.8
        UTF-8
    
    
        
            
            
                org.springframework.boot
                spring-boot-dependencies
                ${spring-boot.version}
                pom
                import
            
            
            
                org.apache.dubbo
                dubbo-bom
                ${dubbo.version}
                pom
                import
            
            
                org.apache.dubbo
                dubbo-dependencies-zookeeper-curator5
                ${dubbo.version}
                pom
            
        
    
    
        
            
                
                    org.springframework.boot
                    spring-boot-maven-plugin
                    ${spring-boot.version}
                
            
        
    

先启动服务提供接口,打印如下控制台信息,代表我们已经连上zookeper了,等待消费者消费呢。

什么是泛化调用?怎么实现Dubbo的泛化调用?代码怎么写?如果有疑问,请进!!

我们在启动消费者的服务,消费者就调用到我们对应的方法啦。

什么是泛化调用?怎么实现Dubbo的泛化调用?代码怎么写?如果有疑问,请进!!

 我们现在之所以能调用到对应的服务是因为我们消费方依赖了共用接口,如果我们现在不依赖了,就没有办法用上面的方式了,就需要用到GenericService,我们来实现下。

什么是泛化调用?怎么实现Dubbo的泛化调用?代码怎么写?如果有疑问,请进!!什么是泛化调用?怎么实现Dubbo的泛化调用?代码怎么写?如果有疑问,请进!!

我们在创建一个FHTask类,代码如下, 通过@DubboReference将接口信息传入,再通过genericService.$invoke将方法和参数类型和参数传入,最后会调用到最终的实现类,拿到结果打印下就OK。

/**
 * @Author df
 * @Description: TODO
 * @Date 2024/3/5 11:44
 */
@Order(1)
@Component
public class FHTask implements CommandLineRunner {
    // 泛化调用,不主动获取没有依赖情况下
    @DubboReference(interfaceName = "org.apache.dubbo.springboot.demo.DemoService")
    GenericService genericService;
    // 消费者调用RPC生产者消息
    // CommandLineRunner在程序启动后执行run方法,
    @Override
    public void run(String... args) throws Exception {
        // 拿到接口关键信息,重新构建个请求
        Object result = genericService.$invoke("sayHello", new String[]{"java.lang.String"}, new Object[]{"fh-Invoke"});
        System.out.println("Receive result ======> " + result);
    }
}

 由于没有了interface的依赖,所以需要将Task注释掉,代码如下,

@Order(2)
@Component
public class Task implements CommandLineRunner {
    //@DubboReference
    //private DemoService demoService;
    // 消费者调用RPC生产者消息
    // CommandLineRunner在程序启动后执行run方法,
    @Override
    public void run(String... args) throws Exception {
       // String result = demoService.sayHello("world");
        //System.out.println("two-Receive result ======> " + result);
//        new Thread(()-> {
//            while (true) {
//                try {
//                    Thread.sleep(1000);
//                    System.out.println(new Date() + " Receive result ======> " + demoService.sayHello("world"));
//                } catch (InterruptedException e) {
//                    e.printStackTrace();
//                    Thread.currentThread().interrupt();
//                }
//            }
//        }).start();
    }
}

启动服务者和消费者,也还是调用到具体的方法啦。

什么是泛化调用?怎么实现Dubbo的泛化调用?代码怎么写?如果有疑问,请进!!

 它主要是根据注册的接口信息,以及方法,参数等信息去注册中心找到对应匹配的实现类,进行调用方法,这样我们自己就不用写复杂的业务代码就能实现了没有依赖情况代码功能的调用使用。


免责声明
本网站所收集的部分公开资料来源于AI生成和互联网,转载的目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。
文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

发表评论

快捷回复: 表情:
评论列表 (暂无评论,1069人围观)

还没有评论,来说两句吧...

目录[+]