`
y806839048
  • 浏览: 1121443 次
  • 性别: Icon_minigender_1
  • 来自: 上海
文章分类
社区版块
存档分类
最新评论

Dubbo 高级特性实践 - 泛化调用

阅读更多

泛化调用,针对消费端不是标准的注入了服务端的,可以直接在消费端用泛化的方式处理,类似直接用resttemplate基于url调用---类似springcloud的sidecar

注入服务的是注入的时候就反射生产服务,泛化是在请求url到了之后临时根据接口,方法,参数,反射调用

 

 

 

当后端Java服务用Dubbo协议作为RPC方案的基础,但部分消费方是前端Restful的PHP服务,不能直接调用,于是在中间架设了Router服务提供统一的基于HTTP的后端调用入口。
而Router调用后端Java服务就应用了Dubbo的高级特性–泛化调用

  • 直接消费方(Router服务)不需要引入接口jar包
  • 通过GenericService接口来处理所有服务请求
  • 以PHP到Router的request body中的方法名和方法参数作为Router远程调用后端Java服务的入参,最后将远程调用的result返回给PHP端

本文将用一个小Demo来演示上面所述的泛化调用应用场景

零.Dubbo简介

DUBBO是一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,是阿里巴巴SOA服务化治理方案的核心框架,每天为2,000+个服务提供3,000,000,000+次访问量支持,并被广泛应用于阿里巴巴集团的各成员站点。
– Dubbo官方描述

Dubbo能做什么:

  • 透明化的远程方法调用
    • 就像调用本地方法一样调用远程方法
    • 只需简单配置,没有任何API侵入。
  • 软负载均衡及容错机制
    • 可在内网替代F5等硬件负载均衡器
  • 服务自动注册与发现
    • 不再需要写死服务提供方地址,注册中心基于接口名查询服务提 供者的IP地址,并且能够平滑添加或删除服务提供者

– 《Dubbo功能介绍》(官方资料)

注:Dubbo的基本使用介绍不在本文范畴,如有需要请自行参考官方资料

泛接口调用方式主要用于客户端没有API接口及模型类元的情况,参数及返回值中的所有POJO均用Map表示,通常用于框架集成,比如:实现一个通用的服务测试框架,可通过GenericService调用所有服务实现。
– Dubbo用户指南

一.后端API

public interface UserInfoService {
    public Map<String, String> getUser(String id);
    public Map<String, String>[] getUsers();
}

二.Router端dubbo配置

dubboconf.properties:

application.name=router
registry.address=zookeeper://address1?buckup=address2,address3

三.前端服务post到Router的Request Body示例:

{
    "interfaceName": "foo", 
    "methodName": "bar", 
    "methodParams": [
        {
            "id": "xxx"
        }
    ]
}

四.处理前端参数用的Dto

RequestDto.java:

import java.util.Map;
/**
 * Created by Luo
 */
public class RequestDto {
    private String interfaceName;
    private String methodName
    private Map[] methodParams;

    public String getInterfaceName() {
        return interfaceName;
    }
    public void setInterfaceName(String interfaceName) {
        this.interfaceName =  interfaceName;
    }
    public String getMethodName() {
        return methodName;
    }
    public void setMethodName(String methodName) {
        this.methodName = methodName;
    }
    public Map[] getMethodParams() {
        return methodParams;
    }
    public void setMethodParam(Map[] methodParams) {
        this.methodParams = methodParams;
    }
}

五.Router服务入口

RouterController.java:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by Luo
 */
@RestController
public class App {
        @RequestMapping(value = "/router/", method = RequestMethod.POST)
        public Object getUser(@ModelAttribute RequestDto dto) {
            Map map = new HashMap<>();
            map.put("ParamType", "java.lang.String");  //后端接口参数类型
            map.put("Object", dto.getMethodParams()[0].get("id"));  //用以调用后端接口的实参

            List<Map<String, Object>> paramInfos= new ArrayList<>();
            paramInfos.add(map);

            DubboServiceFactory dubbo = DubboServiceFactory.getInstance();

            return dubbo.genericInvoke(dto.getInterfaceName(), dto.getMethodName(), paramInfos);
        }
}

注:本文旨在演示泛化调用的一种应用方式,为简明起见,代码中直接从dto中获取了指定参数,而并没有完整实现其路由功能,望见谅。

六.通过GenericService进行泛化调用

DubboServiceFactory.java

package local.demo.genericservice;

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;


import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Properties;

/**
 * Created by Luo
 */
public class DubboServiceFactory {

    private ApplicationConfig application;
    private RegistryConfig registry;

    private static class SingletonHolder {
        private static DubboServiceFactory INSTANCE = new DubboServiceFactory();
    }

    private DubboServiceFactory(){
        Properties prop = new Properties();
        ClassLoader loader = DubboServiceFactory.class.getClassLoader();

        try {
            prop.load(loader.getResourceAsStream("dubboconf.properties"));
        } catch (IOException e) {
            e.printStackTrace();
        }

        ApplicationConfig applicationConfig = new ApplicationConfig();
        applicationConfig.setName(prop.getProperty("application.name")); 
        //这里配置了dubbo的application信息*(demo只配置了name)*,因此demo没有额外的dubbo.xml配置文件
        RegistryConfig registryConfig = new RegistryConfig();
        registryConfig.setAddress(prop.getProperty("registry.address")); 
        //这里配置dubbo的注册中心信息,因此demo没有额外的dubbo.xml配置文件

        this.application = applicationConfig;
        this.registry = registryConfig;

    }

    public static DubboServiceFactory getInstance() {
        return SingletonHolder.INSTANCE;
    }

    public Object genericInvoke(String interfaceClass, String methodName, List<Map<String, Object>> parameters){

        ReferenceConfig<GenericService> reference = new ReferenceConfig<GenericService>();
        reference.setApplication(application); 
        reference.setRegistry(registry); 
        reference.setInterface(interfaceClass); // 接口名 
        reference.setGeneric(true); // 声明为泛化接口 

        //ReferenceConfig实例很重,封装了与注册中心的连接以及与提供者的连接,
        //需要缓存,否则重复生成ReferenceConfig可能造成性能问题并且会有内存和连接泄漏。
        //API方式编程时,容易忽略此问题。
        //这里使用dubbo内置的简单缓存工具类进行缓存

        ReferenceConfigCache cache = ReferenceConfigCache.getCache();
        GenericService genericService = cache.get(reference); 
        // 用com.alibaba.dubbo.rpc.service.GenericService可以替代所有接口引用 

        int len = parameters.size();
        String[] invokeParamTyeps = new String[len];
        Object[] invokeParams = new Object[len];
        for(int i = 0; i < len; i++){
            invokeParamTyeps[i] = parameters.get(i).get("ParamType") + "";
            invokeParams[i] = parameters.get(i).get("Object");
        }
        return genericService.$invoke(methodName, invokeParamTyeps, invokeParams);
    }

}

七.部署

 

将Router部署到Jetty/Tomcat等容器,或者直接使用SpringBoot开发,发布为内嵌Jetty/Tomcat的独立jar包,即可向前端服务提供服务。

 

分享到:
评论

相关推荐

    从零开始手写 dubbo rpc 框架-12-generic泛化调用.docx

    "从零开始手写 Dubbo RPC 框架-泛化调用" Dubbo 是一个基于 Java 实现的 RPC 框架,主要用于个人学习和理解 RPC 的底层实现原理。在这个文件中,我们将深入探讨 Dubbo 的泛化调用机制。 泛化调用 泛化调用是一种...

    从零开始手写 dubbo rpc 框架-12-generic泛化调用.pdf

    GenericService 是 Dubbo RPC 框架中提供的一种泛化调用接口,通过这个接口,客户端可以调用服务端的方法,无需知道服务端的接口和模型类元。 GenericService 接口提供了一个 $invoke 方法,用于调用服务端的方法。...

    dubbo-user-book

    - **泛化引用与泛化实现**:在服务消费者和提供者之间可以不共享接口,实现完全的泛化调用。 - **回声测试(Echo)**:用于检测服务提供者是否存活。 - **上下文信息传递**:在Dubbo调用链中,可以传递一些上下文...

    Dubbo go技术实践分享.pdf

    本文主要介绍了Dubbo Go在实际技术实践中的应用和选择理由,以及在系统架构、服务设计和网关实现等方面的实践经验。Dubbo Go作为一个高性能的RPC框架,被选中用于替换原有的PHP后台系统,以更好地对接Java Dubbo服务...

    Dubbo-go技术实践分享.pdf

    【Dubbo-go技术实践分享】 本文主要探讨了在IT行业中,如何使用Dubbo-go这一Go语言版本的Dubbo实现服务间通信,特别是在构建高可用网关时的技术实践。选择Dubbo-go的原因在于它能无缝接入已有的Java业务集群,同时...

    dubbo泛化的简单应用

    实现Dubbo泛化调用的核心在于`GenericService`接口。这个接口提供了一个`$invoke`方法,允许我们传入任意的业务方法名和参数,然后由Dubbo框架负责在服务提供者端找到对应的方法并执行。这样,我们就可以摆脱预先...

    dubbo-用户指南.pdf

    - 泛化引用、泛化实现:允许不同服务之间的通用通信,增加了 Dubbo 的互操作性。 - 异步调用、本地存根、本地伪装:提供了异步处理能力和本地代理,以提升性能和用户体验。 - 并发控制、连接控制:为服务调用提供了...

    dubbo示例demo

    4. **服务调用方式**:包括同步调用、异步调用、泛化调用等多种调用方式,以及它们的适用场景。 5. **服务过滤器和服务拦截器**:如何自定义和使用这些组件以增强服务功能,比如日志记录、性能监控等。 6. **负载...

    基于groovy实现 java脚本动态编译、部署、发布;可以通过脚本直接调用dubbo接口.zip

    本文将深入探讨如何基于Groovy实现Java脚本的动态编译、部署和发布,并且介绍如何通过Groovy脚本直接调用Dubbo接口,从而提高开发效率和灵活性。 Groovy是一种基于Java平台的强大的动态编程语言,它具有简洁的语法...

    dubbo-master.zip

    2. **服务调用方式**:异步调用、泛化调用、集群容错等,提供了灵活的服务调用方式。 3. **监控与调优**:Dubbo Admin是Dubbo提供的管理控制台,可以查看服务状态、调用统计等信息,辅助进行系统调优。 4. **服务...

    dubbo-demo

    - **服务调用**:学习 Consumer 如何通过 Dubbo 进行远程调用(RPC),包括异步调用、泛化调用等方式。 - **服务监控**:查看如何开启服务的监控,如统计调用次数、耗时等,以便于系统性能的监控和优化。 通过这个 ...

    dubbo samples

    2. **服务消费者(Consumer)**:演示如何在应用中消费远程服务,包括同步调用、异步调用、泛化调用等不同方式。 3. **注册与发现**:如何配置服务注册到Zookeeper、Eureka等注册中心,并实现服务发现机制。 4. **...

    dubbo中文文档说明

    ### Dubbo中文文档知识点...综上所述,Dubbo是一款功能强大的服务框架,其提供的丰富特性和工具能够帮助开发者轻松构建复杂的分布式系统。通过深入理解Dubbo的原理和实践,开发者可以更加高效地进行服务的设计与实现。

    dubbo开发者文档

    - **泛化引用与泛化实现**: 使得非Java语言也能调用Java的Dubbo服务。 - **回声测试**: 用于测试服务是否存活。 - **上下文信息、隐式参数、异步调用、本地调用、参数回调、事件通知**: 这些功能为开发者提供了更...

    Dubbo课程资源09240924

    Dubbo提供了接口调用、泛化调用等多种调用方式,其中接口调用是基于Java的接口实现,而泛化调用则允许用户直接通过URL调用服务,无需预先定义接口。 6. **服务容错** 针对服务异常情况,Dubbo提供了多种容错机制...

    Dubbo入门到精通架构高级课程(视频+课件+源码)

    5. **服务调用方式**:了解同步调用、异步调用、泛化调用的实现与应用场景。 6. **协议与序列化**:分析Dubbo内置的多种通信协议(如Dubbo、HTTP、RMI等)以及数据序列化机制。 7. **服务治理**:探讨服务的元数据...

    Dubbo用户手册

    Dubbo用户手册从入门到实践,详细介绍了Dubbo框架的核心概念、使用方法、高级特性、以及最佳实践。通过这份手册,开发者可以快速掌握如何在自己的项目中使用Dubbo,构建出高性能、可扩展、易于维护的分布式服务架构...

Global site tag (gtag.js) - Google Analytics