欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Soul 网关(四)---- Plugin 的初始化流程分析 & Sofa 插件的使用

程序员文章站 2022-06-09 22:08:09
Plugin 的初始化流程分析 & Sofa 插件的使用Plugin 的初始化流程分析启动 soul-bootstrap 可以看到日志输出了加载的一些 plugin :2021-01-18 22:14:10.685 INFO 71824 --- [ main] o.d.s.w.configuration.SoulConfiguration : load plugin:[global] [org.dromara.soul.plugin.global.GlobalPlug...

Plugin 的初始化流程分析 & Sofa 插件的使用

Plugin 的初始化流程分析

启动 soul-bootstrap 可以看到日志输出了加载的一些 plugin :

2021-01-18 22:14:10.685  INFO 71824 --- [           main] o.d.s.w.configuration.SoulConfiguration  : load plugin:[global] [org.dromara.soul.plugin.global.GlobalPlugin]
2021-01-18 22:14:10.685  INFO 71824 --- [           main] o.d.s.w.configuration.SoulConfiguration  : load plugin:[sign] [org.dromara.soul.plugin.sign.SignPlugin]
2021-01-18 22:14:10.685  INFO 71824 --- [           main] o.d.s.w.configuration.SoulConfiguration  : load plugin:[waf] [org.dromara.soul.plugin.waf.WafPlugin]
2021-01-18 22:14:10.685  INFO 71824 --- [           main] o.d.s.w.configuration.SoulConfiguration  : load plugin:[rate_limiter] [org.dromara.soul.plugin.ratelimiter.RateLimiterPlugin]
2021-01-18 22:14:10.685  INFO 71824 --- [           main] o.d.s.w.configuration.SoulConfiguration  : load plugin:[hystrix] [org.dromara.soul.plugin.hystrix.HystrixPlugin]
2021-01-18 22:14:10.685  INFO 71824 --- [           main] o.d.s.w.configuration.SoulConfiguration  : load plugin:[resilience4j] [org.dromara.soul.plugin.resilience4j.Resilience4JPlugin]
2021-01-18 22:14:10.685  INFO 71824 --- [           main] o.d.s.w.configuration.SoulConfiguration  : load plugin:[divide] [org.dromara.soul.plugin.divide.DividePlugin]
2021-01-18 22:14:10.685  INFO 71824 --- [           main] o.d.s.w.configuration.SoulConfiguration  : load plugin:[webClient] [org.dromara.soul.plugin.httpclient.WebClientPlugin]
2021-01-18 22:14:10.685  INFO 71824 --- [           main] o.d.s.w.configuration.SoulConfiguration  : load plugin:[divide] [org.dromara.soul.plugin.divide.websocket.WebSocketPlugin]
2021-01-18 22:14:10.685  INFO 71824 --- [           main] o.d.s.w.configuration.SoulConfiguration  : load plugin:[alibaba-dubbo-body-param] [org.dromara.soul.plugin.alibaba.dubbo.param.BodyParamPlugin]
2021-01-18 22:14:10.685  INFO 71824 --- [           main] o.d.s.w.configuration.SoulConfiguration  : load plugin:[sofa] [org.dromara.soul.plugin.sofa.SofaPlugin]
2021-01-18 22:14:10.685  INFO 71824 --- [           main] o.d.s.w.configuration.SoulConfiguration  : load plugin:[dubbo] [org.dromara.soul.plugin.alibaba.dubbo.AlibabaDubboPlugin]
2021-01-18 22:14:10.685  INFO 71824 --- [           main] o.d.s.w.configuration.SoulConfiguration  : load plugin:[monitor] [org.dromara.soul.plugin.monitor.MonitorPlugin]
2021-01-18 22:14:10.685  INFO 71824 --- [           main] o.d.s.w.configuration.SoulConfiguration  : load plugin:[response] [org.dromara.soul.plugin.sofa.response.SofaResponsePlugin]
2021-01-18 22:14:10.685  INFO 71824 --- [           main] o.d.s.w.configuration.SoulConfiguration  : load plugin:[response] [org.dromara.soul.plugin.httpclient.response.WebClientResponsePlugin]
2021-01-18 22:14:10.685  INFO 71824 --- [           main] o.d.s.w.configuration.SoulConfiguration  : load plugin:[response] [org.dromara.soul.plugin.alibaba.dubbo.response.DubboResponsePlugin]

根据关键字 ‘load plugin’ 我们可以定位到 SoulConfiguration 这个配置类 的 @Bean(“webHandler”)

@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);
    }

那么为什么启动 soul-bootstrap 会去初始化 @Bean(“webHandler”) 这个Bean 呢?---- 不难发现,SoulConfiguration 类上面加了 组件扫描: @ComponentScan(“org.dromara.soul”),所以会扫描并初始化 org.dromara.soul 包下所有的 Bean

/**
 * SoulConfiguration.
 *
 * @author xiaoyu(Myth)
 */
@Configuration
@ComponentScan("org.dromara.soul")
@Import(value = {ErrorHandlerConfiguration.class, SoulExtConfiguration.class, SpringExtConfiguration.class})
@Slf4j
public class SoulConfiguration {...}

我们再来看 soul-bootstrap 的代码,soul-bootstrap 里定义了 bean(在SoulNettyWebServerFactory类),通过初始化这个 bean 来创建了一个 Netty Server。

    /**
     * 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);
    }

那么 soul-bootstrap 启动日志里打印的 10 多个 plugin 是何时初始化好的呢?

带着这个问题,我在创建 Netty Server 的地方加了一个断点,然后查看 beanFactory
Soul 网关(四)---- Plugin 的初始化流程分析 & Sofa 插件的使用
在 beanFactory 我们可以看到 Spring 已经装载了很多插件的配置类。以 SofaPluginConfiguration 为例,我们可以发现,每一个插件都自定了一个 starter,starter 的 spring.factories 文件里都指定了 自动配置:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.dromara.soul.spring.boot.starter.plugin.sofa.SofaPluginConfiguration

Soul 网关(四)---- Plugin 的初始化流程分析 & Sofa 插件的使用

而 soul-bootstrap 的 pom 文件里也引入了这些插件的starter依赖,详见 soul-bootstrap 的pom文件,这里只贴出来 divide 插件的 starter 依赖:

		<!--if you use http proxy start this-->
        <dependency>
            <groupId>org.dromara</groupId>
            <artifactId>soul-spring-boot-starter-plugin-divide</artifactId>
            <version>${project.version}</version>
        </dependency>
        <dependency>
            <groupId>org.dromara</groupId>
            <artifactId>soul-spring-boot-starter-plugin-httpclient</artifactId>
            <version>${project.version}</version>
        </dependency>
        <!--if you use http proxy end this-->

所以为什么 sofa 插件跑起来后,请求不会转发到 soul-examples-sofa 这个项目?因为 soul-bootstrap 的 pom 文件里是没有 sofa 的starter 依赖,也就无法将 sofa 插件这个bean初始化,要解决这个问题,只要在 soul-bootstrap 的 pom 文件里加入 sofa 的starter依赖即可。

sofa starter依赖:

		<dependency>
            <groupId>com.alipay.sofa</groupId>
            <artifactId>sofa-rpc-all</artifactId>
            <version>5.7.6</version>
        </dependency>
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-client</artifactId>
            <version>4.0.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-framework</artifactId>
            <version>4.0.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-recipes</artifactId>
            <version>4.0.1</version>
        </dependency>
        <dependency>
            <groupId>org.dromara</groupId>
            <artifactId>soul-spring-boot-starter-plugin-sofa</artifactId>
            <version>${project.version}</version>
        </dependency>

因为每个 Plugin 都实现了 SoulPlugin 这个类(相当于都是 SoulPlugin 类型),并且每个Plugin做为一个个的bean都已经自动初始化好,所以这里可以用 List 来接收找出来的所有 Plugin beans。

	@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);
    }

Sofa 插件的使用

在 soul-bootstrap 的 pom 文件里加上了 sofa 的 starter 依赖,启动 soul-admin,soul-bootstrap 以及 example 下的 sofa-test,访问 http://localhost:9195/sofa/findAll,便可以成功访问到 sofa-test 了:
Soul 网关(四)---- Plugin 的初始化流程分析 & Sofa 插件的使用

总结

  1. 通过在自定义 starter 的 spring.factories 文件中开启 AutoConfig,可以帮助主项目(soul-bootstrap)以外的bean(即在pom文件中添加依赖中的bean)装载到 spring 容器,从而实现启动 bootstrap 时将插件都初始化好。

本文地址:https://blog.csdn.net/wu2304211/article/details/112798222

相关标签: Soul 网关源码