简介: 本文介绍了如何通过 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...

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