微服务框架(四)Dubbo泛化调用实现

简介:   此系列文章将会描述Java框架Spring Boot、服务治理框架Dubbo、应用容器引擎Docker,及使用Spring Boot集成Dubbo、Mybatis等开源框架,其中穿插着Spring Boot中日志切面等技术的实现,然后通过gitlab-CI以持续集成为Docker镜像。   本文为服务治理框架Dubbo泛化调用的实现

  此系列文章将会描述Java框架Spring Boot、服务治理框架Dubbo、应用容器引擎Docker,及使用Spring Boot集成Dubbo、Mybatis等开源框架,其中穿插着Spring Boot中日志切面等技术的实现,然后通过gitlab-CI以持续集成为Docker镜像。
  本文为服务治理框架Dubbo泛化调用的实现

本系列文章中所使用的框架版本为Spring Boot 2.0.3-RELEASE,Spring 5.0.7-RELEASE,Dubbo 2.6.2。

泛化调用组件

Dubbo一般在内部系统间,通过RPC调用,正常情况下服务消费方需要导入服务提供skeleton的jar包,根据此接口编写服务消费者

为了便于开发及测试,实现泛化调用功能,即使用Controller封装请求,获取对应的服务,转接为RPC调用

泛化调用组件依赖需添加对应服务接口的jar包

控制器

1.获取泛化服务接口
2.组装服务调用参数
3. 调用接口、封装数据

@RestController
@RequestMapping(value = "/")
public class GenericController {
   
   

    @RequestMapping(value = "/generic", consumes = MediaType.APPLICATION_JSON_UTF8_VALUE,
            produces = MediaType.APPLICATION_JSON_UTF8_VALUE,
            method = {
   
   RequestMethod.POST, RequestMethod.GET})
    @ResponseBody
    public Object call(@ModelAttribute("reqModel") GenericReqModel reqModel) throws ClassNotFoundException {
   
   
        Object result = null;

        // 1.获取泛化服务接口
        GenericService service = DubboUtils.fetchGenericService(reqModel);

        // 2.组装调用参数
        String method = reqModel.getMethod();

        String[] parameterTypes = DubboUtils.getMethodParamType(
                reqModel.getService(), reqModel.getMethod());

        Object[] args = JSON.parseArray(reqModel.getParamValues()).toArray(
                new Object[] {
   
   });

        // 3.调用接口
        return JSON.toJSONString(service
                .$invoke(method, parameterTypes, args));
    }

}

泛化引用接口

Dubbo支持的泛化引用接口,可通过在 Spring Boot 配置申明 generic="true"使用,详见泛化引用

在此组件中无需配置即可使用

xml

<dubbo:reference id="barService" interface="com.foo.BarService" generic="true" />

Properties

dubbo.reference.generic = true

接口定义:

package com.alibaba.dubbo.rpc.service;

/**
 * Generic service interface
 *
 * @export
 */
public interface GenericService {
   
   

    /**
     * Generic invocation
     *
     * @param method         Method name, e.g. findPerson. If there are overridden methods, parameter info is
     *                       required, e.g. findPerson(java.lang.String)
     * @param parameterTypes Parameter types
     * @param args           Arguments
     * @return invocation return value
     * @throws Throwable potential exception thrown from the invocation
     */
    Object $invoke(String method, String[] parameterTypes, Object[] args) throws GenericException;

}

工具类

DubboUtils:

  1. fetchGenericService:获取泛化引用接口(如有缓存, 则从缓存取)
  2. getMethodParamType:根据接口类名及方法名通过反射获取参数类型
public class DubboUtils {
   
   

    private static Logger logger = LoggerFactory.getLogger(DubboUtils.class);

    private static ApplicationConfig application = new ApplicationConfig(
            "generic-reference");

    private static Map<String, GenericService> serviceCache = Maps.newConcurrentMap();

    /**
     * 获取泛化服务接口(如有缓存, 则从缓存取)
     * @param reqModel
     * @return
     */
    public static GenericService fetchGenericService(GenericReqModel reqModel) {
   
   
        // 参数设置
        String serviceInterface = reqModel.getService();
        String serviceGroup = reqModel.getGroup();
        String serviceVersion = reqModel.getVersion();

        // 从缓存中获取服务
        String serviceCacheKey = serviceInterface + "-" + serviceGroup + "-"
                + serviceVersion;
        GenericService service = serviceCache.get(serviceCacheKey);
        if (service != null) {
   
   
            logger.info("fetched generic service from cache");
            return service;
        }

        // 配置调用信息
        ReferenceConfig<GenericService> reference = new ReferenceConfig<GenericService>();
        reference.setApplication(application);
        reference.setInterface(serviceInterface);
        reference.setGroup(serviceGroup);
        reference.setVersion(serviceVersion);
        reference.setGeneric(true); // 声明为泛化接口

        // 获取对应服务
        service = reference.get();

        // 缓存
        serviceCache.put(serviceCacheKey, service);

        return service;
    }

    /**
     * 根据接口类名及方法名通过反射获取参数类型
     * 
     * @param interfaceName 接口名
     * @param methodName    方法名
     * @return
     * @throws ClassNotFoundException
     */
    public static String[] getMethodParamType(String interfaceName,
            String methodName) throws ClassNotFoundException {
   
   
        String[] paramTypeList = null;

        // 创建类
        Class<?> clazz = Class.forName(interfaceName);
        // 获取所有的公共的方法
        Method[] methods = clazz.getMethods();
        for (Method method : methods) {
   
   
            if (method.getName().equals(methodName)) {
   
   

                Class<?>[] paramClassList = method.getParameterTypes();
                paramTypeList = new String[paramClassList.length];

                int i = 0;
                for (Class<?> className : paramClassList) {
   
   
                    paramTypeList[i] = className.getTypeName();
                    i++;
                }
                break;
            }
        }

        return paramTypeList;
    }
}

启动器

若要使用不同的Web容器,需引入对应的Spring Boot启动依赖,e.g

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jetty</artifactId>
    <version>2.0.3.RELEASE</version>
</dependency>

项目使用Web容器启动

@SpringBootApplication(scanBasePackages = "com.spring.boot.generic.controller")
public class Starter {
   
   

    public static void main(String[] args) {
   
   

        new SpringApplicationBuilder(Starter.class)
            .web(WebApplicationType.SERVLET)
            .run(args);

    }

}

请求模型

public class GenericReqModel implements Serializable {
   
   

    /**
     * 
     */
    private static final long serialVersionUID = -7389007812411509827L;

    private String registry; // 注册中心地址
    private String service; // 服务包下类名
    private String version; // 版本
    private String group; // 服务组
    private String method; // 方法名
    private String paramTypes; // 参数类型
    private String paramValues; // 参数值

    setter/getter
}

POSTMAN使用方法

1.Headers配置

Key Value
Content-Type application/json

2.参数配置(Params)

Key Value
registry zookeeper://localhost
service
version 1.0.0
group
method getWord
paramValues [{}]

3.调用示例

在这里插入图片描述


源码:GitHub

相关文章
|
22天前
|
Dubbo Java 应用服务中间件
💥Spring Cloud Dubbo火爆来袭!微服务通信的终极利器,你知道它有多强大吗?🔥
【8月更文挑战第29天】随着信息技术的发展,微服务架构成为企业应用开发的主流模式,而高效的微服务通信至关重要。Spring Cloud Dubbo通过整合Dubbo与Spring Cloud的优势,提供高性能RPC通信及丰富的生态支持,包括服务注册与发现、负载均衡和容错机制等,简化了服务调用管理并支持多种通信协议,提升了系统的可伸缩性和稳定性,成为微服务通信领域的优选方案。开发者仅需关注业务逻辑,而无需过多关心底层通信细节,使得Spring Cloud Dubbo在未来微服务开发中将更加受到青睐。
45 0
|
6天前
|
负载均衡 Dubbo NoSQL
Dubbo框架的1个核心设计点
Java领域要说让我最服气的RPC框架当属Dubbo,原因有许多,但是最吸引我的还是它把远程调用这个事情设计得很有艺术。
Dubbo框架的1个核心设计点
|
17天前
|
Dubbo Java 应用服务中间件
微服务框架Dubbo环境部署实战
微服务框架Dubbo环境部署的实战指南,涵盖了Dubbo的概述、服务部署、以及Dubbo web管理页面的部署,旨在指导读者如何搭建和使用Dubbo框架。
68 17
微服务框架Dubbo环境部署实战
|
15天前
|
存储 Java Maven
从零到微服务专家:用Micronaut框架轻松构建未来架构
【9月更文挑战第5天】在现代软件开发中,微服务架构因提升应用的可伸缩性和灵活性而广受欢迎。Micronaut 是一个轻量级的 Java 框架,适合构建微服务。本文介绍如何从零开始使用 Micronaut 搭建微服务架构,包括设置开发环境、创建 Maven 项目并添加 Micronaut 依赖,编写主类启动应用,以及添加控制器处理 HTTP 请求。通过示例代码展示如何实现简单的 “Hello, World!” 功能,并介绍如何通过添加更多依赖来扩展应用功能,如数据访问、验证和安全性等。Micronaut 的强大和灵活性使你能够快速构建复杂的微服务系统。
39 5
|
14天前
|
缓存 Java 应用服务中间件
随着微服务架构的兴起,Spring Boot凭借其快速开发和易部署的特点,成为构建RESTful API的首选框架
【9月更文挑战第6天】随着微服务架构的兴起,Spring Boot凭借其快速开发和易部署的特点,成为构建RESTful API的首选框架。Nginx作为高性能的HTTP反向代理服务器,常用于前端负载均衡,提升应用的可用性和响应速度。本文详细介绍如何通过合理配置实现Spring Boot与Nginx的高效协同工作,包括负载均衡策略、静态资源缓存、数据压缩传输及Spring Boot内部优化(如线程池配置、缓存策略等)。通过这些方法,开发者可以显著提升系统的整体性能,打造高性能、高可用的Web应用。
43 2
|
15天前
|
Cloud Native 安全 Java
Micronaut对决Spring Boot:谁是微服务领域的王者?揭秘两者优劣,选对框架至关重要!
【9月更文挑战第5天】近年来,微服务架构备受关注,Micronaut和Spring Boot成为热门选择。Micronaut由OCI开发,基于注解的依赖注入,内置多种特性,轻量级且启动迅速;Spring Boot则简化了Spring应用开发,拥有丰富的生态支持。选择框架需考虑项目需求、团队经验、性能要求及社区支持等因素。希望本文能帮助您选择合适的微服务框架,助力您的软件开发项目取得成功!
59 2
|
24天前
|
Cloud Native JavaScript API
一文读懂云原生 go-zero 微服务框架
一文读懂云原生 go-zero 微服务框架
|
1月前
|
开发框架 Dubbo 应用服务中间件
微服务开发框架-----Apache Dubbo
这篇文章介绍了Apache Dubbo微服务开发框架,它提供RPC通信和微服务治理能力,支持服务发现、负载均衡和流量治理等功能,并强调了Dubbo在微服务规模化实践和企业级治理方面的优势。
微服务开发框架-----Apache Dubbo
|
1月前
|
缓存 负载均衡 监控
Dubbo框架整体认知
该文章主要介绍了Dubbo框架的整体认知,包括Dubbo的概念、产生的背景、解决的问题、架构以及功能特性等。
Dubbo框架整体认知
|
1月前
|
负载均衡 Dubbo 应用服务中间件
框架巨擘:Dubbo如何一统异构微服务江湖,成为开发者的超级武器!
【8月更文挑战第8天】在软件开发中,微服务架构因灵活性和可扩展性备受欢迎。面对异构微服务的挑战,Apache Dubbo作为高性能Java RPC框架脱颖而出。它具备服务注册与发现、负载均衡及容错机制等核心特性,支持多种通信协议和序列化方式,能有效连接不同技术栈的微服务。Dubbo的插件化设计保证了面向未来的扩展性,使其成为构建稳定高效分布式系统的理想选择。
35 5