关于apache:Apache-ShenYu-网关正式支持-Dubbo3-服务代理

55次阅读

共计 9593 个字符,预计需要花费 24 分钟才能阅读完成。

简介:本文介绍了如何通过 Apache ShenYu 网关拜访 Dubbo 服务,次要内容包含从简略示例到外围调用流程剖析,并对设计原理进行了总结。
作者:刘良

Apache Dubbo 在去年公布了下一代的云原生微服务版本 Dubbo3,目前最新版本 Dubbo3 已在阿里经济体实现对 HSF2 框架的全面替换与降级,Dubbo3 目前已成为社区企业实际举荐版本。Apache Shenyu 网关在这个背景下公布了对 Dubbo3 服务代理的反对。

本文介绍了如何通过 Apache ShenYu 网关拜访 Dubbo 服务,次要内容包含从简略示例到外围调用流程剖析,并对设计原理进行了总结。

1.png

介绍

Apache ShenYu

2.png

Apache ShenYu(Incubating)是一个异步的,高性能的,跨语言的,响应式的 API 网关。兼容各种支流框架体系,反对热插拔,用户能够定制化开发,满足用户各种场景的现状和将来需要,经验过大规模场景的锻炼。

2021 年 5 月,ShenYu 募捐给 Apache 软件基金会,Apache 基金会全票通过,顺利进入孵化器。

Apache Dubbo

Dubbo3 是下一代的云原生微服务框架,全面降级了包含下一代 RPC 协定、利用级服务发现、Dubbo Mesh、对立服务治理等外围能力,多语言 Java、Golang 同步公布 3.0 个性。目前最新版本 Dubbo3 已在阿里经济体实现对 HSF2 框架的全面替换与降级,包含阿里外围电商、阿里云、活饿了么、钉钉、考拉等都曾经全面降级 Dubbo3,2022 双 11 大促外围零碎将跑在 Dubbo3 之上,社区用户包含工商银行、小米、安全衰弱等也已胜利降级 Dubbo3 外围性能。

Dubbo 疾速开始

本大节介绍如何将 Dubbo 服务接入到 ShenYu 网关,您能够间接在工程下找到本大节的示例代码。

启动 shenyu-admin

shenyu-admin 是 Apache ShenYu 后盾管理系统,启动的形式有多种,本文通过本地部署的形式启动。启动胜利后,须要在根底配置 -> 插件治理中,把 dubbo 插件设置为开启,并设置你的注册地址,请确保注册核心曾经开启。

image.gif3.png

启动 shenyu 网关

在这里通过源码的形式启动,间接运行 shenyu-bootstrap 中的 ShenyuBootstrapApplication。

在启动前,请确保网关曾经引入相干依赖。如果客户端是 apache dubbo,注册核心应用 zookeeper,请参考如下配置:

<!– apache shenyu apache dubbo plugin start–>

    <dependency>
        <groupId>org.apache.shenyu</groupId>
        <artifactId>shenyu-spring-boot-starter-plugin-apache-dubbo</artifactId>
        <version>${project.version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.dubbo</groupId>
        <artifactId>dubbo</artifactId>
        <version>3.0.8</version>
    </dependency>
    <!-- Dubbo zookeeper registry dependency start -->
    <dependency>
        <groupId>org.apache.curator</groupId>
        <artifactId>curator-client</artifactId>
        <version>4.0.1</version>
        <exclusions>
            <exclusion>
                <artifactId>log4j</artifactId>
                <groupId>log4j</groupId>
            </exclusion>
        </exclusions>
    </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>
    <!-- Dubbo zookeeper registry dependency end -->
    <!-- apache dubbo plugin end-->

启动 shenyu-examples-dubbo

以官网提供的例子为例 shenyu-examples-dubbo。如果 dubbo 服务定义如下:

<beans /* …… * />

<dubbo:application name="test-dubbo-service"/>
<dubbo:registry address="${dubbo.registry.address}"/>
<dubbo:protocol name="dubbo" port="20888"/>

<dubbo:service timeout="10000" interface="org.apache.shenyu.examples.dubbo.api.service.DubboTestService" ref="dubboTestService"/>

</beans>

申明应用服务名称,注册核心地址,应用 dubbo 协定,申明服务接口,对应接口实现类:

/**

  • DubboTestServiceImpl.
    */

@Service(“dubboTestService”)
public class DubboTestServiceImpl implements DubboTestService {

@Override
@ShenyuDubboClient(path = "/findById", desc = "Query by Id")
public DubboTest findById(final String id) {return new DubboTest(id, "hello world shenyu Apache, findById");
}

//......

}

在接口实现类中,应用注解 @ShenyuDubboClient 向 shenyu-admin 注册服务。

在配置文件 application.yml 中的配置信息:

server:
port: 8011
address: 0.0.0.0
servlet:

context-path: /

spring:
main:

allow-bean-definition-overriding: true

dubbo:
registry:

address: zookeeper://localhost:2181  # dubbo 应用的注册核心

shenyu:
register:

registerType: http #注册形式
serverLists: http://localhost:9095 #注册地址
props:
  username: admin 
  password: 123456

client:

dubbo:
  props:
    contextPath: /dubbo  
    appName: dubbo

在配置文件中,申明 dubbo 应用的注册核心地址,dubbo 服务向 shenyu-admin 注册,应用的形式是 http,注册地址是 http://localhost:9095。对于注册形式的应用,请参考利用客户端接入。

调用 dubbo 服务

shenyu-examples-dubbo 我的项目胜利启动之后会主动把加 @ShenyuDubboClient 注解的接口办法注册到网关。

关上 插件列表 -> Proxy -> dubbo 能够看到插件规定配置列表:

4.pngimage.gif

注册胜利的选择器信息:

5.png

注册胜利的规定信息:

6.png

选择器和规定是 Apache ShenYu 网关中最灵魂的货色。把握好它,你能够对任何流量进行治理。对应为选择器与规定外面的匹配条件(conditions),依据不同的流量筛选规定,咱们能够解决各种简单的场景。流量筛选能够从 Header, URI, Query, Cookie 等等 Http 申请获取数据。

而后能够采纳 Match,=,Regex,Groovy,Exclude 等匹配形式,匹配出你所料想的数据。多组匹配增加能够应用 And/Or 的匹配策略。具体的介绍与应用请看: 选择器与规定治理。

发动 GET 申请,通过 ShenYu 网关调用 dubbo 服务:

GET http://localhost:9195/dubbo/f…
Accept: application/json

胜利响应之后,后果如下:

{
“name”: “hello world shenyu Apache, findById”,
“id”: “100”
}

至此,就胜利的通过 http 申请拜访 dubbo 服务了,ShenYu 网关通过 shenyu-plugin-dubbo 模块将 http 协定转成了 dubbo 协定。

深刻了解 Dubbo 插件

在运行上述 demo 的过程中,是否存在一些疑难:

dubbo 服务是如何注册到 shenyu-admin?
shenyu-admin 是如何将数据同步到 ShenYu 网关?
DubboPlugin 是如何将 http 协定转换到到 dubbo 协定?

带着这些疑难,来深刻了解 dubbo 插件。

利用客户端接入

利用客户端接入是指将微服务接入到 Apache ShenYu 网关,以后反对 Http、Dubbo、Spring Cloud、gRPC、Motan、Sofa、Tars 等协定的接入。

将利用客户端接入到 Apache ShenYu 网关是通过注册核心来实现的,波及到客户端注册和服务端同步数据。注册核心反对 Http、Zookeeper、Etcd、Consul 和 Nacos。默认是通过 Http 形式注册。

客户端接入的相干配置请参考客户端接入配置。

客户端注册

7.png

在你的微服务配置中申明注册核心客户端类型,如 Http 或 Zookeeper。应用程序启动时应用 SPI 形式加载并初始化对应注册核心客户端,通过实现 Spring Bean 相干的后置处理器接口,在其中获取须要进行注册的服务接口信息,将获取的信息放入 Disruptor 中。

注册核心客户端从 Disruptor 中读取数据,并将接口信息注册到 shenyu-admin,Disruptor 在其中起数据与操作解耦的作用,利于扩大。

服务端注册

8.png

在 shenyu-admin 配置中申明注册核心服务端类型,如 Http 或 Zookeeper。当 shenyu-admin 启动时,读取配置类型,加载并初始化对应的注册核心服务端,注册核心服务端收到 shenyu-client 注册的接口信息后,将其放入 Disruptor 中,而后会触发注册解决逻辑,将服务接口信息更新并公布同步事件。

Disruptor 在其中起到数据与操作解耦,利于扩大。如果注册申请过多,导致注册异样,也有数据缓冲作用。

数据同步原理

数据同步是指在 shenyu-admin 后盾操作数据当前,应用何种策略将数据同步到 Apache ShenYu 网关。Apache ShenYu 网关以后反对 ZooKeeper、WebSocket、Http 长轮询、Nacos、Etcd 和 Consul 进行数据同步。默认是通过 WebSocket 进行数据同步。

数据同步的相干配置请参考数据同步配置。

数据同步的意义

网关是流量申请的入口,在微服务架构中承当了十分重要的角色,网关高可用的重要性显而易见。在应用网关的过程中,为了满足业务诉求,常常须要变更配置,比方流控规定、路由规定等等。因而,网关动静配置是保障网关高可用的重要因素。

以后数据同步个性如下:

1、所有的配置都缓存在 Apache ShenYu 网关内存中,每次申请都应用本地缓存,速度十分快。

2、用户能够在 shenyu-admin 后盾任意批改数据,并马上同步到网关内存。

3、反对 Apache ShenYu 的插件、选择器、规定数据、元数据、签名数据等数据同步。

4、所有插件的选择器,规定都是动静配置,立刻失效,不须要重启服务。

5、数据同步形式反对 Zookeeper、Http 长轮询、Websocket、Nacos、Etcd 和 Consul。

数据同步原理剖析
下图展现了 Apache ShenYu 数据同步的流程,Apache ShenYu 网关在启动时,会从配置服务同步配置数据,并且反对推拉模式获取配置变更信息,而后更新本地缓存。管理员能够在治理后盾(shenyu-admin),变更用户权限、规定、插件、流量配置,通过推拉模式将变更信息同步给 Apache ShenYu 网关,具体是 push 模式,还是 pull 模式取决于应用哪种同步形式。

9.pngimage.gif

在最后的版本中,配置服务依赖 Zookeeper 实现,治理后盾将变更信息 push 给网关。而当初能够反对 WebSocket、Http 长轮询、Zookeeper、Nacos、Etcd 和 Consul,通过在配置文件中设置 shenyu.sync.${strategy} 指定对应的同步策略,默认应用 webosocket 同步策略,能够做到秒级数据同步。然而,有一点须要留神的是,Apache ShenYu 网关 和 shenyu-admin 必须应用雷同的同步策略。

如上图所示,shenyu-admin 在用户产生配置变更之后,会通过 EventPublisher 收回配置变更告诉,由 EventDispatcher 解决该变更告诉,而后依据配置的同步策略(http、weboscket、zookeeper、naocs、etcd、consul),将配置发送给对应的事件处理器。

1、如果是 websocket 同步策略,则将变更后的数据被动推送给 shenyu-web,并且在网关层,会有对应的 WebsocketDataHandler 处理器来解决 shenyu-admin 的数据推送。

2、如果是 zookeeper 同步策略,将变更数据更新到 zookeeper,而 ZookeeperSyncCache 会监听到 zookeeper 的数据变更,并予以解决。

3、如果是 http 同步策略,由网关被动发动长轮询申请,默认有 90s 超时工夫,如果 shenyu-admin 没有数据变更,则会阻塞 http 申请,如果有数据产生变更则响应变更的数据信息,如果超过 60s 依然没有数据变更则响应空数据,网关层接到响应后,持续发动 http 申请,重复同样的申请。

流程剖析

流程剖析是从源码的角度,展现服务注册流程,数据同步流程和服务调用流程。

服务注册流程

1、读取 dubbo 服务

应用注解 @ShenyuDubboClient 标记须要注册到网关的 dubbo 服务。

注解扫描通过 ApacheDubboServiceBeanListener 实现,它实现了 ApplicationListener<ContextRefreshedEvent> 接口,在 Spring 容器启动过程中,产生上下文刷新事件时,开始执行事件处理办法 onApplicationEvent()。在重写的办法逻辑中,读取 Dubbo 服务 ServiceBean,构建元数据对象和 URI 对象,并向 shenyu-admin 注册。具体的注册逻辑由注册核心实现,请参考客户端接入原理。

2、解决注册信息

客户端通过注册核心注册的元数据和 URI 数据,在 shenyu-admin 端进行解决,负责存储到数据库和同步给 shenyu 网关。Dubbo 插件的客户端注册解决逻辑在 ShenyuClientRegisterDubboServiceImpl 中。继承关系如下:

10.png

ShenyuClientRegisterService:客户端注册服务,顶层接口;
FallbackShenyuClientRegisterService:注册失败,提供重试操作;
AbstractShenyuClientRegisterServiceImpl:抽象类,实现局部公共注册逻辑;
ShenyuClientRegisterDubboServiceImpl:实现 Dubbo 插件的注册;

注册信息包含选择器,规定和元数据。

整体的 dubbo 服务注册流程如下:

11.png

数据同步流程

1、admin 更新数据

假如在在后盾管理系统中,新增一条选择器数据,申请会进入 SelectorController 类中的 createSelector()办法,它负责数据的校验,增加或更新数据,返回后果信息。在 SelectorServiceImpl 类中通过 createOrUpdate()办法实现数据的转换,保留到数据库,公布事件,更新 upstream。

在 Service 类实现数据的长久化操作,即保留数据到数据库。公布变更数据通过 eventPublisher.publishEvent()实现,这个 eventPublisher 对象是一个 ApplicationEventPublisher 类,这个类的全限定名是 org.springframework.context.ApplicationEventPublisher,公布数据的性能正是是通过 Spring 相干的性能来实现的。

当事件公布实现后,会主动进入到 DataChangedEventDispatcher 类中的 onApplicationEvent()办法,依据不同数据类型和数据同步形式进行事件处理。

2、网关数据同步

网关在启动时,依据指定的数据同步形式加载不同的配置类,初始化数据同步相干类。

在接管到数据后,进行反序列化操作,读取数据类型和操作类型。不同的数据类型,有不同的数据处理形式,所以有不同的实现类。然而它们之间也有雷同的解决逻辑,所以能够通过模板办法设计模式来实现。雷同的逻辑放在抽象类 AbstractDataHandler 中的 handle()办法中,不同逻辑就交给各自的实现类。

新增一条选择器数据,是新增操作,会进入到 SelectorDataHandler.doUpdate()具体的数据处理逻辑中。

在通用插件数据订阅者 CommonPluginDataSubscriber,负责解决所有插件、选择器和规定信息。

将数据保留到网关的内存中,BaseDataCache 是最终缓存数据的类,通过单例模式实现。选择器数据就存到了 SELECTOR_MAP 这个 Map 中。在后续应用的时候,也是从这里拿数据。

上述逻辑用流程图示意如下:image.gif

12.png

服务调用流程

在 Dubbo 插件体系中,类继承关系如下:

13.png

image.gif

ShenyuPlugin:顶层接口,定义接口办法;
AbstractShenyuPlugin:抽象类,实现插件共有逻辑;
AbstractDubboPlugin:dubbo 插件抽象类,实现 dubbo 共有逻辑(ShenYu 网关反对 ApacheDubbo 和 AlibabaDubbo);
ApacheDubboPlugin:ApacheDubbo 插件。

org.apache.shenyu.web.handler.ShenyuWebHandler.DefaultShenyuPluginChain#execute()

通过 ShenYu 网关代理后,申请入口是 ShenyuWebHandler,它实现了 org.springframework.web.server.WebHandler 接口,通过责任链设计模式将所有插件连接起来。

org.apache.shenyu.plugin.base.AbstractShenyuPlugin#execute()

当申请到网关时,判断某个插件是否执行,是通过指定的匹配逻辑来实现。在 execute()办法中执行选择器和规定的匹配逻辑。

org.apache.shenyu.plugin.global.GlobalPlugin#execute()

最先被执行的是 GlobalPlugin,它是一个全局插件,在 execute()办法中构建上下文信息。

org.apache.shenyu.plugin.base.RpcParamTransformPlugin#execute()

接着被执行的是 RpcParamTransformPlugin,它负责从 http 申请中读取参数,保留到 exchange 中,传递给 rpc 服务。在 execute()办法中,执行该插件的外围逻辑:从 exchange 中获取申请信息,依据申请传入的内容模式解决参数。

org.apache.shenyu.plugin.dubbo.common.AbstractDubboPlugin

而后被执行的是 DubboPlugin。在 doExecute()办法中,次要是查看元数据和参数。在 doDubboInvoker()办法中设置非凡的上下文信息,而后开始 dubbo 的泛化调用。

在 genericInvoker()办法中:

1、获取 ReferenceConfig 对象;

2、获取泛化服务 GenericService 对象;

3、结构申请参数 pair 对象;

4、发动异步的泛化调用。

通过泛化调用就能够实现在网关调用 dubbo 服务了。

ReferenceConfig 对象是反对泛化调用的要害对象,它的初始化操作是在数据同步的时候实现的。

org.apache.shenyu.plugin.response.ResponsePlugin#execute()

最初被执行的是 ResponsePlugin,它对立解决网关的响应后果信息。解决类型由 MessageWriter 决定,类继承关系如下:

14.png

MessageWriter:接口,定义音讯解决办法;
NettyClientMessageWriter:解决 Netty 调用后果;
RPCMessageWriter:解决 RPC 调用后果;
WebClientMessageWriter:解决 WebClient 调用后果;

Dubbo 服务调用,处理结果是 RPCMessageWriter。

org.apache.shenyu.plugin.response.strategy.RPCMessageWriter#writeWith()

在 writeWith()办法中解决响应后果,获取后果或解决异样。

剖析至此,对于 Dubbo 插件的源码剖析就实现了,剖析流程图如下:

15.png

小结

本文从理论案例登程,由浅入深剖析了 ShenYu 网关对 Dubbo 服务的代理过程。波及到的次要知识点如下:

通过责任链设计模式执行插件;
应用模板办法设计模式实现 AbstractShenyuPlugin,解决通用的操作类型;
应用单例设计模式实现缓存数据类 BaseDataCache;
通过 springboot starter 即可引入不同的注册核心和数同步形式,扩展性很好;
通过 admin 反对规定热更新,不便流量管控;
Disruptor 队列是为了数据与操作解耦,以及数据缓冲。

有任何疑难,欢送通过以下渠道分割社区:

Apache Shenyu 社区:
https://github.com/apache/inc…

Dubbo3 社区:
https://github.com/apache/dubbo https://github.com/apache/dubbo

企业用户可搜寻钉钉群 34129986

作者简介

刘良:Apache ShenYu PPMC

原文链接:http://click.aliyun.com/m/100…

本文为阿里云原创内容,未经容许不得转载。

正文完
 0