天天看點

Spring Cloud Alibaba釋出第二個版本,Spring 發來賀電

還是熟悉的面孔,還是熟悉的味道,不同的是,這次的配方更新了。

今年10月底,Spring Cloud聯合創始人Spencer Gibb在Spring官網的部落格頁面宣布:阿裡巴巴開源 Spring Cloud Alibaba,并釋出了首個預覽版本。随後,Spring Cloud 官方Twitter也釋出了此消息。- 傳送門

時隔 51天,Spencer Gibb再次在Spring官網的部落格頁面宣布:Spring Cloud Alibaba釋出了其開源後的第二個版本0.2.1,随後,Spring Cloud 官方Twitter也轉發了此消息。聖誕節的前一周,Josh Long向他的老朋友許曉斌發來賀電:

小編翻譯:

聽聞阿裡巴巴官方宣布使用Spring Cloud,我開心的一晚上沒睡着,下周三我會在Spring Tips小視訊裡介紹Spring Cloud Alibaba。

聖誕快樂,老哥!

愛你

視訊位址

新版本概要

  • 增加了兩個新的子產品, spring-cloud-alibaba-schedulerx 和 spring-cloud-stream-binder-rocketmq 。
  • 在 spring-cloud-alibaba-nacos 和 spring-cloud-alibaba-sentinel 中增加了一些新的 feature 。
  • 修複了之前版本的一些 bug 。
注意: 版本 0.2.1.RELEASE 對應的是 Spring Cloud Finchley 的版本。這次釋出也包含了一個适配 Spring Cloud Edgware 的版本 0.1.1.RELEASE,版本 0.1.1.RELEASE 也包含了 0.2.1.RELEASE 中新增的元件和特性。

Spring Cloud Alibaba RocketMQ

适配了 spring cloud stream 對于 message 抽象的 API。

支援事務消息。

Consumer 端支援以 tags、SQL表達式過濾消息。支援順序、并發以及廣播消費模式。

Spring Cloud Alibaba SchedulerX

  • 提供了秒級、精準、高可靠、高可用的定時任務排程服務。
  • 提供了豐富的任務執行模型,包括單機執行,廣播執行,以及子任務的分布式執行。

Spring Cloud Alibaba Nacos Config

  • 将Nacos Client 的版本更新到 0.6.2 版本。
  • 支援從多個 dataid 和 groupid 中擷取和監聽配置,并支援優先級指定。
  • 優化了 動态監聽的邏輯,隻有配置了動态重新整理的配置項才會實時重新整理。

Spring Cloud Alibaba Nacos Discovery

  • 支援在 Nacos Console 端将服務執行個體設定成不可用狀态,服務發現會自動過濾此節點。
  • 支援服務發現在初始化時不使用本地緩存。

Spring Cloud Alibaba Sentinel

  • 支援 Feign,相容了 @FeignClient 所有的屬性,包括 fallback、fallbackFactory。
  • 支援 熱點參數限流和叢集限流。
  • 重構了 ReadableDataSource 的設計,提供了更友好的配置 Sentinel 規則持久化的方式。
  • 優化了 Sentinel 對于 RestTemplate 的降級後的處理。
  • 調整并添加了一些 Sentinel 配置資訊對應的屬性,如日志目錄,日志檔案名等。

新版本背後的思考

Nacos Discovery 在這個版本最大的更新就是支援在初始化的時候不使用本地檔案緩存,目前初始化的時候已經預設不使用本地檔案緩存。

為什麼要有緩存?首先我們來了解一下本地緩存的概念,為什麼需要這個本地緩存?

我們都知道,服務注冊與發現應該隻是服務調用中的輔助性的一個環節,而不是一個關鍵的環節。一個良好的服務注冊與發現的設計,需要保證以下兩點。

服務注冊與發現隻是旁路,不應該參與具體的調用過程。

在服務的運作過程中,即使服務注冊中心偶然發生異常當機後,也盡量不影響正常的業務調用。

要實作以上兩點,緩存就不可或缺,而為了适應不同的場景,緩存又可以分成記憶體緩存和本地檔案緩存,他們的概念和适用場景如下。

  • 記憶體中的緩存

将服務提供者清單維護在記憶體中,每次調用時直接從記憶體中的清單擷取節點即可。記憶體緩存通過定時任務更新,或者在收到服務注冊中心的推送之後再更新。確定了即使在服務注冊中心當機的情況下,也能保證服務仍能正常調用。

  • 本地檔案緩存

将上述提到的記憶體中的緩存,保留在本地的某個檔案中,這樣在調用服務注冊中心失敗的時候,可以從本機的檔案緩存中擷取服務提供者清單。這樣就保證了在服務注冊中心當機的情況下,應用在重新開機後也能找到服務提供者。

  • 為什麼要關閉

    有了以上背景知識後,讀者可能會有疑問,既然緩存這麼好,你們為什麼預設要把它置為預設關閉呢?

我們在釋出出第一個版本之後,很多使用者回報,為什麼我服務下線之後還是有節點,仍舊可以被查詢到呢?這樣導緻我這個監控資料完全不準,你們這個有 bug,完全不對。其實這是阿裡巴巴在多年業務積累的經驗,對于服務發現來說,一個即使是已經過時的節點,也比沒有任何資料好。而且還有可能其實這個服務隻是和服務注冊中心失去了心跳,但是應用本身是正常的。

當然,這也暴露了我們設計中存在的一些問題,沒有把服務發現本身,以及緩存的分層給做好,兩者糅合在一塊。是以在這一次的版本更新中我們還是選擇适配開源标準,預設關閉了本地檔案緩存,留了一個開關給使用者自由選擇。

Nacos Config 在這個版本中有兩個大的特性,支援了“共享配置”,修正了動态重新整理的語義和行為。

  • 共享配置的實作

    在第一個版本還沒釋出到時候,社群裡對配置管理中心的讨論就沒停止過,其中聽到最多的回報應該就是支援多個應用共享一個配置。我們也通過 github issue 的方式,征集了很多意見,詳情見 #12 , #141。

後來我們将這個模型抽象了一下,認清這些需求本質是一個應用可以從多個 DataID 和 GroupID 組合中擷取配置,并且這些配置還可以單獨指定優先級和是否動态重新整理。

最後我們推薦了這種使用方式,既保證了使用場景的靈活性,又保證了業務語義的明确性。更多詳情可以參考 WIKI。

# config external configuration

# 1、Data Id 在預設的組 DEFAULT_GROUP,不支援配置的動态重新整理
spring.cloud.nacos.config.ext-config[0].data-id=ext-config-common01.properties

# 2、Data Id 不在預設的組,不支援動态重新整理
spring.cloud.nacos.config.ext-config[1].data-id=ext-config-common02.properties
spring.cloud.nacos.config.ext-config[1].group=GLOBAL_GROUP

# 3、Data Id 既不在預設的組,也支援動态重新整理
spring.cloud.nacos.config.ext-config[2].data-id=ext-config-common03.properties
spring.cloud.nacos.config.ext-config[2].group=REFRESH_GROUP
spring.cloud.nacos.config.ext-config[2].refresh=true

#優先級關系: spring.cloud.nacos.config.ext-config[n].data-id 其中 n 的值越大,優先級越高。
           

注意 data-id 的值必須帶檔案擴充名,檔案擴充名支援 properties、yaml 和 yml。通過這種自定義擴充的配置項,既可以支援一個應用從多個配置項中擷取資料,也解決多個應用間配置共享的問題。

頭腦風暴,@fudali 同學還提出了更加靈活的一種方式 #161,就是可以通過一個配置項來配置所有的 DataID 的資訊,然後可以通過修改這個配置項,可以修改整體配置項的邏輯。

這是一個非常好的想法,隻不過這一期中我們沒有實作,原因是這種方式太靈活了。我們認為配置管理其實是一件很嚴肅的事情,太靈活導緻生産中變更比較不可控。

雖然目前的邏輯也可以支援這種用法,但是我們并沒有把這種模式當做推薦模式,後續如果社群有更多的回報認為這是一個強烈的需求,歡迎提 PR。

  • 動态重新整理的修正

    簡單好用、實時可監控的動态重新整理也許是 Nacos Config 相對于其他開源中間件相比最核心的優勢了,不同于 Spring Cloud Config Server 必須使用 Spring Cloud Bus 才能實作動态重新整理,Nacos Config 無需依賴其他任何中間件就可以實作實時動态重新整理,而且推送成功與否和重新整理曆史還支援實時查詢。

但是我們發現在第一個版本中的實作發現兩個問題:

動态重新整理的實作方式不對:不應該直接調用 Context.refresh() 方法,而是應該 publish 一個 RefreshEvent。

是否動态重新整理的語義有誤:對于那些被标記為不動态重新整理的配置項來說,隻是修改他們的時候不會觸發動态重新整理。但是當其他支援動态重新整理的配置項觸發了動态重新整理時,應用的 Context 仍舊會去擷取那些被标記為不動态重新整理的配置項的内容,也就意味着這些配置項有可能被連帶重新整理了。

在這個版本中,我們修複了這兩個問題。

首先,動态重新整理不再是直接去調用 ContextRefresher.refresh() 方法,而是 publish 了一個 RefreshEvent,讓 spring-cloud-commons 裡的 RefreshEventListener 去觸發這個 ContextRefresher.refresh() 方法。

其次,我們修正了動态重新整理的語義後,這一次是真正做到了,隻有 refresh 屬性為 true 的配置項,才會在運作的過程中變更為新的值,refresh 屬性為 false 的配置項再也不用擔心應用在運作的過程中發生莫名其妙的變更了。

更深入一點,在上個月 SpringOne Tour 中,我們和 Spring Cloud 的創始人 Spencer 聊到 Spring Cloud 的 Context.refresh() 成本太高,會重新整理整個 Spring Context。他反複強調了兩次 Context.refresh() 隻對 @RefreshScope 和 @ConfigurationProperties 有效,成本一點也不高。

之前我們接收到很多社群的回報都是 Nacos Config 動态重新整理支不支援 xxxx,支不支援 xxxx。之前我們都是回答隻支援 @RefreshScope 和 @ConfigurationProperties ,如果他内置沒有支援,那就得自己加上相應的注解。

今天我們可以很愉快地回複,他監聽了 RefreshEvent 也能直接支援。而且如果添加 @RefreshScope 和 @ConfigurationProperties 都不滿足你的需求時,可以通過實作自己的 RefreshEventListener 更多進階的玩法。

Sentinel 在這個版本中有三個大的特性:全面支援 FeignClient ,完善了 RestTemplate 的支援,添加了熱點限流、叢集限流。

  • FeignClient 內建 Sentinel

    其實在這之前,Sentinel 支援 FeignClient 已經設計了很久了,之前我們的想法做一個相容性較強的方案,支援 Sentinel 和 Hystrix 在 FeignClient 中同時使用,盡量做到對原有應用的侵入性做到最小。

這個方案我們也思考調研了很久,但是實作難度确實比較大,需要修改 FeignClient 的代碼才能實作兩者共存。正好前段時間在 Spring Cloud 屆最大的新聞就是 Hystrix 宣布不在維護了,于是我們就換了一個思路,直接使用 Sentinel 替代 Hystrix,不再去追求支援兩者共存。

我們實作了自己的 Feign.Builder,在建構的 FeignClient 執行調用的過程中,通過 SentinelInvocationHandler 完成 Sentinel 的流量統計和保護的動作。如果想使用 Sentinel 為 FeignClient 限流降級,首先需要引入 sentinel-starter 的依賴,然後打開 Sentinel 限流降級的開關 feign.sentinel.enabled=true ,就完成了 Sentinel 的接入。如果需要使用更加定制化的功能,則需要在 @FeignClient 添加 fallback 和 configuration 這些屬性的配置。

注意 @FeignClient 注解中的所有屬性,Sentinel 都做了相容。

  • RestTemplate 內建 Sentinel

    Spring Cloud Alibaba Sentinel 支援對 RestTemplate 的服務調用使用 Sentinel 進行保護,補全了 Hystrix 這一塊的空白。接入的方式也不複雜,在構造 RestTemplate bean 的時候需要加上 @SentinelRestTemplate 注解,然後在控制台配置相應的規則即可。

在觸發了限流降級時,預設的處理方式是傳回 RestTemplate request block by sentinel 資訊。

如果想自定義被限流之後的處理方式,還可以添加 blockHandlerClass,blockHandler 分别定制被限流後的處理類以及對于的處理方法。

如果想自定義被降級之後的處理方式,還可以添加 fallback,fallbackClass 分别定制被降級後的處理類以及對于的處理方法。

RestTemplate 的限流降級 ?Sentinel 也承包了!

  • 熱點參數限流和叢集限流

    首先解釋一下什麼是熱點參數限流和叢集限流。

熱點參數限流會統計傳入參數中的熱點參數,并根據配置的限流門檻值與模式,對包含熱點參數的資源調用進行限流。熱點參數限流可以看做是一種特殊的流量控制,僅對包含熱點參數的資源調用生效。

叢集流控主要解決的問題是:當我們需要控制整個叢集流量總量,但是單機流量可能會不均勻,如果是單機次元去限制的話會無法精确地限制總體流量,是以需要引入叢集次元的流量控制。

Sentinel v1.4.0 的 新功能 ,也能第一時間愉快地在 Spring Cloud Alibaba 上使用了。

新元件

Spring Cloud Stream 是一個用于建構基于消息的微服務應用架構,它基于 SpringBoot 來建立具有生産級别的單機 Spring 應用,并且使用 Spring Integration 與 Broker 進行連接配接。它提供了消息中間件的統一抽象,推出了 publish-subscribe、consumer groups、partition 這些統一的概念。

RocketMQ 是一款開源的分布式消息系統,基于高可用分布式叢集技術,提供低延時的、高可靠的消息釋出與訂閱服務。具有以下特點:能夠保證嚴格的消息順序、提供豐富的消息拉取模式、高效的訂閱者水準擴充能力、實時的消息訂閱機制、億級消息堆積能力。

在這次的 Spring Cloud Stream Binder RocketMQ 的實作中,我們适配了 Spring Cloud Stream 對于 message 抽象的 API,支援了 RocketMQ 的事務消息。消息訂閱時支援以 tags、SQL 表達式過濾消息,同時還支援順序、并發、延遲以及廣播消費模式。

SchedulerX 是阿裡中間件團隊開發的一款分布式任務排程産品,提供秒級、精準、高可靠、高可用的定時(基于 Cron 表達式)任務排程服務,同時提供分布式的任務執行模型,如網格任務,網格任務支援海量子任務均勻配置設定到所有 Worker(schedulerx-client)上執行。

  • 簡單易用的輕量分布式任務排程

您不需要關心排程邏輯,隻需要在在 JobProcessor 接口的實作中添加業務邏輯即可,然後在自主運維控制台配置上一個 Job 即可完成使用。

  • 高可用的分布式任務

不管是 SchedulerX 服務端還是用戶端都是分布式架構設計,任務可以在多台用戶端機器裡的任何一台機器執行,如果用戶端出現當機的情況,服務端會自動選擇正常運作的用戶端去執行 Job,每個 Job 在服務端的不同機器均有備份,SchedulerX 服務端任意宕掉部分機器仍能保證 Job 正常排程。

  • 友好的使用者界面

SchedulerX 提供了非常友好的頁面友善您建立、删除或修改 Job,提供了立即觸發執行一次的功能,友善您測試以及關鍵時刻手動立即執行一次,還提供了曆史執行記錄查詢的功能,您可以看到任何一個 Job 過去 100 次的曆史執行記錄。

  • 功能強大

    提供了秒級、精準的定時任務排程服務,且提供了豐富的任務執行模型,包括單機執行,廣播執行,以及子任務的分布式執行。

What's Next?

Spring Cloud Alibaba Cloud SLS 針對日志類資料的一站式服務,在阿⾥巴巴集團經曆大量大資料場景錘煉⽽成。您⽆需開發就能快捷地完成日志資料采集、消費、投遞以及查詢分析等功能,提升運維、營運效率,建立 DT 時代海量日志處理能力。

Spring Cloud Alibaba Dubbo Dubbo 是一款流行的開源 RPC 架構,我們會把 Dubbo 整合到 Spring Cloud Alibaba 中,讓大家在開發 Dubbo 時也能享受到 Spring Cloud 帶來的便利。

緻謝

Spring Cloud Alibaba 從開源建設以來,受到了很多社群同學的關注。社群的每一個 issue ,每一個 PR,都是對整個項目的幫助,都在為建設更好用的 Spring Cloud 添磚加瓦。

我們真心地感謝為這個項目提出過 Issue 和 PR 的同學,特别是這些 contributor:

HaojunRen、xiejiashuai、mengxiangrui007

我們希望有更多社群的同學加入進來,一起把項目做好。

還要特别感謝文檔團隊的傾芸,她幫忙将我們所有的 Reference Doc 翻譯了英文,為Spring Cloud Alibaba 的國際化程序鋪平了道路。

亦盞,阿裡巴巴中間件進階開發工程師,長期關注微服務領域,主要負責 Spring Cloud Alibaba 項目的開發和社群維護。