Dubbo高级特性实践-泛化调用
引言
当后端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高级特性实践-泛化调用的更多相关文章
- Dubbo 高级特性实践-泛化调用
引言 当后端Java服务用Dubbo协议作为RPC方案的基础,但部分消费方是前端Restful的PHP服务,不能直接调用,于是在中间架设了Router服务提供统一的基于HTTP的后端调用入口. 而Ro ...
- Dubbo基本特性之泛化调用
Dubbo 是支持泛化调用的,什么是泛化调用呢?泛化调用的好处是什么呢,泛化调用说白一点就是服务消费者并没有服务的接口. 在<Dubbo入门-搭建一个最简单的Demo框架>一文中,我们已完 ...
- 小甜点,RecyclerView 之 ItemDecoration 讲解及高级特性实践
本篇文章摘自微信公众号 guolin_blog (郭霖)独家发布 毫无疑问,RecyclerView 是现在 Android 世界中最重要的系统组件之一,它的出现就是为了高效代替 ListView 和 ...
- paip。java 高级特性 类默认方法,匿名方法+多方法连续调用, 常量类型
paip.java 高级特性 类默认方法,匿名方法+多方法连续调用, 常量类型 作者Attilax 艾龙, EMAIL:1466519819@qq.com 来源:attilax的专栏 地址:http ...
- 《深入理解Java虚拟机:JVM高级特性与最佳实践》【PDF】下载
<深入理解Java虚拟机:JVM高级特性与最佳实践>[PDF]下载链接: https://u253469.pipipan.com/fs/253469-230062566 内容简介 作为一位 ...
- Spark Streaming高级特性在NDCG计算实践
从storm到spark streaming,再到flink,流式计算得到长足发展, 依托于spark平台的spark streaming走出了一条自己的路,其借鉴了spark批处理架构,通过批处理方 ...
- Redis进阶实践之五Redis的高级特性(转载 5)
Redis进阶实践之五Redis的高级特性 一.引言 上一篇文章写了Redis的特征,使用场景,同时也介绍了Redis的基本数据类型,redis的数据类型是操作redis的基础,这个必须好好的掌握.今 ...
- Dubbo学习笔记4:服务消费端泛化调用与异步调用
本文借用dubbo.learn的Dubbo API方式来解释原理. 服务消费端泛化调用 前面我们讲解到,基于Spring和基于Dubbo API方式搭建简单的分布式系统时,服务消费端引入了一个SDK二 ...
- 《PHP对象、模式与实践》之高级特性
高级特性包括:1.静态方法和属性(通过类而不是对象来访问数据和功能)2.抽象类和接口(设计,实现分离)3.错误处理(异常)4.Final类和方法(限制继承)5.拦截器(自动委托)6.析构方法(对象销毁 ...
随机推荐
- 利用JavaScript数组动态写入HTML数据节点
如果想要使用数组来写入HTML数据,绝对需要的是一个Key值,由Key来引导遍历数组各项:此外,使用DOM原生方法写入文档,用同一个CSS样式渲染它们,这样可以极大地减少开发时间和减少维护成本,此方法 ...
- 关于JS的return false
之前真的不知道JS里的return false 还能跳出事件. 今天在修改BUG的时候,用到了这个,就去查了一下,为了加深记忆在此处做个总结. retrun true: 返回正确的处理结果. retu ...
- Js判断是否是直接进入本页面的
今天带来一个Js的小示例,用来判断当前页面的链接来路.很多人应该可以用到,这个虽然非常简单,但是用到的地方却还是挺多的 首先新建一个index.html,代码如下 <!DOCTYPE html& ...
- es6之Generator
1.Generator函数其实是一个封装了多个内部状态的状态机,执行它会返回一个遍历器对象,然后可以依次遍历Generator中的每一个状态,也就是分段执行,yield是暂停执行的标记,next恢复执 ...
- ASP.NET Core:使用EntityFrameworkCore操作MySql来丰富仓储模块
概述 上一篇简单介绍了Dapper的基本用法,数据的存储为SqlServer.那么这一篇就记录一下使用EFCore来操作MySql的一些方式,这种模式比较适合那种一个项目中需要操作多种数据库的模式.不 ...
- 为什么说上ERP找死?
长期以来,管理软件领域流行着这样一句话“不上ERP等死,上了ERP找死”.根据为十九年管理软件开发的经验来看,“不上ERP等死”这句话不敢苟同,但“上了ERP找死”这句话倒有些同感.上ERP虽然不一定 ...
- linux下部署php项目-Apache、php、mysql关联
linux下部署php项目环境可以分为两种,一种使用Apache,php,mysql的压缩包安装,一种用yum命令进行安装. 使用三种软件的压缩包进行安装,需要手动配置三者之间的关系.apache和p ...
- JavaScript设计模式_03_代理模式
代理模式是非常常见的模式,比如我们使用的VPN工具,明星的经纪人,都是代理模式的例子.但是,有人会疑问,明明可以直接访问对象,为什么中间还要加一个壳呢?这也就说到了代理模式的好处.在我看来,代理模式最 ...
- [github项目]基于百度地图二次开发实现的车辆监管(包含车辆定位、车辆图片和方向控制,电子围栏,图形绘制等功能)前端实现(不包含后端实现)
前言:基于百度地图javascript版本开发,百度地图中所用的key已承诺仅用于测试,不用于商业用途 注:本文所有代码可以到github上进行下载,github地址:http://map.eguid ...
- linux系统中的删除操作
#rm [-fir] 文件或者目录 参数: -f:就是force的意思,忽略不存在的文件,不会出现警告信息: -i:互动模式,在删除前会询问用户是否操作: -r:递归删除.最常用的在目录删除.这是一个 ...