引言

当后端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. NodeJS安装第一个工程

    一.刚接触Node.js,下载好安装包后,一路Next,安装好后,结构目录如下 在命令行窗口输入node -v 和npm -v 二.建立一个Node.js工程 1.(控制台窗口)全局安装了expres ...

  2. Java 脚本化编程指南

    Java 脚本化编程指南 Java脚本化API为谁准备? 脚本语言的一些有用的特性是: 方便:大多数脚本语言都是动态类型的.您通常可以创建新的变量,而不声明变量类型,并且您可以重用变量来存储不同类型的 ...

  3. c语言项目开发流程一部曲

    一.c项目开发总体分如下图所示 二.对每一步的解析 1.需求文档分析,本例以电子词典作为例子 列出每一个需求以及每一个需求的每一个特点,将其归纳 为一张表. 2.设计数据结构 设计数据结构,也就是确定 ...

  4. iOS storyBoard中tableViewCell传值方法

    一般在storyboard中传值通过identifier的值来控制segue的跳转和传值,但是,如果在tableView中,由于cell特别多,不可能创建n个identifier标识符,这里通过NSI ...

  5. javaWeb学习总结(11)- 监听器(Listener)在开发中的应用

    监听器在JavaWeb开发中用得比较多,下面说一下监听器(Listener)在开发中的常见应用 一.统计当前在线人数 在JavaWeb应用开发中,有时候我们需要统计当前在线的用户数,此时就可以使用监听 ...

  6. 关于Laravel中的artisan命令

    p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 14.0px Helvetica; color: #454545 } p.p2 { margin: 0.0p ...

  7. xampp教程(一):xampp下载,安装,配置,运行PHP的web项目

    本来没有想着弄PHP,但是有同学叫我帮忙启动一下一个PHP写的后台.着实需要去学习一下. 想着安装xampp软件,一个集合了多个服务器,多个数据库,多个后台语言的管理软件. 一.xampp下载 二.安 ...

  8. spring异常处理器

    一.本篇文章旨在讨论异常处理器: 1.因为异常处理器在实战中通常用来处理开发人员自定义的运行时异常,所以如果要了解如何自定义运行时异常,请自行搜索相关资料. 2.本文的demo用IndexOutOfB ...

  9. nodejs 开发指南 书中小项目 代码

    最近 在学习node.js 先看了下语法 ,然后就看这个开发指南感觉书还是很有用,但是代码太旧了,网上也没有最新的,所以就自己查着前人的痕迹和自己修改,现在可以跑了. https://github.c ...

  10. eclipse 创建maven 项目 动态web工程报错

    Eclipse 创建maven 项目 动态web工程 注:Eclipse版本为(Version: Mars.1 Release (4.5.1))maven版本为(apache-maven-3.3.9) ...