引言

当后端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. 4、Swing在JPanel中添加背景图片方法

    4.Jpanel面板中加载背景图片 在实际应用Java做界面的过程中,常常会涉及到加载背景图片以使页面美化.下面整理了一个小模块以便于调用. 1 package com.tntxia.commonsw ...

  2. (基础篇 走进javaNIO)第二章-NIO入门

    在本章巾,我们会分别对 JDK 的BIO ,NIO 和JDK 1.7 最新提供的 NI02.0的使用进行详细说明 ,通过流程图和代 码讲解,让大 家体会到随着 Ja va 1/0 类库的 不断发展和改 ...

  3. Hibernate SQLQuery 原生SQL 查询及返回结果集处理-1

    第一篇:官方文档的处理方法,摘自官方 在迁移原先用JDBC/SQL实现的系统,难免需要采用hibernat native sql支持. 1.使用SQLQuery hibernate对原生SQL查询执行 ...

  4. OpenStack(企业私有云)万里长征第二步——使用Fuel部署

    一.前言 最近一直在使用DevStack来安装OpenStack,注意一直二字,部署了一遍又一遍,操作系统怕是安装了不下上百次,有时是为了验证新的方案,有时是安装出错,还有时是运行过程中出错.总之是碰 ...

  5. IPad分屏,当电脑第二显示屏

    最在在网上看到使用IPad可以做为电脑的第二个显示屏,对于我这样一个程序猿来说,这真是我的福音呀!因此在网上搜了许多关于Ipad投屏的信息,下面简单说明一下,包括怎么使用! 1.根据在网上搜索的结果, ...

  6. PHP基础入门(一)---世界上最好用的编程语言

    作为一名程序员,我们应该都听过这样一个梗:PHP编程语言,是世界上最好用的编程语言~~~下面来和大家看一下,什么是PHP↓↓↓ PHP PHP又名超文本预处理器,是一种通用开源脚本语言.PHP主要适用 ...

  7. php系统共享模板问题

    我们在用php+html+css来写一个管理系统时,例如报名系统.投票系统,统计系统等,我们往往需要在管理后台查看每一位报名者的情况,问题接着就来了,由于比赛或者活动要求不同个,往往报名表不太一样,这 ...

  8. 数据库MySQL安装和校验

    1.安装MySQL 双击已经下载的安装包: Typical:典型安装,第一次安装建议选择该类安装 Custom:自定义安装,在对数据库熟悉后,知道自己需要哪些组件时,可以选择该类安装(这里选择的是自定 ...

  9. SQLalchemy模块用法

    安装 pip install sqlalchemy #!/usr/bin/env python # -*- coding:utf-8 -*- # 加载模块 from sqlalchemy.ext.de ...

  10. 如何动态加载js文件,$.getScript()方法的使用

    有时候我们需要动态在页面中加载js文件,jquery封装了getScript()方法,不用自己再创建标签了. 写法: $.getScript("name.js",function( ...