根据soul官方文档的指引,Sofa接入soul网关,启动完 soul-admin,soul-bootdtrap,再去启动 TestSofaApplication 时报连接错误,看了下是因为没启动 zookeeper,zookeeper 开启后 ,就成功运行了 sofa插件,但使用网关访问时报这个错误。
{"code":-106,"message":"Can not find url, please check your configuration!","data":null}
后来发现重启 soul-bootstrap 就可以了,应该是重启才注册了元数据。
sofa插件执行的时候,首先是在 AbstractSoulPlugin 根据 url 找到对应的选择器规则。
在执行 GlobalPlugin 时,使用 DefaultSoulContextBuilder ,构建了 exchange 的数据,从缓存中拿到元数据,放到 exchange 里。
在执行 BodyParamPlugin 插件时,把 sofa 的参数封装在 exchange 里。
exchange.getAttributes().put(Constants.SOFA_PARAMS,
HttpParamConverter.ofString(() -> serverRequest.uri().getQuery()));
return chain.execute(exchange);
接着在插件链执行到 sofa 插件时,从 exchange拿到元数据。
这里就使用 SofaProxyService 进行泛化调用了,下图中可以看到执行完泛化调用,就拿到返回值了。
拿到返回值后就去执行 SofaResponsePlugin 去对 sofa请求的结果进行处理。
public Mono<Void> execute(final ServerWebExchange exchange, final SoulPluginChain chain) {
return chain.execute(exchange).then(Mono.defer(() -> {
//获取 sofa 请求结果
final Object result = exchange.getAttribute(Constants.SOFA_RPC_RESULT);
if (Objects.isNull(result)) {
Object error = SoulResultWrap.error(SoulResultEnum.SERVICE_RESULT_ERROR.getCode(), SoulResultEnum.SERVICE_RESULT_ERROR.getMsg(), null);
return WebFluxResultUtils.result(exchange, error);
}
//拼接返回值
Object success = SoulResultWrap.success(SoulResultEnum.SUCCESS.getCode(), SoulResultEnum.SUCCESS.getMsg(), JsonUtils.removeClass(result));
return WebFluxResultUtils.result(exchange, success);
}));
}
今天把 sofa 插件跑通了,也大概看了下执行的流程,在只开启 sofa 插件的情况下,总体来说,使用 GlobalPlugin 放数据,sofaPlugin 处理请求,SofaResponsePlugin 处理返回值。最难懂的就是 泛化调用这一块,这个具体流程明天再研究。
关于 sofa ,其实最终使用的还是 dubbo 的功能,也是一种 rpc 框架,简单在官网了解下它的功能。
- 当一个 SOFARPC 的应用启动的时候,如果发现当前应用需要发布 RPC 服务的话,那么 SOFARPC 会将这些服务注册到服务注册中心上。如图中 Service 指向 Registry。
- 当引用这个服务的 SOFARPC 应用启动时,会从服务注册中心订阅到相应服务的元数据信息。服务注册中心收到订阅请求后,会将发布方的元数据列表实时推送给服务引用方。如图中 Registry 指向 Reference。
- 当服务引用方拿到地址以后,就可以从中选取地址发起调用了。如图中 Reference 指向 Service。