This article focuses on how HTTP back-end services in the Soul Gateway framework register with Divide plug-ins once they are started.

background

As described earlier, the Divide load balancing plug-in can forward HTTP requests to soul-admin-configured back-end services.

HTTP service registration to the gateway source code analysis

Back-end service side source code analysis

  • The soul-example-http backend service, for example, introduces the soul-spring-boot-starter-client-springMVC package, which contains only one configuration class. Including a SpringMvcClientBeanPostProcessor type of bean; (implementation of BeanPostProcessor interface for Bean initialization post-processing;)

    <dependency>
        <groupId>org.dromara</groupId>
        <artifactId>soul-spring-boot-starter-client-springmvc</artifactId>
        <version>${soul.version}</version>
    </dependency>
    Copy the code
    @Bean
    public SpringMvcClientBeanPostProcessor springHttpClientBeanPostProcessor(final SoulSpringMvcConfig soulSpringMvcConfig) {
        return new SpringMvcClientBeanPostProcessor(soulSpringMvcConfig);
    }
    Copy the code
  • SpringMvcClientBeanPostProcessor initialization, contains url registration;

  • The backend Http service Controller needs to use the SoulSpringMvcClient annotation for service registration.

    @RestController @RequestMapping("/test") @SoulSpringMvcClient(path = "/test/**") public class HttpTestController { // . }Copy the code
    @RestController
    @RequestMapping("/order")
    @SoulSpringMvcClient(path = "/order")
    public class OrderController {
    // ...
    }
    Copy the code
  • Backend triggered when the Http service Controller instantiated SpringMvcClientBeanPostProcessor rear processing, post processing will be registered in the back-end services;

  • If the registered service path contains an * asterisk, such as /test/** in HttpTestController, it will be placed in the thread pool to perform the asynchronous registration task.



    / / requests into the reference sample url: http://localhost:9095/soul-client/springmvc-register json: {" appName ":" HTTP ", "context" : "HTTP/"," path ":" HTTP/test / * * / ", "pathDesc" : ""," rpcType ":" HTTP ", "the host" : "172.16.21.89." "port":8188, "ruleName":"/http/test/**", "enabled":true, "registerMetaData":false }Copy the code
  • After registration, the soul-admin management side will see the backend service.

  • If the registered service path does not contain an * asterisk, such as OrderController, the principle is similar, except that each method in the class needs to be registered in sequence. Because the method also uses the SoulSpringMvcClient annotation;

    @PostMapping("/save")
    @SoulSpringMvcClient(path = "/save" , desc = "Save order")
    public OrderDTO save(@RequestBody final OrderDTO orderDTO) {
        orderDTO.setName("hello world save order");
        return orderDTO;
    }
    Copy the code

Gateway background side source code analysis

  • Soul-admin receives a registration request for the backend service, processing the selector and the rule in turn, focusing only on the registration of the selector.

    public String registerSpringMvc(final SpringMvcRegisterDTO dto) { if (dto.isRegisterMetaData()) { MetaDataDO exist = metaDataMapper.findByPath(dto.getPath()); If (objects.isNULL (exist)) {saveSpringMvcMetaData(dTO); if (objects.isnull (exist)) {saveSpringMvcMetaData(dto); } } String selectorId = handlerSpringMvcSelector(dto); handlerSpringMvcRule(selectorId, dto); return SoulResultMessage.SUCCESS; }Copy the code
  • If the selector under the current contextPath does not exist, it needs to be registered.

    selectorId = registerSelector(contextPath, dto.getRpcType(), dto.getAppName(), uri);
    Copy the code
  • If the selector already exists, the list of back-end services needs to be updated, which involves updating the DB, local caching, and notifying the Soul gateway cluster.

    // update db
    selectorMapper.updateSelective(selectorDO);
    // submit upstreamCheck
    upstreamCheckService.submit(contextPath, addDivideUpstream);
    // publish change event.
    eventPublisher.publishEvent(new DataChangedEvent(ConfigGroupEnum.SELECTOR, DataEventTypeEnum.UPDATE,
            Collections.singletonList(selectorData)));
    Copy the code
  • After the selector backend service list is updated, the Configuration column is displayed on the soul-admin side. If the back-end service is not started, the column is empty;

conclusion

  • When the backend Http service instance is started, it relies on BeanPostProcessor to register the service uniformly after Bean initialization.

  • Only beans with SoulSpringMvcClient annotations need to register with the gateway, which is to make an HTTP request to the gateway background.

  • After receiving the registration request, the gateway background processes the context -> selector -> rule in sequence. It is worth noting that the registration of back-end services also involves the synchronization of configuration data. For details, see the previous analysis.

series

  • Soul source learning [1] – preliminary exploration
  • Soul source learning [2] – divide load balancing plug-in
  • Soul source learning [3] – Dubbo plug-in
  • Soul source learning [4] – RateLimiter stream limiting plug-in
  • Soul source learning [5] – SpringCloud plug-in
  • Soul source learning [6] – Chain of responsibility mode
  • Soul source learning [7] – Data synchronization strategy websocket synchronization
  • [8] – Data synchronization strategy for ZooKeeper synchronization
  • [9] – ZooKeeper Synchronization (2)
  • Soul source learning [10] – Observer mode application
  • Soul source learning [11] – Data synchronization strategy HTTP long poll synchronization
  • Soul source learning [12] – Data Synchronization strategy HTTP long Poll synchronization (2)
  • Soul source learning [13] – data synchronization strategy comparison