序
前两篇文章都在了解 HTTP 接口是怎么被 soul 网关代理的,先是新建了一个提供 http 接口的项目,然后引入 soul 的 starter 依赖去完成 http 接口的注册,然后从源码上去解读了项目启动过程中 http 接口信息注册到 soul-admin 模块。
但是这依然不是完整的流程,因为 soul-admin 服务开放的端口是 9095,真实的 http 服务端口是 8080,但是我们使用 soul 网关去访问接口却是使用的 9195,也就是说,http 的接口信息除了注册到了 soul-admin,还传递给了 soul 网关。
所以又回到了上一次留下的问题:配置 soul 网关的地址明明只是端口为 9095 的 soul-admin,为啥最后代理的端口是 9195?
但是从我们自己新建的项目里来看,是没有任何有关于 soul 网关的配置信息的,只有直接关联了 soul-admin。那么可以猜测下,是不是 soul-admin 背着我们干了这些事?
soul-admin 偷偷干了啥
还是老规矩,一条线走到黑,暂时只关注 http 接口相关的部分。
先从配置文件开始,里面需要关注的配置内容也不多,数据库就可以忽略了。另外一个重要的就是数据同步这部分内容了。就先了解默认的 websocket 同步方式吧。
soul:
sync:
websocket:
enabled: true
配置内容找到了,接下来就是找配置使用的地方了。
可以在 org.dromara.soul.admin.config.DataSyncConfiguration 配置类里面找到这样的代码。
@Configuration
public class DataSyncConfiguration {
/**
* The WebsocketListener(default strategy).
*/
@Configuration
@ConditionalOnProperty(name = "soul.sync.websocket.enabled", havingValue = "true", matchIfMissing = true)
@EnableConfigurationProperties(WebsocketSyncProperties.class)
static class WebsocketListener {
/**
* Config event listener data changed listener.
*
* @return the data changed listener
*/
@Bean
@ConditionalOnMissingBean(WebsocketDataChangedListener.class)
public DataChangedListener websocketDataChangedListener() {
return new WebsocketDataChangedListener();
}
/**
* Websocket collector websocket collector.
*
* @return the websocket collector
*/
@Bean
@ConditionalOnMissingBean(WebsocketCollector.class)
public WebsocketCollector websocketCollector() {
return new WebsocketCollector();
}
/**
* Server endpoint exporter server endpoint exporter.
*
* @return the server endpoint exporter
*/
@Bean
@ConditionalOnMissingBean(ServerEndpointExporter.class)
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
}
可以看到这个类只会在配置了上面的信息之后才会执行加载。
里面重要的有两个点:
- 使用 WebSocket 开启了一个 socket 服务
- 将会实例化一个 WebsocketDataChangedListener 实例,看名字大概就能猜到是当监听到数据有变化时候的处理过程
对于第一点,使用了 spring-boot-starter-websocket 依赖去开启了一个 web socket 的 endpoint,可以跟 web 服务共用一个端口 9095。
既然是提供了 web socket 的服务,那么肯定有对应的 client 端来连接它吧,那会是谁呢?
回到开头的问题,我们从自己的 http 服务一路追寻到了 soul-admin 模块,至今都没有跟 soul-bootstrap 打过交道(无论是自己的 http 服务,还是当前的 soul-admin 模块),但偏偏网关的代理是由 soul-bootstrap 去完成的。
结合上面的 web socket 服务,答案也就显而易见了吧。 没错,soul-admin 通过提供了 web socket 服务,去充当了一个中间人的角色。
我们自己的 http 服务注册接口信息到 soul-admin,soul-admin 提供 web socket 服务,soul-bootstrap 主动建立连接到 soul-admin,终于——三者的联系找到了。
明白了这一点,那就可以去 soul-bootstrap 找找有没有 soul-admin 模块的 web socket 服务配置了。配置内容如下:
soul :
file:
enabled: true
corss:
enabled: true
dubbo :
parameter: multi
sync:
websocket :
urls: ws://localhost:9095/websocket
总结
所以到目前为止,我们已经可以解答开头的问题了,接口的数据先是传递到了 soul-admin,然后 soul-bootstrap 主动跟 soul-admin 的 web socket 服务连接获取数据,这样 soul-bootstrap 也就知道了接口的地址,从而可以对外提供接口代理的服务了。
但是,这只是从代码上找到了它们三个的联系,加上自己的逻辑证明了这个过程,那么接口数据传递具体是怎么实现的呢?
我们下一篇文章继续深入探究数据是怎么通过 soul-admin 到 soul-bootstap 网关的。