引言

当后端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 高级特性实践-泛化调用的更多相关文章

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

    引言 当后端Java服务用Dubbo协议作为RPC方案的基础,但部分消费方是前端Restful的PHP服务,不能直接调用,于是在中间架设了Router服务提供统一的基于HTTP的后端调用入口. 而Ro ...

  2. Dubbo基本特性之泛化调用

    Dubbo 是支持泛化调用的,什么是泛化调用呢?泛化调用的好处是什么呢,泛化调用说白一点就是服务消费者并没有服务的接口. 在<Dubbo入门-搭建一个最简单的Demo框架>一文中,我们已完 ...

  3. 小甜点,RecyclerView 之 ItemDecoration 讲解及高级特性实践

    本篇文章摘自微信公众号 guolin_blog (郭霖)独家发布 毫无疑问,RecyclerView 是现在 Android 世界中最重要的系统组件之一,它的出现就是为了高效代替 ListView 和 ...

  4. paip。java 高级特性 类默认方法,匿名方法+多方法连续调用, 常量类型

    paip.java 高级特性 类默认方法,匿名方法+多方法连续调用, 常量类型 作者Attilax 艾龙,  EMAIL:1466519819@qq.com 来源:attilax的专栏 地址:http ...

  5. 《深入理解Java虚拟机:JVM高级特性与最佳实践》【PDF】下载

    <深入理解Java虚拟机:JVM高级特性与最佳实践>[PDF]下载链接: https://u253469.pipipan.com/fs/253469-230062566 内容简介 作为一位 ...

  6. Spark Streaming高级特性在NDCG计算实践

    从storm到spark streaming,再到flink,流式计算得到长足发展, 依托于spark平台的spark streaming走出了一条自己的路,其借鉴了spark批处理架构,通过批处理方 ...

  7. Redis进阶实践之五Redis的高级特性(转载 5)

    Redis进阶实践之五Redis的高级特性 一.引言 上一篇文章写了Redis的特征,使用场景,同时也介绍了Redis的基本数据类型,redis的数据类型是操作redis的基础,这个必须好好的掌握.今 ...

  8. Dubbo学习笔记4:服务消费端泛化调用与异步调用

    本文借用dubbo.learn的Dubbo API方式来解释原理. 服务消费端泛化调用 前面我们讲解到,基于Spring和基于Dubbo API方式搭建简单的分布式系统时,服务消费端引入了一个SDK二 ...

  9. 《PHP对象、模式与实践》之高级特性

    高级特性包括:1.静态方法和属性(通过类而不是对象来访问数据和功能)2.抽象类和接口(设计,实现分离)3.错误处理(异常)4.Final类和方法(限制继承)5.拦截器(自动委托)6.析构方法(对象销毁 ...

随机推荐

  1. ESXi6.5上的Ubuntu虚机在远程SSH时宕机

    情况是这样的, 有一个ESXi6.5上跑的Ubuntu虚机, 版本是18.04.1, 今天升级成18.04.2后, 就发现远程连接SSH不对劲, 在本地登录和操作都好好的, 只要远程SSH一连接, 服 ...

  2. Arcgis案例操作教程——去掉Z值和M值

    Arcgis案例操作教程--去掉Z值和M值 商务合作,科技咨询,版权转让:向日葵,135-4855__4328,xiexiaokui#qq.com 处理前 处理后: 处理方法     商务合作,科技咨 ...

  3. Linux_CentOS中的MySQL 数据库的安装调试、远程管理

    官网查看最新 MySQL 安装包 https://dev.mysql.com/downloads/repo/yum/ 下载 MySQL 源的安装包 wget http://dev.mysql.com/ ...

  4. nfs高可用

      一.简介 NFS是单点的,如果一个节点出现问题,那使用它挂载服务的都将出现问题.所以需要高可用,挂掉一台不影响.采用keepalived+rsync+inotify-tools 环境: ubunt ...

  5. Laya自定义组件

    laya2.1.1.1 参考: 预设使用 一 没有自定义组件 教程翻了几遍,没有自定义组件,论坛搜了下,说是不能使用. 二 预置件做自定义组件 预置件无法右键创建. 又去翻教程.终于知道预置件怎么创建 ...

  6. PP篇10 修改工单组件行

    CO_XT_COMPONENT_CHANGE 修改工单组件行 DATA : is_order_key TYPE coxt_ord_key, is_order_component_key TYPE co ...

  7. [LeetCode] 65. Valid Number 验证数字

    Validate if a given string can be interpreted as a decimal number. Some examples:"0" => ...

  8. GenericObjectPool

    commons-pool2源码走读(四) 对象池实现GenericObjectPool 2018年05月27日 18:24:56 蓝墨49 阅读数 1787   版权声明:本文为博主原创文章,遵循CC ...

  9. python爬虫4猫眼电影的Top100

    1 查看网页结构 (1)确定需要抓取的字段 电影名称 电影主演 电影上映时间 电影评分 (2) 分析页面结构 按住f12------->点击右上角(如下图2)---->鼠标点击需要观察的字 ...

  10. WordPress概览

    "绝望是一种罪过"-------------------------<老人与海> WordPress 是世界上使用最广泛的博客系统,是一款开源的PHP软件,在GNU通用 ...