我是靠谱客的博主 鳗鱼夏天,最近开发中收集的这篇文章主要介绍soul网关-16-dubbo插件,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

soul网关有divide插件可以进行http的代理,它还有dubbo插件可以进行dubbo服务的代理。dubbo插件的作用就是将用户的http请求转换成dubbo调用。

运行soul网关的dubbo插件

我们先来试一下soul网关的dubbo插件。首先启动soul-admin,并在soul-admin管理后台里面开启dubbo插件

在这里插入图片描述

然后启动soul-examples-apache-dubbo-service示例项目,启动前先确保该示例项目的spring-dubbo.xml配置文件里的注册中心可以连接。该示例项目默认是使用zookeeper,关于zookeeper的安装和运行,我在之前的数据同步机制之zookeeper里面已经介绍过。

示例项目启动成功之后,可以在soul-admin管理后台看到dubbo插件里面已经有selector和rule添加进来了。

在这里插入图片描述

然后我们启动soul网关soul-bootstrap,启动之前,确保pom.xml里面有以下依赖:

        <dependency>
            <groupId>org.dromara</groupId>
            <artifactId>soul-spring-boot-starter-plugin-apache-dubbo</artifactId>
            <version>${project.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo</artifactId>
            <version>2.7.5</version>
        </dependency>

        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-client</artifactId>
            <version>4.0.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-framework</artifactId>
            <version>4.0.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-recipes</artifactId>
            <version>4.0.1</version>
        </dependency>

soul-bootstrap启动成功之后,我们就可以在浏览器里面试一下,看下是否能够成功调用dubbo服务

在这里插入图片描述


dubbo简介

当我们的业务拆分成多个微服务的时候,服务间相互调用的时候都有序列化、反序列化、超时处理、状态机等需求,如果每个服务都自己实现一套,那么太浪费人力了,所以产生了服务框架的概念。

dubbo就是根据该需求产生的一个RPC框架。

首先我们来简单了解一下dubbo。先看一下dubbo的架构图

在这里插入图片描述

看一下官网关于架构图的说明:

节点角色说明
Provider暴露服务的服务提供方
Consumer调用远程服务的服务消费方
Registry服务注册与发现的注册中心
Monitor统计服务的调用次数和调用时间的监控中心
Container服务运行容器

调用关系说明:

  1. 服务容器负责启动,加载,运行服务提供者。
  2. 服务提供者在启动时,向注册中心注册自己提供的服务。
  3. 服务消费者在启动时,向注册中心订阅自己所需的服务。
  4. 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
  5. 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
  6. 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心

上方我们已经过dubbo的架构有了基本的了解。在我们平常的spring项目中,不管是provider还是consumer接入dubbo都是很容易的。但是对于consumer来说,需要知道你要调用的服务的函数名、参数、返回类型等。

soul网关的dubbo插件既然是起到代理dubbo服务的功能,那么soul网关就可以看做是一个consumer,但是它作为consumer不可能在项目里面生成每个service的bean,所以它需要有个机制在知道service名字、参数、返回值的情况下可以统一地广泛的调用dubbo服务。

正好dubbo中提供了这样一个机制——-泛化调用。先来粗略的浏览一下apache dubbo官方文档关于泛化调用的介绍。

可以了解到,GenericService是Dubbo提供的泛化接口,用来进行泛化调用。

GenericService接口里面有下面这个方法,可以发起调用:

Object $invoke(String var1, String[] var2, Object[] var3) throws GenericException;

从apache dubbo官方的文档里面的关于泛化调用的示例代码中,可以看到几个关键的代码:

  • ReferenceConfig<GenericService> reference
  • GenericService genericService = reference.get();
  • genericService.$invoke

soul网关dubbo插件是如何代理dubbo服务的

好了,我们现在就来看下soul网关的dubbo插件,去soul-plugin-apache-dubbo下面看一下ApacheDubboPlugin.java

ApacheDubboPlugin也是继承了AbstractSoulPlugin类,那我们直接看它的doExecute方法,里面的主要逻辑是:

  • 从exchange中取出metaData,并判断metaData是否合法
  • 判断metaData中是否有存储参数类型,与当前请求的body进行比较。如果一个不为空,一个为空,则该请求缺少参数
  • 调用了ApacheDubboProxyService.genericInvoker方法,调用后端dubbo服务,获取返回值
  • 执行插件链上的下一个插件
    @Override
    protected Mono<Void> doExecute(final ServerWebExchange exchange, final SoulPluginChain chain, final SelectorData selector, final RuleData rule) {
        String body = exchange.getAttribute(Constants.DUBBO_PARAMS);
        SoulContext soulContext = exchange.getAttribute(Constants.CONTEXT);
        assert soulContext != null;
        MetaData metaData = exchange.getAttribute(Constants.META_DATA);
        if (!checkMetaData(metaData)) {
            assert metaData != null;
            log.error(" path is :{}, meta data have error.... {}", soulContext.getPath(), metaData.toString());
            exchange.getResponse().setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR);
            Object error = SoulResultWrap.error(SoulResultEnum.META_DATA_ERROR.getCode(), SoulResultEnum.META_DATA_ERROR.getMsg(), null);
            return WebFluxResultUtils.result(exchange, error);
        }
        if (StringUtils.isNoneBlank(metaData.getParameterTypes()) && StringUtils.isBlank(body)) {
            exchange.getResponse().setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR);
            Object error = SoulResultWrap.error(SoulResultEnum.DUBBO_HAVE_BODY_PARAM.getCode(), SoulResultEnum.DUBBO_HAVE_BODY_PARAM.getMsg(), null);
            return WebFluxResultUtils.result(exchange, error);
        }
        final Mono<Object> result = dubboProxyService.genericInvoker(body, metaData, exchange);
        return result.then(chain.execute(exchange));
    }

那么整个dubbo插件的最关键的地方就是在ApacheDubboProxyService.genericInvoker方法里面了,我们来看下这个方法:

在这里插入图片描述

可以看到几个划线的关键的地方,正是我们上面分析的dubbo泛化调用的几个关键步骤。

上面看的是soul-plugin-apache-dubbo,下面来看下soul-plugin-alibaba-dubbo这个插件的AlibabaDubboProxyService.genericInvoker方法

在这里插入图片描述

可以看到几个泛化调用的关键步骤都在,大致是和soul-plugin-apache-dubbo差不多的。

至此,我们已经大致了解了soul网关的dubbo插件是如何实现dubbo服务代理的。后续有时间要深入研究一下泛化调用的原理。

最后

以上就是鳗鱼夏天为你收集整理的soul网关-16-dubbo插件的全部内容,希望文章能够帮你解决soul网关-16-dubbo插件所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(62)

评论列表共有 0 条评论

立即
投稿
返回
顶部