网站首页 文章专栏 soul源码解析(三)
1. 继续结合divde插件,发起http请求soul网关,体验http代理
2. 梳理admin如何接受@SoulSpringMvcClient发来的请求,以及保存策略
3. 学习admin与网关之间的内存同步方式
1. admin端接受请求
1). SoulClientController
在该controller中编写了多种方式的register,暴露url:/soul-client/springmvc-register ,通过SpringMvcRegisterDTO接受入参,返回 "success" 字符串
@Data
public class SpringMvcRegisterDTO implements Serializable {
private String appName;
private String context;
private String path;
private String pathDesc;
private String rpcType;
private String host;
private Integer port;
private String ruleName;
private boolean enabled;
private boolean registerMetaData;
}2). 先判断参数中 registerMetaData 是否为true,是否注册元数据
如果是:
1>. 先根据参数中的 path 查库,判断是否存在
2>. 存在的就忽略,不存在则保存入库
3>. 并同时通过 ApplicationEventPublisher 发布 DataChangedEvent 事件 META_DATA CREATE 的通知
4>. 通过定义的 DataChangedListener接口 的 onMetaDataChanged 监听该事件
5>. 该接口有 4 中实现方式,AbstractDataChangedListener,NacosDataChangedListener,WebsocketDataChangedListener,ZookeeperDataChangedListener
if (dto.isRegisterMetaData()) {
MetaDataDO exist = metaDataMapper.findByPath(dto.getPath());
if (Objects.isNull(exist)) {
saveSpringMvcMetaData(dto);
}
}3). 处理SpringMvc的选择器,根据path查询是否存在 Selector
SelectorDO selectorDO = selectorService.findByName(contextPath);
4). 如果不存在,则创建一个,具体数据就是页面看到的那样,拼接ip,port,默认权重50,设置插件divide,并同步到内存
if (Objects.isNull(selectorDO)) {
selectorId = registerSelector(contextPath, dto.getRpcType(), dto.getAppName(), uri);
}
private String registerSelector(final String contextPath, final String rpcType, final String appName, final String uri) {
SelectorDTO selectorDTO = new SelectorDTO();
selectorDTO.setName(contextPath);
selectorDTO.setType(SelectorTypeEnum.CUSTOM_FLOW.getCode());
selectorDTO.setMatchMode(MatchModeEnum.AND.getCode());
selectorDTO.setEnabled(Boolean.TRUE);
selectorDTO.setLoged(Boolean.TRUE);
selectorDTO.setContinued(Boolean.TRUE);
selectorDTO.setSort(1);
if (RpcTypeEnum.DUBBO.getName().equals(rpcType)) {
selectorDTO.setPluginId("6");
} else if (RpcTypeEnum.SPRING_CLOUD.getName().equals(rpcType)) {
selectorDTO.setPluginId("8");
selectorDTO.setHandle(appName);
} else {
//is divide
DivideUpstream divideUpstream = buildDivideUpstream(uri);
String handler = GsonUtils.getInstance().toJson(Collections.singletonList(divideUpstream));
selectorDTO.setHandle(handler);
selectorDTO.setPluginId("5");
upstreamCheckService.submit(selectorDTO.getName(), divideUpstream);
}
SelectorConditionDTO selectorConditionDTO = new SelectorConditionDTO();
selectorConditionDTO.setParamType(ParamTypeEnum.URI.getName());
selectorConditionDTO.setParamName("/");
selectorConditionDTO.setOperator(OperatorEnum.MATCH.getAlias());
selectorConditionDTO.setParamValue(contextPath + "/**");
selectorDTO.setSelectorConditions(Collections.singletonList(selectorConditionDTO));
return selectorService.register(selectorDTO);
}5). 存在的话,且有新的 Selector 则在原来已存在的 Selector 基础上,增加新的,并更新到数据库
6). 提交过去检查,发送更新事件
//更新数据库 selectorMapper.updateSelective(selectorDO); //提交过去检查 upstreamCheckService.submit(contextPath, addDivideUpstream); //发送更新事件 // publish change event. eventPublisher.publishEvent(new DataChangedEvent(ConfigGroupEnum.SELECTOR, DataEventTypeEnum.UPDATE, Collections.singletonList(selectorData)));
7). 处理规则,查询是否存在规则,不存在的话创建一个
private void handlerSpringMvcRule(final String selectorId, final SpringMvcRegisterDTO dto) {
RuleDO ruleDO = ruleMapper.findByName(dto.getRuleName());
if (Objects.isNull(ruleDO)) {
registerRule(selectorId, dto.getPath(), dto.getRpcType(), dto.getRuleName());
}
}8). 同时通过 ruleService.register(ruleDTO); 保存到数据库,并发布规则更新事件
public String register(final RuleDTO ruleDTO) {
RuleDO ruleDO = RuleDO.buildRuleDO(ruleDTO);
List<RuleConditionDTO> ruleConditions = ruleDTO.getRuleConditions();
if (StringUtils.isEmpty(ruleDTO.getId())) {
ruleMapper.insertSelective(ruleDO);
ruleConditions.forEach(ruleConditionDTO -> {
ruleConditionDTO.setRuleId(ruleDO.getId());
ruleConditionMapper.insertSelective(RuleConditionDO.buildRuleConditionDO(ruleConditionDTO));
});
}
publishEvent(ruleDO, ruleConditions);
return ruleDO.getId();
}2. admin模块事件发布订阅,推送消息模式
1). ApplicationEventPublisher和监听ApplicationEvent事件
1>. 自定义需要发布的事件类,需要继承ApplicationEvent类或PayloadApplicationEvent(该类也仅仅是对ApplicationEvent的一层封装)
2>. 在soul中使用自定义 DataChangedEvent 继承ApplicationEvent类
3>. 使用ApplicationEventPublisher来发布自定义事件(@Autowired注入即可)
3. 疑问未解决:
1). onMetaDataChanged 事件的目的是什么?几种实现方式具体用的哪一个?
2). 下面这张图中,configServer代表什么,是在admin端,还是网关侧
3). 网关如何接受全量数据以及增量数据同步到内存的?

发现问题:
// publish AppAuthData's event该句注释应用在很多地方,应该是不对的
版权声明:本文由星尘阁原创出品,转载请注明出处!