Soul网关源码阅读(九)—— 数据同步之WebSocket
文章目录
概要
之前我们简单介绍了soul网关是通过admin进行数据同步的,这一篇我们来消息介绍一下soul网关使用websocket来进行数据同步的关机设计和详细流程。
流程图
详细解析
1. WebsocketSyncDataConfiguration
首先知道网关与admin之间需要同步的数据类型有哪些:
- 插件Plugin
- 元数据MetaData
- 认证数据AuthData
我们那需要为每一种数据类型编写不同的业务逻辑:
- PluginDataSubcriber
- MetaDataSubcriber
- AuthDataSubscriber
这里我们Websocket下对应实现类分别是:
- CommonPluginDataSubscriber
- MetaDataAllSubscriber
- SignAuthDataSubscriber
WebsocketSyncDataConfiguration配置类,组合了以上对象,并且初始化了WebsocketSyncDataService对象。WebsocketSyncDataService对象是用来进行数据同步的类型,它组合了一个WebSocketClient用来与admin服务进行socket通信。
2. WebsocketSyncDataService
WebsocketSyncDataService在初始化的时候,会出发WebSocketClient初始化并且通过websocket连接到admin,连接到配置的端口:ws://localhost:9095/websocket
。
Admin服务WebSocketCollector
的onMessage
方法会触发soul的请求:
@OnMessage
public void onMessage(final String message, final Session session) {
if (message.equals(DataEventTypeEnum.MYSELF.name())) {
try {
ThreadLocalUtil.put(SESSION_KEY, session);
SpringBeanUtils.getInstance().getBean(SyncDataService.class).syncAll(DataEventTypeEnum.MYSELF);
} finally {
ThreadLocalUtil.clear();
}
}
}
Admin中通过SyncDataServiceImpl来syncAll
方法来进行所有数据类型的同步,由于是soul刚启动,所以需要同步全量数据,这里通过去数据库获取数据发送事件的方式,将不同ConfigGroupEnum类型发送给不同的监听器进行处理。
@Override
public boolean syncAll(final DataEventTypeEnum type) {
appAuthService.syncData();
List<PluginData> pluginDataList = pluginService.listAll();
eventPublisher.publishEvent(new DataChangedEvent(ConfigGroupEnum.PLUGIN, type, pluginDataList));
List<SelectorData> selectorDataList = selectorService.listAll();
eventPublisher.publishEvent(new DataChangedEvent(ConfigGroupEnum.SELECTOR, type, selectorDataList));
List<RuleData> ruleDataList = ruleService.listAll();
eventPublisher.publishEvent(new DataChangedEvent(ConfigGroupEnum.RULE, type, ruleDataList));
metaDataService.syncData();
return true;
}
这里分别进行了auth、plugin、selector、rule、metadata数据的事件发送。
4. DataChangedEventDispatcher
发送的事件被DataChangedEventDispatcher监听器接收,它会根据不同的DataChangedEvent事件的ConfigGroupEnum类型,将事件委托给不同的listener进行处理。
这listener的实现类有四种,他们配置在DataSyncConfiguration,通过配置文件决定加载与否,如下所示,
这里我们由于只配置了WebSocketDataChangedListener,所有只会委托给WebSocketDataChangedListener的方法,进行执行:
5. WebsocketDataChangedListener
这里WebsocketDataChangedListener会将从数据库加载的信息发送给Soul
public void onPluginChanged(final List<PluginData> pluginDataList, final DataEventTypeEnum eventType) {
WebsocketData<PluginData> websocketData =
new WebsocketData<>(ConfigGroupEnum.PLUGIN.name(), eventType.name(), pluginDataList);
WebsocketCollector.send(GsonUtils.getInstance().toJson(websocketData), eventType);
}
6. SoulWebsocketClient
Soul网关SoulWebsocketClient接收到admin推送过来的数据,出发onMessage方法执行:
private void handleResult(final String result) {
WebsocketData websocketData = GsonUtils.getInstance().fromJson(result, WebsocketData.class);
ConfigGroupEnum groupEnum = ConfigGroupEnum.acquireByName(websocketData.getGroupType());
String eventType = websocketData.getEventType();
String json = GsonUtils.getInstance().toJson(websocketData.getData());
websocketDataHandler.executor(groupEnum, json, eventType);
}
并使用之前在装配进来的websocketDataHandler进行处理,具体处理逻辑handler为PluginDataHandler,并根据具体的事件类型做处理,这里将调用doRefresh方法:
@Override
public void handle(final String json, final String eventType) {
List<T> dataList = convert(json);
if (CollectionUtils.isNotEmpty(dataList)) {
DataEventTypeEnum eventTypeEnum = DataEventTypeEnum.acquireByName(eventType);
switch (eventTypeEnum) {
case REFRESH:
case MYSELF:
doRefresh(dataList);
break;
case UPDATE:
case CREATE:
doUpdate(dataList);
break;
case DELETE:
doDelete(dataList);
break;
default:
break;
}
}
}
@Override
protected void doRefresh(final List<PluginData> dataList) {
pluginDataSubscriber.refreshPluginDataSelf(dataList);
dataList.forEach(pluginDataSubscriber::onSubscribe);
}
doRefresh方法的逻辑很简单:
- 删除就缓存
- 添加新缓存
@Override
public void onSubscribe(final PluginData pluginData) {
subscribeDataHandler(pluginData, DataEventTypeEnum.UPDATE);
}
数据同步逻辑结束。
总结语
这篇我们分析了使用WebSocket进行数据同步的详细逻辑,并且分析soul启动时是如何加载plugin数据的,其他的数据类型的流程是一毛一样的,只不过换成不同的handler进行处理即可。
这里由于Soul启动时有一个初始化的操作,所以通过主动请求出发了数据同步操作。之后如果admin数据同步逻辑,也会通过事件的方式触发到DataChangedEventDispatcher监听器,将对应的数据更新发送给soul,如此就完成了admin与soul之间的数据同步。