网站首页 文章专栏 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该句注释应用在很多地方,应该是不对的
版权声明:本文由星尘阁原创出品,转载请注明出处!