Dubbo基本特性之泛化调用

  Dubbo 是支持泛化调用的,什么是泛化调用呢?泛化调用的好处是什么呢,泛化调用说白一点就是服务消费者并没有服务的接口。

  在《Dubbo入门—搭建一个最简单的Demo框架》一文中,我们已完成了最最基本的Dubbo的搭建及调用,我们的dubbo-provider、dubbo-consumer、dubbo-consumer2都是依赖dubbo-api,而dubbo-api其实什么也没做,就定义了一个接口,也就是说,在我们开发写Demo的时候,必做的一件事情,就是在服务消费者和服务提供者两端同路径下有同样的接口,只不过在服务提供者端会有该接口的具体实现,之所以在服务消费者有一个没有任何具体实现的接口,是因为在设计RPC之初,设计者的最高理念就是你去面向接口编程,你在进行远程调用的时候,并没有意识到你在进行远程调用,却也能拿到接口一样,相信你也感觉到了,服务消费者在调用服务的时候,与调用一个普通的接口是一样的。

  泛化调用就是服务消费者端因为某种原因并没有该服务接口,这个原因有很多,比如是跨语言的,一个PHP工程师想调用某个java接口,他并不能按照你约定,去写一个个的接口,Dubbo并不是跨语言的RPC框架,但并不是不能解决这个问题,这个PHP程序员搭建了一个简单的java web项目,引入了dubbo的jar包,使用dubbo的泛化调用,然后利用web返回json,这样也能完成跨语言的调用。泛化调用的好处之一就是这个了。

  好了,简而言之,泛化调用,最最直接的表现就是服务消费者不需要有任何接口的实现,就能完成服务的调用。

一.泛化调用入门

  老规矩,我们现在服务提供者端定义一个简单的接口,(与往常不一样的地方就是不需要把该接口复制到服务提供者的同路径下了,因为服务消费者不需要使用该接口进行调用),在这我们就继续用《Dubbo入门—搭建一个最简单的Demo框架》一文中的案例代码。

  定义一个简单的接口DemoService.java

package com.alibaba.dubbo.demo;

import java.util.List;

public interface DemoService {
    List<String> getPermissions(Long id);
}

  该接口的具体实现DemoServiceImpl.java

package com.alibaba.dubbo.demo.impl;

import com.alibaba.dubbo.demo.DemoService;

import java.util.ArrayList;
import java.util.List;

public class DemoServiceImpl implements DemoService {
    public List<String> getPermissions(Long id) {
        List<String> demo = new ArrayList<String>();
        demo.add(String.format("Permission_%d", id - 1));
        demo.add(String.format("Permission_%d", id));
        demo.add(String.format("Permission_%d", id + 1));
        return demo;
    }
}

  服务提供者端的Spring的配置文件provider.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://code.alibabatech.com/schema/dubbo
       http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
    <!--定义了提供方应用信息,用于计算依赖关系;在 dubbo-admin 或 dubbo-monitor 会显示这个名字,方便辨识-->
    <dubbo:application name="demotest-provider" owner="programmer" organization="dubbox"/>
    <!--使用 zookeeper 注册中心暴露服务,注意要先开启 zookeeper-->
    <dubbo:registry address="zookeeper://localhost:2181"/>
    <!-- 用dubbo协议在20880端口暴露服务 -->
    <dubbo:protocol name="dubbo" port="20880" />
    <!--使用 dubbo 协议实现定义好的 api.PermissionService 接口-->
    <dubbo:service interface="com.alibaba.dubbo.demo.DemoService" ref="demoService" protocol="dubbo"/>
    <!--具体实现该接口的 bean-->
    <bean id="demoService" class="com.alibaba.dubbo.demo.impl.DemoServiceImpl"/>
</beans>

  服务提供者端再写一个启动类Provider.java:

package com.alibaba.dubbo.demo.impl;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.io.IOException;

public class Provider {
    public static void main(String[] args) throws IOException {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
                "provider.xml");
        System.out.println(context.getDisplayName() + ": here");
        context.start();
        System.out.println("服务已经启动...");
        System.in.read();
    }
}

  好了,到此为止,泛化调用服务提供者的配置文件就全部结束了,你可以看到从代码和spring的配置文件都没有任何特殊处理,与一般的服务提供者并没有任何的不同,泛化调用,从这四个字看也知道是调用的方式不一样而已,我们再看看服务消费者端的代码编写。

  因为服务消费者没有了接口,我们直接编写消费者端spring的配置文件consumer.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">

    <dubbo:application name="demotest-consumer" owner="programmer" organization="dubbox"/>
    <!--向 zookeeper 订阅 provider 的地址,由 zookeeper 定时推送-->
    <dubbo:registry address="zookeeper://localhost:2181"/>
    <!--使用 dubbo 协议调用定义好的 api.PermissionService 接口-->
    <dubbo:reference id="permissionService" interface="com.alibaba.dubbo.demo.DemoService" generic="true"/>
</beans>

  可以看到上图的配置文件中有两个地方需要注意一下,第一个是interface,其实该接口在消费者端并不存在,这是与往常写的不一样的地方,第二个地方需要注意的地方就是generic=”true”这样的标签,表示该接口支持泛型调用。

  好了,我们写一个服务测试类,看看如何进行泛型调用Consumer.java

package com.alibaba.dubbo.consumer;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.alibaba.dubbo.rpc.service.GenericService;

public class Consumer {
    public static void main(String[] args) {
        /////////////////Spring泛化调用/////////  
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("consumer.xml");
        context.start();
        System.out.println("consumer start");
        GenericService demoService = (GenericService) context.getBean("permissionService");
        System.out.println("consumer");
        Object result = demoService.$invoke("getPermissions", new String[] { "java.lang.Long" }, new Object[]{ 1L });
        System.out.println(result);
    }
}

  看到Main函数中,从spring的上下文中读到”permissionService”之后却把它强转为GenericService的类,然后调用GenericService的$invoke的方法,该方法有三个参数,第一个参数是你调用远程接口的具体方法名,第二个参数是permissionService这个方法的入参的类型,最后一个参数是值。

  我们测试一下,启动dubbo-provider的main函数,然后启动服务消费者的测试类Consumer.java,你会发现控制台打印:

[22/04/18 05:06:36:036 CST] main  INFO config.AbstractConfig:  [DUBBO] Refer dubbo service com.alibaba.dubbo.rpc.service.GenericService from url zookeeper://localhost:2181/com.alibaba.dubbo.registry.RegistryService?anyhost=true&application=demotest-consumer&check=false&dubbo=2.5.3&generic=true&interface=com.alibaba.dubbo.demo.DemoService&methods=getPermissions&organization=dubbox&owner=programmer&pid=6604&side=consumer&timestamp=1524387995725, dubbo version: 2.5.3, current host: 10.39.56.134
consumer
[Permission_0, Permission_1, Permission_2]

  可以看到能够调通,没有问题。

  我们刚才说,一个PHP程序员想要搭建一个简单的web项目,可是你却叫他依赖于spring的配置文件,对他难度是不小的,dubbo也帮你想到了,泛型调用,服务消费端可以不依赖spring的配置文件,我们重新写下测试类Consumer:

package com.alibaba.dubbo.consumer;

import com.alibaba.dubbo.config.ApplicationConfig;
import com.alibaba.dubbo.config.ReferenceConfig;
import com.alibaba.dubbo.config.RegistryConfig;
import com.alibaba.dubbo.config.utils.ReferenceConfigCache;
import com.alibaba.dubbo.rpc.service.GenericService;

public class Consumer {
    public static void main(String[] args) {

        // 普通编码配置方式
        ApplicationConfig application = new ApplicationConfig();
        application.setName("dubbo-consumer");  

        // 连接注册中心配置
        RegistryConfig registry = new RegistryConfig();
        registry.setAddress("zookeeper://127.0.0.1:2181");  

        ReferenceConfig<GenericService> reference = new ReferenceConfig<GenericService>();
        reference.setApplication(application);
        reference.setRegistry(registry);
        reference.setInterface("com.alibaba.dubbo.demo.DemoService");
        reference.setGeneric(true); // 声明为泛化接口  

        ReferenceConfigCache cache = ReferenceConfigCache.getCache();
        GenericService genericService = cache.get(reference);  

        // 基本类型以及Date,List,Map等不需要转换,直接调用
        Object result = genericService.$invoke("getPermissions", new String[] { "java.lang.Long" },
                new Object[] { 1L });
        System.out.println(result);
    }
}

  重新启动一下该类。控制台正常打印:

[22/04/18 05:09:09:009 CST] main  INFO config.AbstractConfig:  [DUBBO] Refer dubbo service com.alibaba.dubbo.rpc.service.GenericService from url zookeeper://127.0.0.1:2181/com.alibaba.dubbo.registry.RegistryService?anyhost=true&application=dubbo-consumer&check=false&dubbo=2.5.3&generic=true&interface=com.alibaba.dubbo.demo.DemoService&methods=getPermissions&organization=dubbox&owner=programmer&pid=21144&side=consumer&timestamp=1524388149244, dubbo version: 2.5.3, current host: 10.39.56.134
[Permission_0, Permission_1, Permission_2]

  也能正常进行调用。

二.泛化调用小结

  泛化调用可以方便用户对dubbo服务消费者端的扩展,可以方便,丰富了服务消费者的调用方式,甚至可以做变相的Rest调用,这些都是可以的,不过,它的缺点也是很明显的,参数传递复杂,不方便使用。但是这种方式是不能缺失的。

参考文章:https://blog.csdn.net/linuu/article/details/54313560

实例代码:http://bijian1013.iteye.com/blog/2419726

原文地址:https://www.cnblogs.com/flyingeagle/p/8908317.html

时间: 2024-10-10 01:03:32

Dubbo基本特性之泛化调用的相关文章

dubbo泛化调用 小demo

前两天刚好有个同事来问是否用过 dubbo泛化 调用,不需要通过指定配置.第一次听到的时候,还是有点懵,但觉得有意思,可以学点东西. 立马百度了,找了demo,这篇比较容易上手(http://www.cnblogs.com/lobo/p/7129119.html).并结合 dubbo的官方文档(http://dubbo.io/user-guide/demos/%E6%B3%9B%E5%8C%96%E5%BC%95%E7%94%A8.html)写了个demo. provider 直接引用了 dub

服务消费端泛化调用与异步调用

本文借用dubbo.learn的Dubbo API方式来解释原理. 服务消费端泛化调用 前面我们讲解到,基于Spring和基于Dubbo API方式搭建简单的分布式系统时,服务消费端引入了一个SDK二方包,里面存放着服务提供端提供的所有接口类,之所以需要引入接口类是因为服务消费端一般是基于接口使用JDK代理实现远程调用的. 泛化接口调用方式主要在服务消费端没有API接口类及模型类元(比如入参和出参的POJO类)的情况下使用.其参数及返回值中没有对应的POJO类,所以所有POJO均转换为Map表示

构建 Zookeep + Dubbo + Spring Boot 的分布式调用项目(一)

一.写在前头 在开始构建前,默认你已经能够成功安装并启动 Zookeeper 注册中心,能够成功安装并启动 Dubbo 控制台: 在本例中,我的 Zookeeper 注册中心 IP 地址为 192.168.10.41,端口号为 4183,Dubbo 控制台的访问地址为 http://192.168.10.41:8080: 为了体现分布式调用,本例中创建了以下两个项目,dubbo-consumer 远程调用 dubbo-provider 提供的服务: dubbo-provider        

vuejs开发笔记—IDE选择和WebStorm性能优化、框架特性和数据调用、路由的配置以及原理

一.IDE的选择: VsCode和WebStorm都是不错的选择,两者运行调试都非常的方便都可以使用快捷键运行和停止,就打开项目的速度和对电脑配置的要求来说,vscode要比webstorm要出色很多,如果电脑配置足够好的情况下请忽略前面说的性能问题,具体的使用要看个人的需求和爱好了. 1.先说VsCode的配置: 首先是要装VsCode的扩展插件,点击左上角最后一个图标,在搜索里面输入JavaScript (ES6) snippets/NPM/Vue 2 Snippets: 第二步调试配置:V

dubbo集成zookeeper rpc远程调用

注:下面使用dubbo依赖的是zookeeper注册中心,这里没有详细的介绍.在配置之前,请自行准备好zookeeper环境. 后续如果写zookeeper的配置会补放链接 添加Gradle依赖 compile group: 'com.alibaba', name: 'dubbo', version: '2.5.10'//dubbo compile group: 'org.apache.zookeeper', name: 'zookeeper', version: '3.3.3'//zookee

dubbo 服务端和客户端调用

下面是一种客户端和服务端的调用链,可能会走到其他分支,但是通过这一条链路,可以观察dubbo的整体脉络. 服务端: 客户端:

Dubbo通过注解实现RPC调用

启动Dubbo服务有2个方式,1是通过xml配置,2是通过注解来实现,这点和Spring相似. 采用XML配置如下:  <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance&

dubbo之泛化引用

使用泛化调用 泛化接口调用方式主要用于客户端没有 API 接口及模型类元的情况,参数及返回值中的所有 POJO 均用 Map 表示,通常用于框架集成,比如:实现一个通用的服务测试框架,可通过 GenericService 调用所有服务实现. 通过 Spring 使用泛化调用 在 Spring 配置申明 generic="true": <dubbo:reference id="barService" interface="com.foo.BarServ

dubbo之泛化实现

实现泛化调用 泛化接口调用方式主要用于客户端没有 API 接口及模型类元的情况,参数及返回值中的所有 POJO 均用 Map 表示,通常用于框架集成,比如:实现一个通用的服务测试框架,可通过 GenericService 调用所有服务实现. 通过 Spring 实现泛化调用 在 Spring 配置申明服务的实现: <bean id="genericService" class="com.foo.MyGenericService" /> <dubbo