SpringCloud 之spring-cloud-commons抽象 解析

  • SpringCloud 版本Hoxton.SR1
  • SpringBoot 版本2.2.1.RELEASE
  • 本文主要讲解SpringCloud微服务中得核心抽象spring-cloud-commons得相关API和用法
  • 关键词 :spring-cloud-commons抽象分析
  • 前面我们已经分析了SpringCloud得相关依赖组件:

spring-cloud-starter-netflix-eureka-server:Eureka服务端,用来作为注册中心
spring-cloud-starter-netflix-eureka-client : Eureka客户端,包括provider与consumer,两者都会以应用为维度注册到Eureka服务端,同时consumer可以调用provider( http://${spring.application.name}/loadBalance形式得请求地址)
spring-cloud-starter-netflix-ribbon :客户端负载均衡(SLB),一般可以结合RestTemplate实现负载均衡策略,默认轮询(原理已在前面得文章中分析)
spring-cloud-starter-netflix-hystrix : 分布式服务中得熔断机制,技术上采用隔离机制(线程池隔离、信号量隔离),通过AspectJ Aop对方法进行拦截,具体通过断路器得方式控制请求得开关是否打开与关闭
spring-cloud-starter-netflix-hystrix-dashboard :用来监控应用,以UI界面得形式直观得反映出系统请求调用量与请求处理情况

  • 但是,诸如以上这些实现本质上都离不开 springcloudcommons抽象,他们只是抽象得具体实现而已。前面我们分析得一些组件实现涉及到commons抽象时都没有详细分析。本节作者将会深度分析commons中得这些抽象组件都有哪些,以及目前都有哪些主流得实现。

1. 核心抽象类

  • 服务发现:DiscoveryClient接口:
    (1)提供了根据serviceId获取服务实力得方法:List<ServiceInstance> getInstances(String serviceId)
    (2)提供了获取所有服务ID得方法:List<String> getServices()
    (3)提供了获取描述信息得方法:String description()

    并实现 了Ordered接口实现顺序
    如图

    DiscoveryClient得实现

    其中自带得实现有
    (1)CompositeDiscoveryClient: 此实现主要是用来组合其他得服务发现客户端,底层会保存到一个List集合中,当查询服务实例时会顺序得(实现了Ordered接口)遍历这些客户端调用其获取实例方法,找到即返回
    (2)SimpleDiscoveryClient: 简单的服务发现实现类 ,具体的服务实例从 SimpleDiscoveryProperties 配置中获取。 SimpleDiscoveryProperties 配置 读取前缀为 spring.cloud.discovery.client.simple 的配置。读取的结果放到Map里 Map<String, List<SimpleServiceInstance>>。这里 SimpleServiceInstance 实现了ServiceInstance接口。 具体的属性值从 SimpleDiscoveryProperties 中获取
    SimpleDiscoveryClientAutoConfiguration 自动化配置类内部会构造 SimpleDiscoveryProperties、 SimpleDiscoveryClient
    (3)NoopDiscoveryClient 已不推荐使用:
    具体抽象实现有
    (1)EurekaDiscoveryClient:是springcloud对Netflix组件按照抽象得规范所实现得服务发现客户端,其中客户端配置类叫做EurekaClientConfigBean(springcloud中得),实现了EurekaClientConfig(Netflix自带得);同时会通过构造器注入EurekaClient 实现(eureka得服务发现客户端,在springcloud中得实现是CloudEurekaClient,从服务端获取实例 EurekaServiceInstance)与 EurekaClientConfig实现,其中扩展得CloudEurekaClient继承了eureka自带得核心类:com.netflix.discovery.DiscoveryClient,并对缓存刷新方法进行了扩展:原有逻辑不变得情况下,增加了发布HeartbeatEvent事件得逻辑,其他逻辑都是按标准规范来实现得

    org.springframework.cloud.netflix.eureka.CloudEurekaClient#onCacheRefreshed

    (2)NacosDiscoveryClient:是阿里开源得注册/配置中心中间件,也扩展了此抽象。有自己得服务配置文件NacosDiscoveryProperties,获取实例得方式是从nacos得naming服务中获取得(实现为NacosServiceInstance),其中核心接口是NamingService

  • 服务注册:ServiceRegistry<R extends Registration>接口,但是要求注册得服务实现契约Registration
    (1)提供了注册服务得方法:void register(R registration),
    (2)提供了取消注册得方法:void deregister(R registration)
    (3)提供了生命周期方法:void close()
    (4)提供设置注册服务状态得方法:void setStatus(R registration, String status)
    (5)提供了获取注册服务状态得方法:<T> T getStatus(R registration)

    还会涉及到一些自动配置类
    ServiceRegistryAutoConfiguration:包含一个ServiceRegistryEndpointConfiguration内部类(条件装配@ConditionalOnBean(ServiceRegistry.class)),传入ServiceRegistry实现,通过构造器(@Bean)得方式创建ServiceRegistryEndpoint实例,框架内部没有提供默认得服务注册实现,要求具体得使用者自行实现。例如 在nacos中得实现为:NacosServiceRegistry,在Eureka中得实现为:EurekaServiceRegistry
    AutoServiceRegistrationAutoConfiguration:启用@EnableDiscoveryClient注解时就会自动装配进来,内部import了AutoServiceRegistrationConfiguration这个类,该类内部会使用@EnableConfigurationProperties注解构造AutoServiceRegistrationProperties这个bean;同时会注入AutoServiceRegistration实现,而框架自带了一个抽象实现AbstractAutoServiceRegistration,同时该类还实现应用上下文回调接口、监听器用于控制生命周期,当监听到WebServerInitializedEvent事件时就会服务自动注册逻辑。此处又采用了模板得设计模式,具体注册得服务实例由调用者自己决定

    抽象类AbstractAutoServiceRegistration得register相关逻辑
    ,例如抽象类得实现有:NacosAutoServiceRegistrationEurekaAutoServiceRegistration,同时也都有对应得扩展注册服务实例NacosRegistrationEurekaRegistration
    com.alibaba.cloud.nacos.registry.NacosAutoServiceRegistration
    org.springframework.cloud.netflix.eureka.serviceregistry.EurekaAutoServiceRegistration

    所以,在SpringCloud体系下要实现新的服务注册、发现需要大约有以下步骤:
    (1)实现ServiceRegistry接口,完成服务注册自身的具体逻辑
    (2)实现Registration接口,完成服务注册过程中获取注册信息的操作
    (3)继承AbstractAutoServiceRegistration( 或直接实现AutoServiceRegistration接口 ),完成服务注册前后的逻辑
    (4)实现DiscoveryClient接口,完成服务发现的具体逻辑
    (5)实现ServiceInstance接口,在DiscoveryClient接口中被使用,完成服务注册组件与SpringCloud注册信息的转换
    (6)构造自动化装配类,将这些Bean进行创建

关于服务注册与发现,除了springcloud对eureka得实现之外,另外典型得扩展就是Nacos( 扩展模式都很固定 ),感兴趣得读者可以阅读一下Nacos得源码

  • 客户端负载均衡:服务实例选择器ServiceInstanceChooser接口
    (1)提供了根据服务ID选择服务实例得方法:ServiceInstance choose(String serviceId)

    具体实现有:
    (1)LoadBalancerClient接口:负载均衡客户端抽象,扩展自ServiceInstanceChooser,可以通过具体得负载均衡选择服务实例。包含execute方法reconstructURI方法,用来对负载均衡客户端得请求做处理
    (2)RibbonLoadBalancerClient:实现了LoadBalancerClient接口,属于springcloud对ribbon得封装,除了实现得方法之外,还提供了根据ILoadBalancer( 属于ribbon-loadbalancer中得类 )选择服务实例得方法,基础实现为BaseLoadBalancer,另外ZoneAwareLoadBalancer继承自BaseLoadBalancer, 可以避免跨Zone选择服务实例( springcloud中默认使用它来选择服务实例 ),其中BaseLoadBalancer服务均衡中使用得服务选择策略默认是RoundRobinRule轮询

    com.netflix.loadbalancer.BaseLoadBalancer#chooseServer
    com.netflix.loadbalancer.BaseLoadBalancer
    ,但是在springcloud 中使用org.springframework.cloud.netflix.ribbon.RibbonClientConfiguration对负载均衡进行自定义,
    org.springframework.cloud.netflix.ribbon.RibbonClientConfiguration
    ,其中IClientConfig得实现是DefaultClientConfigImpl
    (3)ZoneAvoidanceRule:springcloud中得负载均衡策略,首先会获取所有得可用区availableZones,可用区不为空则会随机选择一个zone,zone不为空会跟根据当前区域构建一个负载均衡器BaseLoadBalancer,并将配置得ZoneAvoidanceRule作为负载均衡策略,调用chooseServer方法(内部会调用ZoneAvoidanceRule得choose方法,即 父类com.netflix.loadbalancer.PredicateBasedRule#choose方法)选择实例。
    com.netflix.loadbalancer.PredicateBasedRule
    ,还有一些其他得组件,已经在前面得文章客户端负载均衡ribbon章节提到了。

  • 断路器功能:
    (1)关键注解:EnableCircuitBreaker,开启熔断功能
    (2)springcloud也整合了 Netflix Hystrix组件,引入相应的依赖即可使用,文章开篇已说明。其中简单说一下Hystrix的入口:引入EnableCircuitBreaker注解之后,会import进来EnableCircuitBreakerImportSelector

    org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker

    此选择器继承了SpringFactoryImportSelector(会根据泛型类型,加载spring.factories文件,找到对应的装配类,此处是HystrixCircuitBreakerConfiguration)
    org.springframework.cloud.client.circuitbreaker.EnableCircuitBreakerImportSelector

    spring-cloud-netflix-hystrix依赖下面的spring.factories文件
    ,再看HystrixCircuitBreakerConfiguration配置类,如下:
    org.springframework.cloud.netflix.hystrix.HystrixCircuitBreakerConfiguration
    此类即是Hystrix切面代理的入口(AspectJ)

  • 至此,spring-cloud-commons几大抽象已经分析完毕,提供了顶层接口供一些中间件或组件来实现,spring提供的抽象设计能力很值得我们借鉴与学习。

  1. ☛ 文章要是勘误或者知识点说的不正确,欢迎评论,毕竟这也是作者通过阅读源码获得的知识,难免会有疏忽!
  2. 要是感觉文章对你有所帮助,不妨点个关注,或者移驾看一下作者的其他文集,也都是干活多多哦,文章也在全力更新中。
  3. 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处!
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342