当前位置:网站首页>Research on data registration and synchronous data flow of soul gateway

Research on data registration and synchronous data flow of soul gateway

2021-01-23 22:59:40 A real loser

Soul The gateway Http/SpringMvc Data registration and synchronous data flow

Soul-Admin Research on the data of the end user

Start the client project first soul-examples-http The console will output and
file
It's obvious that this message is our annotation @SoulSpringMvcClient Interface information , So where did this operation come from .
Global search register success word . Found in soul-examples-http Dependent subprojects soul-client-springmvc There is a corresponding SpringMvcClientBeanPostProcessor To register , This SpringMvcClientBeanPostProcessor Realized Spring Of BeanPostProcessor Interface , If we want to Spring Done in container bean Instantiation 、 Add some logic processing before and after configuration and other initialization methods . We need to define one or more BeanPostProcessor Interface implementation class , And then register to Spring IoC In the container . So here is soul The client registers the data with soul-admin Entrance ,
So I did breakpoint debugging here , Let's see what interface he registered with to pass data to soul-admin Projects and gateways ,
file
You can see http The project is in the console project http://localhost:9095/soul-client/springmvc-register The interface is registered .
Then we go to this interface

    /**
     * Register spring cloud string.
     *
     * @param springCloudRegisterDTO the spring cloud register dto
     * @return the string
     */
    @PostMapping("/springcloud-register")
    public String registerSpringCloud(@RequestBody final SpringCloudRegisterDTO springCloudRegisterDTO) {
        return soulClientRegisterService.registerSpringCloud(springCloudRegisterDTO);
    }

Go deep into the service You can see that the application data is used in the previous section Spring The event handling mechanism of
file
Then the breakpoint goes into implementation Spring Event monitoring interface for ApplicationListener Event distribution class for DataChangedEventDispatcher
file
You can see , When I started, because I didn't add plug-ins , So it's time to enter SELECTOR In the breakpoint , Because at this time I choose zookeepr As a component of data synchronization . I have found the ZookeeperDataChangedListener Break point in , We found that data synchronization is to put data into zookeeper
file

    private void createZkNode(final String path) {
        if (!zkClient.exists(path)) {
            zkClient.createPersistent(path, true);
        }
    }
    
    /**
     * create or update zookeeper node.
     * @param path node path
     * @param data node data 
     */
    private void upsertZkNode(final String path, final Object data) {
        if (!zkClient.exists(path)) {
            zkClient.createPersistent(path, true);
        }
        zkClient.writeData(path, data);
    }
    
    private void deleteZkPath(final String path) {
        if (zkClient.exists(path)) {
            zkClient.delete(path);
        }
    }
    
    private void deleteZkPathRecursive(final String path) { 
        if (zkClient.exists(path)) {
            zkClient.deleteRecursive(path);
        }
    }

zookeeper The process of writing nodes and updating data is as above

Soul-Boostrap Research on the data of the end user

open soul-boostrap You can see . There are few classes , Only two. . One SoulNettyWebServerFactory and HealthFilter.HealthFilter It's for service health check-up . and SoulNettyWebServerFactory Namely spring webflux Application of a responsive Server Factory . You can go to see the details https://www.jianshu.com/p/ada196969995 This article
But at this time, we still didn't reach what we wanted to forward . Go to pom The core Gateway project is found in the file soul-spring-boot-starter-gateway But I found that none of the classes , But it depends on soul-web modular , So right. soul-web Module to understand
First you can see the configuration class SoulConfiguration,

   /**
     * Init SoulWebHandler.
     *
     * @param plugins this plugins is All impl SoulPlugin.
     * @return {@linkplain SoulWebHandler}
     */
    @Bean("webHandler")
    public SoulWebHandler soulWebHandler(final ObjectProvider<List<SoulPlugin>> plugins) {
        List<SoulPlugin> pluginList = plugins.getIfAvailable(Collections::emptyList);
        final List<SoulPlugin> soulPlugins = pluginList.stream()
                .sorted(Comparator.comparingInt(SoulPlugin::getOrder)).collect(Collectors.toList());
        soulPlugins.forEach(soulPlugin -> log.info("load plugin:[{}] [{}]", soulPlugin.named(), soulPlugin.getClass().getName()));
        return new SoulWebHandler(soulPlugins);
    }

You can see here , Loaded a webhandler The processor of , The main content of the processor

    public SoulWebHandler(final List<SoulPlugin> plugins) {
        this.plugins = plugins;
        String schedulerType = System.getProperty("soul.scheduler.type", "fixed");
        if (Objects.equals(schedulerType, "fixed")) {
            int threads = Integer.parseInt(System.getProperty(
                    "soul.work.threads", "" + Math.max((Runtime.getRuntime().availableProcessors() << 1) + 1, 16)));
            scheduler = Schedulers.newParallel("soul-work-threads", threads);
        } else {
            scheduler = Schedulers.elastic();
        }
    }
    
    /**
     * Handle the web server exchange.
     *
     * @param exchange the current server exchange
     * @return {@code Mono<Void>} to indicate when request handling is complete
     */
    @Override
    public Mono<Void> handle(@NonNull final ServerWebExchange exchange) {
        MetricsTrackerFacade.getInstance().counterInc(MetricsLabelEnum.REQUEST_TOTAL.getName());
        Optional<HistogramMetricsTrackerDelegate> startTimer = MetricsTrackerFacade.getInstance().histogramStartTimer(MetricsLabelEnum.REQUEST_LATENCY.getName());
        return new DefaultSoulPluginChain(plugins).execute(exchange).subscribeOn(scheduler)
                .doOnSuccess(t -> startTimer.ifPresent(time -> MetricsTrackerFacade.getInstance().histogramObserveDuration(time)));
    }

The main content is to use the chain of responsibility to process the number of threads requested .handle Method to process the request
according to soul-example-springmvc Comment on the request . On the basis of abstraction AbstractSoulPlugin Accept this request

    @Override
    public Mono<Void> execute(final ServerWebExchange exchange, final SoulPluginChain chain) {
        String pluginName = named();
        final PluginData pluginData = BaseDataCache.getInstance().obtainPluginData(pluginName);
        if (pluginData != null && pluginData.getEnabled()) {
            final Collection<SelectorData> selectors = BaseDataCache.getInstance().obtainSelectorData(pluginName);
            if (CollectionUtils.isEmpty(selectors)) {
                return handleSelectorIsNull(pluginName, exchange, chain);
            }
            final SelectorData selectorData = matchSelector(exchange, selectors);
            if (Objects.isNull(selectorData)) {
                return handleSelectorIsNull(pluginName, exchange, chain);
            }
            selectorLog(selectorData, pluginName);
            final List<RuleData> rules = BaseDataCache.getInstance().obtainRuleData(selectorData.getId());
            if (CollectionUtils.isEmpty(rules)) {
                return handleRuleIsNull(pluginName, exchange, chain);
            }
            RuleData rule;
            if (selectorData.getType() == SelectorTypeEnum.FULL_FLOW.getCode()) {
                //get last
                rule = rules.get(rules.size() - 1);
            } else {
                rule = matchRule(exchange, rules);
            }
            if (Objects.isNull(rule)) {
                return handleRuleIsNull(pluginName, exchange, chain);
            }
            ruleLog(rule, pluginName);
            return doExecute(exchange, chain, selectorData, rule);
        }
        return chain.execute(exchange);
    }

There are obvious rules and logic related to selector comparison , Used to determine whether the current request is in the gateway agent's request . But here it corresponds to , How can I get the selector data set above , I'll leave this for later
Then the breakpoint comes to the specific business request plug-in WebClientPlugin Execute the following business requests

    @Override
    public Mono<Void> execute(final ServerWebExchange exchange, final SoulPluginChain chain) {
        final SoulContext soulContext = exchange.getAttribute(Constants.CONTEXT);
        assert soulContext != null;
        String urlPath = exchange.getAttribute(Constants.HTTP_URL);
        if (StringUtils.isEmpty(urlPath)) {
            Object error = SoulResultWrap.error(SoulResultEnum.CANNOT_FIND_URL.getCode(), SoulResultEnum.CANNOT_FIND_URL.getMsg(), null);
            return WebFluxResultUtils.result(exchange, error);
        }
        long timeout = (long) Optional.ofNullable(exchange.getAttribute(Constants.HTTP_TIME_OUT)).orElse(3000L);
        int retryTimes = (int) Optional.ofNullable(exchange.getAttribute(Constants.HTTP_RETRY)).orElse(0);
        log.info("The request urlPath is {}, retryTimes is {}", urlPath, retryTimes);
        HttpMethod method = HttpMethod.valueOf(exchange.getRequest().getMethodValue());
        WebClient.RequestBodySpec requestBodySpec = webClient.method(method).uri(urlPath);
        return handleRequestBody(requestBodySpec, exchange, timeout, retryTimes, chain);
    }

As you can see from the above , The gateway's logic in proxy requests

problem

The remaining unsolved problems in this paper are mainly

  • How to go from abstractSoulPlugin After the execution WebClientPlugin In the same way , Is it chain of responsibility mode or other loading process
  • abstractSoulPlugin How to load the registered or modified selector and other data
  • plugin How does the execution method in get ServerWebExchange Related request data for

Reference article https://blog.csdn.net/u010084384/article/details/113010594

Welcome to search and pay attention to the wechat face-to-face program developed by me and friends 【 Interview assistant of big factory 】 And the official account 【 Micro view technology 】, And the summary of the classified interview questions https://github.com/zhendiao/JavaInterview

file
file

版权声明
本文为[A real loser]所创,转载请带上原文链接,感谢
https://chowdera.com/2021/01/20210123224508899J.html

随机推荐