概述
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 | 服务运行容器 |
调用关系说明:
- 服务容器负责启动,加载,运行服务提供者。
- 服务提供者在启动时,向注册中心注册自己提供的服务。
- 服务消费者在启动时,向注册中心订阅自己所需的服务。
- 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
- 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
- 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心
上方我们已经过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插件所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复