Soul source code read 01-SpringMvc interface registration gateway process

In the last section, we saw an overview of how Soul can find and register interfaces under the SpringMvc architecture, so let’s track down what happens when the interface addresses register with the gateway.

Process tracking

  • As described in the previous chapter, soul registers an interface via HTTP. This interface address is shown below (/soul-client/ springmVC-register).
public ContextRegisterListener(final SoulSpringMvcConfig soulSpringMvcConfig) {
        ValidateUtils.validate(soulSpringMvcConfig);
        this.soulSpringMvcConfig = soulSpringMvcConfig;
        url = soulSpringMvcConfig.getAdminUrl() + "/soul-client/springmvc-register";
    }
Copy the code
  • Look for this interface in soul’s admin

@RestController
@RequestMapping("/soul-client")
public class SoulClientController {
    /** * SpringMvc interface registration *@param springMvcRegisterDTO
     * @return* /
    @PostMapping("/springmvc-register")
    public String registerSpringMvc(@RequestBody final SpringMvcRegisterDTO springMvcRegisterDTO) {
        returnsoulClientRegisterService.registerSpringMvc(springMvcRegisterDTO); }}Copy the code
  • Since there is no requirement to register metadata when passing through the service layer, we directly enter the underlying logic of if
public String registerSpringMvc(final SpringMvcRegisterDTO dto) {
        // Determine whether metadata needs to be registered
        logger.info("SpringMvc passes a registration DTO of {}",dto.toString());
        if (dto.isRegisterMetaData()) {
            // The if logic is not executed here
            // Determine whether there is metadata for the data
            MetaDataDO exist = metaDataMapper.findByPath(dto.getPath());
            if (Objects.isNull(exist)) {
                // There is no direct registrationsaveSpringMvcMetaData(dto); }}// The dTO passed by processing returns the selector ID
        String selectorId = handlerSpringMvcSelector(dto);
        // Data is processed according to the selector ID and the corresponding DTO
        handlerSpringMvcRule(selectorId, dto);
        return SoulResultMessage.SUCCESS;
    }
Copy the code
  • The SpringMvc selector returns the ID of the selector. In this method logic, the processing of handle is involved. The first step is to determine whether the handle of the current selector is empty. Empty will refresh the updated value into the table, if not empty, determine whether the real address of the access item is consistent with the current address, if so, directly return ID (may involve multiple loads?) , inconsistent modified library operation and service loading memory monitor operation (upstreamCheckService. Submit), at last, through the Spring event mechanism sent a selector to change events
private String handlerSpringMvcSelector(final SpringMvcRegisterDTO dto) {
        String contextPath = dto.getContext();
        SelectorDO selectorDO = selectorService.findByName(contextPath);
        String selectorId;
        // Assemble the real path
        String uri = String.join(":", dto.getHost(), String.valueOf(dto.getPort()));
        // Check whether the selector does not have direct entry
        if (Objects.isNull(selectorDO)) {
        // The registration method is public and also involves internal monitoring of the service monitoring state
            selectorId = registerSelector(contextPath, dto.getRpcType(), dto.getAppName(), uri);
        } else {
            selectorId = selectorDO.getId();
            //update upstream
            String handle = selectorDO.getHandle();
            String handleAdd;
            DivideUpstream addDivideUpstream = buildDivideUpstream(uri);
            SelectorData selectorData = selectorService.buildByName(contextPath);
            if (StringUtils.isBlank(handle)) {
                handleAdd = GsonUtils.getInstance().toJson(Collections.singletonList(addDivideUpstream));
            } else {
                List<DivideUpstream> exist = GsonUtils.getInstance().fromList(handle, DivideUpstream.class);
                for (DivideUpstream upstream : exist) {
                    if (upstream.getUpstreamUrl().equals(addDivideUpstream.getUpstreamUrl())) {
                        return selectorId;
                    }
                }
                exist.add(addDivideUpstream);
                handleAdd = GsonUtils.getInstance().toJson(exist);
            }
            selectorDO.setHandle(handleAdd);
            selectorData.setHandle(handleAdd);
            // Modify the database
            selectorMapper.updateSelective(selectorDO);
            // Join the queue for service monitoring
            upstreamCheckService.submit(contextPath, addDivideUpstream);
            // Event publish The publish type is selector and the action type is modify
            eventPublisher.publishEvent(new DataChangedEvent(ConfigGroupEnum.SELECTOR, DataEventTypeEnum.UPDATE,
                    Collections.singletonList(selectorData)));
        }
        return selectorId;
    }
Copy the code
  • The logic of the handlerSpringMvcRule is basically to combine the returned selector ID with the corresponding springMvcDto, and finally to import the publishEvent method in the following method. A rule related change notification event was published.
 @Override
    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();
    }
    
    private void publishEvent(final RuleDO ruleDO, final List<RuleConditionDTO> ruleConditions) {
        // omit the code
        // publish change event.
        eventPublisher.publishEvent(new DataChangedEvent(ConfigGroupEnum.RULE, DataEventTypeEnum.UPDATE,
                Collections.singletonList(RuleDO.transFrom(ruleDO, pluginDO.getName(), conditionDataList))));
    }
Copy the code

ContextPath = contextPath; contextPath = contextPath; contextPath = contextPath; contextPath = contextPath; contextPath = contextPath; If there is a will determine whether is empty, empty directly covered, not empty than those of the current under the contextPath address is already exists, if there is a direct jump out, there is no unified change of library, service test, release a modify event selector, the next step is for the processing of registration rules, change is also about logic library, Then finally publish a rule-related change event.