和spring cloud/boot 学习如何管理自己的组件

案例,

功能:

需要写一个往kafka上报数据的组建。

当组建启动时,需要建立如下资源:

1, 和kafka建立若干条连接

2, 启动一个线程池

3, 启动上报一个缓冲区

问题如下:

1, 如何在spring工程中引入该组件,并注入到spring容器中

2, 如间接被引用到此JAR包(如 引用的工程有引用到此组建JAR),或只是想用到里面数据类型,并不打算用功能时,如何避免资源会随着引入而自行启动造成资源浪费

3, 组建的配置如何统一管理问题

4, 如何管理众多JAR包依赖,如, 此组建开发要用到kafka的0.11.0.2,有天需要升级到1.0.0

这些问题其实在spring cloud中都有比较好的解决方案,如 zuul, 后面也是仿造zuul的解决

一, 如何使该组建被spring工程引入

SPI方式,

如 zuul 的通过

\META-INF\spring.factories

进行引入 ,指定引导目录

org.springframework.boot.autoconfigure.EnableAutoConfiguration=org.springframework.cloud.netflix.zuul.ZuulServerAutoConfiguration,org.springframework.cloud.netflix.zuul.ZuulProxyAutoConfiguration

故 组建也定义如下

\META-INF\spring.factories

org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.zhenai.security.report.SecurityAutoConfiguration

在SecurityAutoConfiguration中,根据需要对bean进行初始化,和相关资源的启动。如 启动连接,启动本地线程池等。

但这里的问题是,只要引入了这个JAR包(包括间接引入该JAR包),那么所有工程都会平白无故的去连kafka,去启动一些无用的线程池

二, 如何屏蔽间接被引用到此JAR包的工程启动相关资源

解决这个问题,spring cloud和spring boot还稍有不同,先看spring cloud.

Marker方式

spring cloud标签模式

先看zuul是怎么做的, 如要在工程里启动ZUUL,一般会在main类里加入@EnableZuulProxy 标签,如下:

@SpringBootApplication
@EnableEurekaClient
@EnableZuulProxy
public class Application {
...  ....
}

需要引入@EnableZuulProxy 标签

@EnableZuulProxy的源码如下 :

@EnableCircuitBreaker
@EnableDiscoveryClient
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Import(ZuulProxyMarkerConfiguration.class)
public @interface EnableZuulProxy {
}

看到 @Import(ZuulProxyMarkerConfiguration.class), ZuulProxyMarkerConfiguration只做了一件事,引入一个maker标签

如下:

@Configuration
public class ZuulProxyMarkerConfiguration {
    @Bean
    public Marker zuulProxyMarkerBean() {
        return new Marker();
    }

    class Marker {
    }
}

这个Maker对象用作是否启动启用该配置,从而控制了资源是否启动,如 ZuulServerAutoConfiguration

@Configuration
@EnableConfigurationProperties({ ZuulProperties.class })
@ConditionalOnClass(ZuulServlet.class)
@ConditionalOnBean(ZuulServerMarkerConfiguration.Marker.class)
// Make sure to get the ServerProperties from the same place as a normal web app would
@Import(ServerPropertiesAutoConfiguration.class)
public class ZuulServerAutoConfiguration {
...  ...
}

根据是否有Marker进行相关类的注入,是否启动。

故:

此处,案例中的组件也选用了这种方式,如

@EnableZASecurityReport 标签

当需要启动时,在main类里加入标签即可,如

@EnableZASecurityReport
public class Application {

...  ....

}

后续kafka的连接类,线程池,缓冲区等是否分配都可以根据相关标识进行管理,如spi入口类SecurityAutoConfiguration :

@Configuration
@EnableConfigurationProperties({ SecurityReportProperties.class })
@ConditionalOnBean(SecurityProxyMarkerConfiguration.Marker.class)
public class SecurityAutoConfiguration {
...  ...
}

这样,如果在main启动类中,只要未加入@EnableZASecurityReport,那么即使引入了组件的JAR包,相关资源也不会被启动。

starter方式

还有一种方式,即,spring boot用的比较多的start方式

spring boot的所有配置都在spring-boot-autoconfigure/META-INF/spring.factories里,通过@ConditionalOnBean特定类是否引入来判断是否启动资源。

如: spring-boot-starter-data-redis

首先通过spring.factories,引入Redis的引导类

org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,org.springframework.boot.autoconfigure.data.redis.RedisReactiveAutoConfiguration,org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration,\

如:

RedisAutoConfiguration

@Configuration
@ConditionalOnClass({ RedisOperations.class })
@EnableConfigurationProperties(RedisProperties.class)
@Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class })
public class RedisAutoConfiguration {
 ... ...
}

当工程需要用到Redis时,通过Maven引入相关类

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-redis</artifactId>
</dependency>

spring-boot-starter-data-redis, 其实是一个空项目,有个spring.provides,通过它引入redis相关的JAR包,然后使@ConditionalOnClass生效,从而完成对Redis的JAR环境的初始化。

三, 配置如何统一管理问题

一个组件(JAR包)出来后,配置会比较多,比如该项目涉及到kafka配置,线程池配置等一大堆,传统方式是去写个相关说明文档,一堆配置项会让使用起来很是麻烦。

1, 约定优于配置

在spring cloud/boot中,最让人好用的就是 约定优于配置。记住约定,少写配置

如在zuul中, 只需要配置几个必须项,其它都是约定项

如,约定配置文件即application.yml( 或 bootstrap.yml):

zuul:
 debug:
  routes:
    ZHENAI-CLIENT:
      path: /test/**

简单配置下routes就可以启动,如果要找到zuul的配置的约定值,可以直接寻找总配置类ZuulProperties,

ZuulProperties里,包含了所有配置项,并通过配置对象的方式进行模块话的划分如:

ZuulRoute相关,Host相关,HystrixSemaphore相关等

(也是一种默认约定)

故,

在组件中,也可以模仿简化下配置。 此组件核心功能就是上报,比配项目应该只是kafka的地址,要启用,只需要

report.kafkaConfig.servers=X.X.X.X:9092

即可,若要详细配置,和约定值,用一个统一配置文件管 ReportProperties.java

里面注明约定配置的值

2,运用spring的自动装配功能

运用@ConfigurationProperties标签进行自动装配。这个所有基本功能不细说。

详细可查看ZuulProperties里。

好处在于:

1, 可以实现动态配置,如 配置 map,list,甚至enums等

2,如果配合spring cloud config,可以实现动态热更新

四,统一管理JAR包的依赖

参考spring cloud/boot 里,JAR文件统一在spring-boot-dependencies的项目里单独管理,而版本间的兼容,依靠了开源项目http://platform.spring.io/platform/ 来做管理,故很少存在版本冲突。

作为自研的组件,最好依赖到的第三方jar都由spring boot去同理管理版本号,而需要用到的其它jar,可用建立个dependencies项目单独管理起来,不再自己工程能写版本号,方便统一升级维护。

总结下:

1,  如何给spring /spring boot 项目提供组件会比较好

用SPI方式,方便平滑引用

2,如何避免不需要用到组件的项目误引用JAR后,自动启动组件相关资源

1, 提供@EnableXXX标签模式,注入一个marker标签,在启动时通过@ConditionalOnBean来判断

2,starter方式,配置与类分开,@ConditionalOnBean来判断,同时引用时才启动会

3,组件的配置如何统一管理

1, 约定大于配置,简化配置。 为每个组件统一一个组件的XXXProperties.java,并提供约定值

2,自动装配模式

4, 如何统一管理JAR包,防止JAR版本冲突等

交给spring boot统一管理,其它版本号统一在父工程(或加入dependencies工程) 管理版本

加个广告,新的一年,打算把公众号维护起来,质量做起来。

欢迎关注下,谢谢

原文地址:https://www.cnblogs.com/springsource/p/8440986.html

时间: 2024-07-30 05:30:45

和spring cloud/boot 学习如何管理自己的组件的相关文章

《Spring Cloud》学习(一) 服务治理!

原文:http://www.cnblogs.com/crazycheng/p/10826283.html前言:之前网上学习过Spring Cloud,对于工作上需要是足够了,总归对于一些方面一知半解,最近难得有些闲暇时间,有幸读了崔永超先生的<Spring Cloud 微服务实战>,一方面记录下自己的学习历程和读后感,一方面分享下自己对Spring Cloud微服务的一些见解,写下此文. 注意:本文着重于描述Spring Cloud运行的机制和原理部分,不会涉及到过多的代码,不会演示如何搭建注

spring cloud深入学习(三)-----服务消费

在上一篇博文中简单实现了eureka-server以及eureka-provider,后面会实现eureka-cosumer,现在针对eureka做进一步的详解. 微服务整体架构 文字再美也没有图片直观,下面通过一张图来说明微服务的整体架构以及调用过程,如下: 服务注册中心-1和服务注册中心-2互相组成了高可用集群:服务提供者启动了两个实例,一个注册到服务注册中心-1上,另外一个注册到服务注册中心-2上:两个服务消费者,也都分别指向了一个注册中心. 服务提供者 1.服务注册 服务提供者在启动的时

spring cloud深入学习(七)-----配置中心git示例

随着线上项目变的日益庞大,每个项目都散落着各种配置文件,如果采用分布式的开发模式,需要的配置文件随着服务增加而不断增多.某一个基础服务信息变更,都会引起一系列的更新和重启,运维苦不堪言也容易出错.配置中心便是解决此类问题的灵丹妙药. 市面上开源的配置中心有很多,BAT每家都出过,360的QConf.淘宝的diamond.百度的disconf都是解决这类问题.国外也有很多开源的配置中心Apache的Apache Commons Configuration.owner.cfg4j等等.这些开源的软件

spring cloud深入学习(八)-----配置中心svn示例和refresh

svn版本 同样先示例server端的代码,基本步骤一样. 1.添加依赖 <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-config-server</artifactId> </dependency> <dependency> <groupId>org

spring cloud深入学习(十一)-----服务网关zuul

前面的文章我们介绍了,Eureka用于服务的注册于发现,Feign支持服务的调用以及均衡负载,Hystrix处理服务的熔断防止故障扩散,Spring Cloud Config服务集群配置中心,似乎一个微服务框架已经完成了. 我们还是少考虑了一个问题,外部的应用如何来访问内部各种各样的微服务呢?在微服务架构中,后端服务往往不直接开放给调用端,而是通过一个API网关根据请求的url,路由到相应的服务.当添加API网关后,在第三方调用端和服务提供方之间就创建了一面墙,这面墙直接与调用方通信进行权限控制

spring cloud深入学习(六)-----熔断监控Hystrix Dashboard和Turbine

Hystrix-dashboard是一款针对Hystrix进行实时监控的工具,通过Hystrix Dashboard我们可以在直观地看到各Hystrix Command的请求响应时间, 请求成功率等数据.但是只使用Hystrix Dashboard的话, 你只能看到单个应用内的服务信息, 这明显不够. 我们需要一个工具能让我们汇总系统内多个服务的数据并显示到Hystrix Dashboard上, 这个工具就是Turbine. Hystrix Dashboard 该demo基于本人之前的eurek

spring cloud深入学习(十二)-----Spring Cloud Zuul网关 Filter、熔断、重试、高可用的使用方式

Zuul的核心 Filter是Zuul的核心,用来实现对外服务的控制.Filter的生命周期有4个,分别是“PRE”.“ROUTING”.“POST”.“ERROR”,整个生命周期可以用下图来表示. Zuul大部分功能都是通过过滤器来实现的,这些过滤器类型对应于请求的典型生命周期. PRE: 这种过滤器在请求被路由之前调用.我们可利用这种过滤器实现身份验证.在集群中选择请求的微服务.记录调试信息等. ROUTING:这种过滤器将请求路由到微服务.这种过滤器用于构建发送给微服务的请求,并使用Apa

docker kubernetes swarm spring cloud结合学习资源

http://www.docin.com/p-2062732301.html https://blog.csdn.net/michael_hm/article/details/79213839 https://www.zhihu.com/question/55391506 https://www.zhihu.com/question/61403505 https://yq.aliyun.com/articles/73491?spm=a2c4e.11153940.blogcont73493.8.1

SpringCloud学习(六)分布式配置中心(Spring Cloud Config)(Finchley版本)

在上一篇文章讲述zuul的时候,已经提到过,使用配置服务来保存各个服务的配置文件.它就是Spring Cloud Config. 简介 在分布式系统中,由于服务数量巨多,为了方便服务配置文件统一管理,实时更新,所以需要分布式配置中心组件.在Spring Cloud中,有分布式配置中心组件spring cloud config ,它支持配置服务放在配置服务的内存中(即本地),也支持放在远程Git仓库中.在spring cloud config 组件中,分两个角色,一是config server,二