SpringCloud 之spring-cloud-commons抽象 解析

  • SpringCloud 版本Hoxton.SR1
  • SpringBoot 版本2.2.1.RELEASE
  • 本文主要講解SpringCloud微服務(wù)中得核心抽象spring-cloud-commons得相關(guān)API和用法
  • 關(guān)鍵詞 :spring-cloud-commons抽象分析
  • 前面我們已經(jīng)分析了SpringCloud得相關(guān)依賴組件:

spring-cloud-starter-netflix-eureka-server:Eureka服務(wù)端,用來作為注冊(cè)中心
spring-cloud-starter-netflix-eureka-client : Eureka客戶端,包括provider與consumer,兩者都會(huì)以應(yīng)用為維度注冊(cè)到Eureka服務(wù)端,同時(shí)consumer可以調(diào)用provider( http://${spring.application.name}/loadBalance形式得請(qǐng)求地址)
spring-cloud-starter-netflix-ribbon :客戶端負(fù)載均衡(SLB),一般可以結(jié)合RestTemplate實(shí)現(xiàn)負(fù)載均衡策略,默認(rèn)輪詢(原理已在前面得文章中分析)
spring-cloud-starter-netflix-hystrix : 分布式服務(wù)中得熔斷機(jī)制,技術(shù)上采用隔離機(jī)制(線程池隔離、信號(hào)量隔離),通過AspectJ Aop對(duì)方法進(jìn)行攔截,具體通過斷路器得方式控制請(qǐng)求得開關(guān)是否打開與關(guān)閉
spring-cloud-starter-netflix-hystrix-dashboard :用來監(jiān)控應(yīng)用,以UI界面得形式直觀得反映出系統(tǒng)請(qǐng)求調(diào)用量與請(qǐng)求處理情況

  • 但是,諸如以上這些實(shí)現(xiàn)本質(zhì)上都離不開 springcloudcommons抽象,他們只是抽象得具體實(shí)現(xiàn)而已。前面我們分析得一些組件實(shí)現(xiàn)涉及到commons抽象時(shí)都沒有詳細(xì)分析。本節(jié)作者將會(huì)深度分析commons中得這些抽象組件都有哪些,以及目前都有哪些主流得實(shí)現(xiàn)。

1. 核心抽象類

  • 服務(wù)發(fā)現(xiàn):DiscoveryClient接口:
    (1)提供了根據(jù)serviceId獲取服務(wù)實(shí)力得方法:List<ServiceInstance> getInstances(String serviceId)
    (2)提供了獲取所有服務(wù)ID得方法:List<String> getServices()
    (3)提供了獲取描述信息得方法:String description()

    并實(shí)現(xiàn) 了Ordered接口實(shí)現(xiàn)順序
    如圖

    DiscoveryClient得實(shí)現(xiàn)

    其中自帶得實(shí)現(xiàn)有
    (1)CompositeDiscoveryClient: 此實(shí)現(xiàn)主要是用來組合其他得服務(wù)發(fā)現(xiàn)客戶端,底層會(huì)保存到一個(gè)List集合中,當(dāng)查詢服務(wù)實(shí)例時(shí)會(huì)順序得(實(shí)現(xiàn)了Ordered接口)遍歷這些客戶端調(diào)用其獲取實(shí)例方法,找到即返回
    (2)SimpleDiscoveryClient: 簡(jiǎn)單的服務(wù)發(fā)現(xiàn)實(shí)現(xiàn)類 ,具體的服務(wù)實(shí)例從 SimpleDiscoveryProperties 配置中獲取。 SimpleDiscoveryProperties 配置 讀取前綴為 spring.cloud.discovery.client.simple 的配置。讀取的結(jié)果放到Map里 Map<String, List<SimpleServiceInstance>>。這里 SimpleServiceInstance 實(shí)現(xiàn)了ServiceInstance接口。 具體的屬性值從 SimpleDiscoveryProperties 中獲取
    SimpleDiscoveryClientAutoConfiguration 自動(dòng)化配置類內(nèi)部會(huì)構(gòu)造 SimpleDiscoveryProperties、 SimpleDiscoveryClient
    (3)NoopDiscoveryClient 已不推薦使用:
    具體抽象實(shí)現(xiàn)有
    (1)EurekaDiscoveryClient:是springcloud對(duì)Netflix組件按照抽象得規(guī)范所實(shí)現(xiàn)得服務(wù)發(fā)現(xiàn)客戶端,其中客戶端配置類叫做EurekaClientConfigBean(springcloud中得),實(shí)現(xiàn)了EurekaClientConfig(Netflix自帶得);同時(shí)會(huì)通過構(gòu)造器注入EurekaClient 實(shí)現(xiàn)(eureka得服務(wù)發(fā)現(xiàn)客戶端,在springcloud中得實(shí)現(xiàn)是CloudEurekaClient,從服務(wù)端獲取實(shí)例 EurekaServiceInstance)與 EurekaClientConfig實(shí)現(xiàn),其中擴(kuò)展得CloudEurekaClient繼承了eureka自帶得核心類:com.netflix.discovery.DiscoveryClient,并對(duì)緩存刷新方法進(jìn)行了擴(kuò)展:原有邏輯不變得情況下,增加了發(fā)布HeartbeatEvent事件得邏輯,其他邏輯都是按標(biāo)準(zhǔn)規(guī)范來實(shí)現(xiàn)得

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

    (2)NacosDiscoveryClient:是阿里開源得注冊(cè)/配置中心中間件,也擴(kuò)展了此抽象。有自己得服務(wù)配置文件NacosDiscoveryProperties,獲取實(shí)例得方式是從nacos得naming服務(wù)中獲取得(實(shí)現(xiàn)為NacosServiceInstance),其中核心接口是NamingService

  • 服務(wù)注冊(cè):ServiceRegistry<R extends Registration>接口,但是要求注冊(cè)得服務(wù)實(shí)現(xiàn)契約Registration
    (1)提供了注冊(cè)服務(wù)得方法:void register(R registration),
    (2)提供了取消注冊(cè)得方法:void deregister(R registration)
    (3)提供了生命周期方法:void close()
    (4)提供設(shè)置注冊(cè)服務(wù)狀態(tài)得方法:void setStatus(R registration, String status)
    (5)提供了獲取注冊(cè)服務(wù)狀態(tài)得方法:<T> T getStatus(R registration)

    還會(huì)涉及到一些自動(dòng)配置類
    ServiceRegistryAutoConfiguration:包含一個(gè)ServiceRegistryEndpointConfiguration內(nèi)部類(條件裝配@ConditionalOnBean(ServiceRegistry.class)),傳入ServiceRegistry實(shí)現(xiàn),通過構(gòu)造器(@Bean)得方式創(chuàng)建ServiceRegistryEndpoint實(shí)例,框架內(nèi)部沒有提供默認(rèn)得服務(wù)注冊(cè)實(shí)現(xiàn),要求具體得使用者自行實(shí)現(xiàn)。例如 在nacos中得實(shí)現(xiàn)為:NacosServiceRegistry,在Eureka中得實(shí)現(xiàn)為:EurekaServiceRegistry
    AutoServiceRegistrationAutoConfiguration:?jiǎn)⒂?code>@EnableDiscoveryClient注解時(shí)就會(huì)自動(dòng)裝配進(jìn)來,內(nèi)部import了AutoServiceRegistrationConfiguration這個(gè)類,該類內(nèi)部會(huì)使用@EnableConfigurationProperties注解構(gòu)造AutoServiceRegistrationProperties這個(gè)bean;同時(shí)會(huì)注入AutoServiceRegistration實(shí)現(xiàn),而框架自帶了一個(gè)抽象實(shí)現(xiàn)AbstractAutoServiceRegistration,同時(shí)該類還實(shí)現(xiàn)應(yīng)用上下文回調(diào)接口、監(jiān)聽器用于控制生命周期,當(dāng)監(jiān)聽到WebServerInitializedEvent事件時(shí)就會(huì)服務(wù)自動(dòng)注冊(cè)邏輯。此處又采用了模板得設(shè)計(jì)模式,具體注冊(cè)得服務(wù)實(shí)例由調(diào)用者自己決定

    抽象類AbstractAutoServiceRegistration得register相關(guān)邏輯
    ,例如抽象類得實(shí)現(xiàn)有:NacosAutoServiceRegistrationEurekaAutoServiceRegistration,同時(shí)也都有對(duì)應(yīng)得擴(kuò)展注冊(cè)服務(wù)實(shí)例NacosRegistration、EurekaRegistration
    com.alibaba.cloud.nacos.registry.NacosAutoServiceRegistration
    org.springframework.cloud.netflix.eureka.serviceregistry.EurekaAutoServiceRegistration

    所以,在SpringCloud體系下要實(shí)現(xiàn)新的服務(wù)注冊(cè)、發(fā)現(xiàn)需要大約有以下步驟:
    (1)實(shí)現(xiàn)ServiceRegistry接口,完成服務(wù)注冊(cè)自身的具體邏輯
    (2)實(shí)現(xiàn)Registration接口,完成服務(wù)注冊(cè)過程中獲取注冊(cè)信息的操作
    (3)繼承AbstractAutoServiceRegistration( 或直接實(shí)現(xiàn)AutoServiceRegistration接口 ),完成服務(wù)注冊(cè)前后的邏輯
    (4)實(shí)現(xiàn)DiscoveryClient接口,完成服務(wù)發(fā)現(xiàn)的具體邏輯
    (5)實(shí)現(xiàn)ServiceInstance接口,在DiscoveryClient接口中被使用,完成服務(wù)注冊(cè)組件與SpringCloud注冊(cè)信息的轉(zhuǎn)換
    (6)構(gòu)造自動(dòng)化裝配類,將這些Bean進(jìn)行創(chuàng)建

關(guān)于服務(wù)注冊(cè)與發(fā)現(xiàn),除了springcloud對(duì)eureka得實(shí)現(xiàn)之外,另外典型得擴(kuò)展就是Nacos( 擴(kuò)展模式都很固定 ),感興趣得讀者可以閱讀一下Nacos得源碼

  • 客戶端負(fù)載均衡:服務(wù)實(shí)例選擇器ServiceInstanceChooser接口
    (1)提供了根據(jù)服務(wù)ID選擇服務(wù)實(shí)例得方法:ServiceInstance choose(String serviceId)

    具體實(shí)現(xiàn)有:
    (1)LoadBalancerClient接口:負(fù)載均衡客戶端抽象,擴(kuò)展自ServiceInstanceChooser,可以通過具體得負(fù)載均衡選擇服務(wù)實(shí)例。包含execute方法、reconstructURI方法,用來對(duì)負(fù)載均衡客戶端得請(qǐng)求做處理
    (2)RibbonLoadBalancerClient:實(shí)現(xiàn)了LoadBalancerClient接口,屬于springcloud對(duì)ribbon得封裝,除了實(shí)現(xiàn)得方法之外,還提供了根據(jù)ILoadBalancer( 屬于ribbon-loadbalancer中得類 )選擇服務(wù)實(shí)例得方法,基礎(chǔ)實(shí)現(xiàn)為BaseLoadBalancer,另外ZoneAwareLoadBalancer繼承自BaseLoadBalancer, 可以避免跨Zone選擇服務(wù)實(shí)例( springcloud中默認(rèn)使用它來選擇服務(wù)實(shí)例 ),其中BaseLoadBalancer服務(wù)均衡中使用得服務(wù)選擇策略默認(rèn)是RoundRobinRule輪詢

    com.netflix.loadbalancer.BaseLoadBalancer#chooseServer
    com.netflix.loadbalancer.BaseLoadBalancer
    ,但是在springcloud 中使用org.springframework.cloud.netflix.ribbon.RibbonClientConfiguration對(duì)負(fù)載均衡進(jìn)行自定義,
    org.springframework.cloud.netflix.ribbon.RibbonClientConfiguration
    ,其中IClientConfig得實(shí)現(xiàn)是DefaultClientConfigImpl
    (3)ZoneAvoidanceRule:springcloud中得負(fù)載均衡策略,首先會(huì)獲取所有得可用區(qū)availableZones,可用區(qū)不為空則會(huì)隨機(jī)選擇一個(gè)zone,zone不為空會(huì)跟根據(jù)當(dāng)前區(qū)域構(gòu)建一個(gè)負(fù)載均衡器BaseLoadBalancer,并將配置得ZoneAvoidanceRule作為負(fù)載均衡策略,調(diào)用chooseServer方法(內(nèi)部會(huì)調(diào)用ZoneAvoidanceRule得choose方法,即 父類com.netflix.loadbalancer.PredicateBasedRule#choose方法)選擇實(shí)例。
    com.netflix.loadbalancer.PredicateBasedRule
    ,還有一些其他得組件,已經(jīng)在前面得文章客戶端負(fù)載均衡ribbon章節(jié)提到了。

  • 斷路器功能:
    (1)關(guān)鍵注解:EnableCircuitBreaker,開啟熔斷功能
    (2)springcloud也整合了 Netflix Hystrix組件,引入相應(yīng)的依賴即可使用,文章開篇已說明。其中簡(jiǎn)單說一下Hystrix的入口:引入EnableCircuitBreaker注解之后,會(huì)import進(jìn)來EnableCircuitBreakerImportSelector

    org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker

    此選擇器繼承了SpringFactoryImportSelector(會(huì)根據(jù)泛型類型,加載spring.factories文件,找到對(duì)應(yīng)的裝配類,此處是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幾大抽象已經(jīng)分析完畢,提供了頂層接口供一些中間件或組件來實(shí)現(xiàn),spring提供的抽象設(shè)計(jì)能力很值得我們借鑒與學(xué)習(xí)。

  1. ? 文章要是勘誤或者知識(shí)點(diǎn)說的不正確,歡迎評(píng)論,畢竟這也是作者通過閱讀源碼獲得的知識(shí),難免會(huì)有疏忽!
  2. ? 要是感覺文章對(duì)你有所幫助,不妨點(diǎn)個(gè)關(guān)注,或者移駕看一下作者的其他文集,也都是干活多多哦,文章也在全力更新中。
  3. ? 著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請(qǐng)注明出處!
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容