简介: 本文介绍了如何经过 Apache ShenYu 网关访问 Dubbo 服务,主要内容包含从简略示例到中心调用流程剖析,并对规划原理进行了总结。

作者:刘良

Apache Dubbo 在去年发布了下一代的云原生微服务版别 Dubbo3,现在最新版别 Dubbo3 已在阿里经济体完结对 HSF2 结构的全面替换与晋级,Dubbo3 现在已成为社区企业实践推荐版别。Apache Shenyu 网关在这个布景下发布了对 Dubbo3 服务署理的支撑。

本文介绍了如何经过 Apache ShenYu 网关访问 Dubbo 服务,主要内容包含从简略示例到中心调用流程剖析,并对规划原理进行了总结。

介绍

Apache ShenYu

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 插件设置为敞开,并设置你的注册地址,请保证注册中心现已敞开。

发动 shenyu 网关

在这儿经过源码的办法发动,直接运转 shenyu-bootstrap 中的 ShenyuBootstrapApplication。

在发动前,请保证网关现已引进相关依赖。假如客户端是 apache dubbo,注册中心运用 zookeeper,请参考如下装备:

org.apache.shenyu

shenyu-spring-boot-starter-plugin-apache-dubbo

${project.version}

org.apache.dubbo

dubbo

3.0.8

org.apache.curator

curator-client

4.0.1

log4j

log4j

org.apache.curator

curator-framework

4.0.1

org.apache.curator

curator-recipes

4.0.1

发动 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”/>

声明运用服务名称,注册中心地址,运用 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 能够看到插件规矩装备列表:

注册成功的选择器信息:

注册成功的规矩信息:

选择器和规矩是 Apache ShenYu 网关中最灵魂的东西。掌握好它,你能够对任何流量进行办理。对应为选择器与规矩里面的匹配条件(conditions),依据不同的流量挑选规矩,我们能够处理各种复杂的场景。流量挑选能够从 Header, URI, Query, Cookie 等等 Http 恳求获取数据。

然后能够采用 Match,=,Regex,Groovy,Exclude 等匹配办法,匹配出你所料想的数据。多组匹配添加能够运用 And/Or 的匹配战略。详细的介绍与运用请看: 选择器与规矩办理 。

建议 GET 恳求,经过 ShenYu 网关调用 dubbo 服务:

GET http://localhost:9195/dubbo/findById?id=100

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 办法注册。

客户端接入的相关装备请参考客户端接入装备。

  • 客户端注册

在你的微服务装备中声明注册中心客户端类型,如 Http 或 Zookeeper。运用程序发动时运用 SPI 办法加载并初始化对应注册中心客户端,经过完结 Spring Bean 相关的后置处理器接口,在其间获取需求进行注册的服务接口信息,将获取的信息放入 Disruptor 中。

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

  • 服务端注册

在 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 方式取决于运用哪种同步办法。

在最初的版别中,装备服务依赖 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接口,在 Spring 容器发动进程中,产生上下文刷新事情时,开端履行事情处理办法 onApplicationEvent()。在重写的办法逻辑中,读取 Dubbo 服务 ServiceBean,构建元数据目标和 URI 目标,并向 shenyu-admin 注册。详细的注册逻辑由注册中心完结,请参考客户端接入原理。

2、处理注册信息

客户端经过注册中心注册的元数据和 URI 数据,在 shenyu-admin 端进行处理,担任存储到数据库和同步给 shenyu 网关。Dubbo 插件的客户端注册处理逻辑在 ShenyuClientRegisterDubboServiceImpl 中。承继联系如下:

  • ShenyuClientRegisterService:客户端注册服务,顶层接口;
  • FallbackShenyuClientRegisterService:注册失利,供给重试操作;
  • AbstractShenyuClientRegisterServiceImpl:抽象类,完结部分公共注册逻辑;
  • ShenyuClientRegisterDubboServiceImpl:完结 Dubbo 插件的注册;

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

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

  • 数据同步流程

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 中。在后续运用的时分,也是从这儿拿数据。

上述逻辑用流程图表明如下:

  • 服务调用流程

在 Dubbo 插件系统中,类承继联系如下:

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 决定,类承继联系如下:

MessageWriter:接口,界说音讯处理办法;

NettyClientMessageWriter:处理 Netty 调用成果;

RPCMessageWriter:处理 RPC 调用成果;

WebClientMessageWriter:处理 WebClient 调用成果;

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

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

在 writeWith()办法中处理呼应成果,获取成果或处理异常。

剖析至此,关于 Dubbo 插件的源码剖析就完结了,剖析流程图如下:

小结

本文从实践事例出发,由浅入深剖析了 ShenYu 网关对 Dubbo 服务的署理进程。涉及到的主要知识点如下:

  • 经过责任链规划方式履行插件;
  • 运用模板办法规划方式完结 AbstractShenyuPlugin,处理通用的操作类型;
  • 运用单例规划方式完结缓存数据类 BaseDataCache;
  • 经过 springboot starter 即可引进不同的注册中心和数同步办法,扩展性很好;
  • 经过 admin 支撑规矩热更新,方便流量管控;
  • Disruptor 行列是为了数据与操作解耦,以及数据缓冲。

有任何疑问,欢迎经过以下途径联系社区:

  • Apache Shenyu 社区:

github.com/apache/incu…

  • Dubbo3 社区:

github.com/apache/dubb… github.com/apache/dubb…

企业用户可查找钉钉群 34129986

作者简介

刘良:Apache ShenYu PPMC

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

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