spring cloud概述
從本篇開始,我們将正式踏上探索spring cloud秘密的旅程。學完本文後,讀者将學會搭建一個完整的分布式架構,進而向架構師的目标靠近。
簡介
spring cloud基于spring boot,是微服務架構思想的一個具體實作,它為開發人員提供了一些快速建構分布式系統中常見模式的工具,如配置管理、服務發現、熔斷器、智能路由、微代理、控制總線等。spring cloud 的底層基于spring boot架構,它不重複“造輪子”,而是将一些第三方實作的微服務應用子產品內建。
spring cloud是一系列有序架構的集合,下面列舉了一些我們在實際項目中可能會用到的子項目。
spring cloud config:通過svn、git等倉庫使配置集中化存儲,配置資源可以直接映射到spring environment 中。
spring cloud netflix:與 netflix開發的各種元件內建,包括服務注冊與發現、熔斷器、服務網關、rest用戶端及負載均衡器等。
spring cloud bus:将服務、服務執行個體與分布式消息連結在一起的事件總線;用于在叢集中傳播狀态變化;和 spring cloud config配合,可以實作配置的動态重新整理。
spring cloud consul:進行spring cloud中的服務注冊與發現配置管理。
spring cloud security:為zuul代理中的負載平衡oauth2rest用戶端和身份驗證中繼提供支援。
spring cloud sleuth:用于spring cloud應用程式的分布式跟蹤,相容zipkin、htrace和基于日志(例如elk)的跟蹤。
spring cloud data flow:一種能夠用于現代運作時并可以組合微服務應用程式的雲本地編排服務。易于使用的dsl、拖放式gui和rest-api共同簡化了基于微服務的資料管道的整體編排。
spring cloud stream:輕量級事件驅動的微服務架構,能夠快速建構可連接配接到外部系統的應用程式,用于在spring boot應用程式之間使用apache kafka或rabbitmq發送和接收消息。
spring cloud task:一種短暫的微服務架構,用于快速建構執行有限資料處理的應用程式,它用于向spring boot應用程式中添加功能性和非功能性的簡單聲明。
spring cloud gateway:一款基于project reactor的智能可程式設計路由器。由于zuul 2.0版本的開發經常跳票,是以spring官方開發了路由網關以支援spring boot 2.0及新版spring cloud。
spring cloud openfeign:基于netflix feign,是一個聲明式的http用戶端,可以輕松實作服務間接口調用。
spring cloud function:通過函數促進業務邏輯的實作,它支援無伺服器提供商之間的統一程式設計模型以及獨立運作(本地或paas )。
這些項目不會全部集中在一個應用上,将它們列舉出來的目的是友善讀者在建構基于springcloud的微服架構時,可根據實際應用情況選擇一些适合的元件內建到應用中。
優缺點
在技術更新如此頻繁的時代中,存活下來的架構必然有它的優點。那麼,spring cloud 有什麼優點呢?下面我們就來探讨一下。
集大成者:包含了微服務架構的方方面面。約定優于配置:基于注解,沒有配置檔案。
輕量級元件:整合的元件大多比較輕量,且都是各自領域的佼佼者。
開發簡便:對元件進行了大量封裝,進而簡化了開發。
開發靈活:元件都是解耦的,開發人員可以靈活按需選擇元件。
事物都有雙面性,spring cloud也不例外,它主要有以下缺點。
項目結構複雜:每一個元件或者每一個服務都需要建立一個項目。
部署門檻高:需要配合docker等容器技術進行叢集部署。而要想深入了解docker,學習成本比較高。
spring cloud 的優勢是顯而易見的,是以對于想研究微服務架構的讀者來說,學習spring cloud是一個不錯的選擇。
現狀
目前,國内使用spring cloud作為主要技術棧的公司并不多見,這并不是因為spring cloud不好,主要原因有以下幾點。
spring cloud中文文檔較少,出現問題找不到太多的解決方案。
國内創業型公司的技術老大很多曾就職于阿裡巴巴,他們多采用dubbo來建構微服務架構。
大型公司基本都有自己的分布式解決方案,而中小型公司的架構很多用不上微服務,是以沒有采用spring cloud 的必要性。
但是微服務架構是一個趨勢,而spring cloud是微服務解決方案中的佼佼者,這也是我編寫本書的意義所在。
開始spring cloud 實戰
學習任何一門語言或者一種架構,都是由hello world 開始的,本書也不例外。在正式進入實戰之前,我們先來搭建一個最簡單的spring cloud架構,以便大家能夠領略其強大之處。
技術儲備
在開始 spring cloud學習之前,讀者應該擁有以下技術儲備。
java基礎:如果你的java基礎還不夠紮實,建議先學習相關内容,再來閱讀本文。
spring mvc: spring cloud基于spring boot,而 spring boot又基于spring mvc,是以讀者需要具備spring mvc架構的基礎。
準備工作
本文采用intellijidea開發spring cloud項目,若讀者尚未安裝該工具,可以從其官網https://www.jetbrains.com/idea/下載下傳最新版。圖4-1是我所用的idea的詳細版本資訊。
本文所用的spring boot版本為2.0.3.release,spring cloud版本為finchley.release,是以jdk的版本至少在1.8以上。此外,書中也包含了大量lambda表達式,讀者也需要了解lambda表達式,否則有些代碼可能無法讀懂。
從hello world開始你的實戰之旅
下面開始搭建一個最簡單的spring cloud架構,主要包括服務的注冊與發現、用戶端以及服務網關。spring cloud 屬于微服務架構,會包含多個工程,是以,我們應該先建立一個父工程,并設定
打開intellij idea,建立一個maven工程,将其命名為springclouddemo,然後修改pom.xml的内容:
其中,pom.xml裡面需要添加hystrix熔斷器的依賴,這是因為spring cloud預設加人了該熔斷器,如果不添加此依賴,啟動子工程時會報錯。
父工程建立好後,就可以建立子工程,并實作一個最簡單的spring cloud項目。
1.服務的注冊與發現
spring cloud預設的服務注冊與發現元件是netflix的eureka元件(該元件會在第6章中詳細介紹),本節也是使用它的預設元件來建立服務注冊與發現的。
spring cloud将 eureka內建到微服務家族中,并對它進行了二次封裝,eureka負責微服務架構中的服務治理功能。服務治理是微服務架構中的核心思想,它可以實作服務的注冊、發現、銷毀和續約等。
(1)右擊springclouddemo工程,在彈出的快捷菜單中選擇new→module(如圖4-2所示),在打開的new module視窗中将artifactild命名為eurekaserver,如圖4-3所示,然後一直點選next 按鈕即可。
(2)在pom.xml檔案中添加如下依賴:
eureka元件分為服務端和用戶端,服務端負責管理用戶端,比如注冊、銷毀和續約等。加入上述依賴後,我們就可以将該工程設定為eureka 服務端來管理eureka用戶端。
(3)建立啟動類application:
application是該工程的啟動類。我們知道,一個java程式的入口函數是main方法。在上述代碼中,我們在application類中添加了main方法,并通過springapplication調用run方法,啟動一個spring cloud工程。
此外,我們還在application類中添加了@enableeurekaserver和@springcloudapplication注解。其中,第一個注解表示将目前工程設定為注冊中心,隻有加入該注解,目前工程才能作為注冊與發現的服務端,後者表明該工程是一個 spring cloud工程。
@springcloudapplication注解的源碼如下:
可以發現,它也包含3個核心注解:@springbootapplication、@enablediscoveryclient和@enablecircuitbreaker。@springbootapplication注解在第2章中已經講過,一個spring boot工程的啟動類必須添加該注解,否則無法正确啟動工程;@enablediscoveryclient表示該工程可以作為用戶端注冊到注冊中心;@enablecircuitbreaker表示開啟熔斷器,熔斷器的相關内容詳見第10篇(此文為第四篇)。
(4)在resources下建立配置檔案application.yml,并添加如下内容:
上述配置是注冊中心最基本的配置。其中, spring. application.name定義了目前工程的應用名,eureka服務端将以該名稱注冊,預設全部替換成大寫字母; eureka.client. register-with-eureka用于說明目前工程是否注冊到eureka服務端,預設為true;eureka.client.fetch-registry可以訓示該工程是否應從 eureka服務端中擷取eureka系統資料庫資訊,預設為true,主要在高可用注冊中心或進行負載均衡等場景下使用,而上述示例是單節點eureka服務端,不需要同步其他eureka 服務端的資訊,是以設定為false;eureka.client.service-url訓示該工程注冊到哪個注冊中心下, eureka為固定值,8761為注冊中心端口。
這樣服務的注冊與發現就建立完成了,下面我們來測試一下。(1)啟動application類的main方法。
(2)在浏覽器中通路localhost:8761,就能看到如圖4-4所示的界面。eureka服務端将自己也注冊了,而eurekaserver就是在spring.application.name 定義的應用名,eureka服務端統一将其轉換為大寫字母eurekaserver了。
2.用戶端
eureka服務端搭建完成後,我們繼續來搭建用戶端。
(1)建立module,将其命名為eurekaclient,在pom.xml檔案裡添加依賴:
其中,spring-cloud-starter-netflix-eureka-client為eureka 用戶端依賴,隻有添加該依賴,我們才能将用戶端注冊到eureka服務端; spring-boot-starter-web內建了spring mvc架構,在eureka用戶端必須添加該依賴,否則無法啟動工程。工程啟動日志如圖4-5所示。
通過圖4-5可以清晰地看到,工程啟動後會自動停止.而加上spring-boot-starter-web依賴後,我們就能正确啟動工程,如圖4-6所示。
(2)建立啟動類application,其代碼與本節前面的“服務的注冊與發現”相同。注意,本啟動類隻需要添加@springcloudapplication即可,無須添加 @enableeurekaserver注解。
(3)建立配置檔案 application.yml,其代碼與本節前面的“服務的注冊與發現”相同,隻需要将server.port 設定為8762,将spring.application.name 設定為eurekaclient即可。
下面來測試一下。
(1)分别啟動eurekaserver和 eurekaclient。
(2)通過浏覽器通路localhost:8761,我們發現 eureka用戶端(eurekaclient)也被注冊上去了,如圖4-7所示。
3.服務網關
在spring boot 1.x時代, spring cloud的預設網關是netflix的zuul 1.0,zuul 2.0也在持續開發中,但是開發過程一波三折,經常跳票°。于是spring cloud官方也沒有耐心等下去,自己開發了一套路由網關架構,在spring boot 2.0以後,服務網關有了新的架構,那就是spring cloud gateway。
zuul 1.0是阻塞式網關,也不支援websocket; zuul 2.0是非阻塞式網關,并且支援了websocket。由于spring cloud官方自己開發了一套網關,它采用非阻塞api,支援websocket、熔斷、限流、路由過濾等功能,是以沒有必要再內建zuul 2.0。目前如果繼續依賴zuul 的話,依然是zuul 1.0。zuul 1.0在處理并發性能方面明顯不如 spring cloud gateway,是以,本書使用spring cloud gateway作為服務網關。
下面我們就來搭建服務網關。
(1)在springclouddemo下建立一個module,将其命名為gateway,然後添加如下依賴:
在上面的代碼中,我們加人了spring-cloud-starter-gateway依賴,這樣就可以将該工程設定為服務網關。而服務網關也需要注冊到eureka服務端,否則它無法代理其他eureka 用戶端,也失去了網關的作用,是以也需要添加spring-cloud-starter-netflix-eureka-client依賴。
因為spring cloud gateway采用 webflux,是以我們需要添加 webflux 的依賴。注意不能添加spring-boot-starter-web 依賴,否則啟動會報錯,如圖4-8所示。
如果我們要實作動态路由,需要将spring cloud gateway注冊到注冊中心,此時需要添加eureka用戶端的依賴。
(2)建立配置檔案application.yml:
在上述配置中,eureka.client.fetch-registry 設定為true,這是因為外部通路通過本服務網關通路具體的 eureka用戶端,服務網關需要拉取eureka系統資料庫資訊,否則無法發現具體的用戶端;而spring.cloud.gateway.discovery.locator.enabled用于設定是否開啟動态路由配置,如果将其設定為 true,表示gateway 會通過注冊中心注冊的 serviceid 去請求指定用戶端接口,位址如http:/localhost:gateway port/serviceid/**。這裡需要注意的是,通過eureka服務端注冊的serviceid是大寫的,如圖4-9所示。
是以,請求位址的 serviceid也應寫成大寫的,因為它是區分大小寫的,而 serviceid就是我們在application.yml中設定的 spring.application.name。
(3)建立啟動類application。由于服務網關也作為eureka用戶端注冊到eureka服務端,是以所有用戶端代碼都幾乎同上述“用戶端”一樣,此處也不例外,是以代碼不再給出。
(4)在eurekaclient工程中建立hellocontroller類,該類是spring mvc中的控制器:
在上述代碼中,我們定義了一個http請求方法 index,外部環境(如浏覽器)可以通過index位址通路該方法。
然後測試一下。
(1)分别啟動eurekaserver、eurekaclient和l gateway三個工程。
(2)按照前面講到的規則,通過浏覽器通路localhost:8080/eurekaclient/index,可以看到如圖4-10所示的界面。
以上就是基于spring cloud架建構立的最簡單的工程,通過這個工程,我們可以了解如何建立注冊中心、如何将用戶端注冊到注冊中心,如何通過gateway請求用戶端定義的接口。
在本書後面的實戰中,我們将進一步研究spring cloud 的各個元件,并且将這些元件合理運用到實際應用中。
小結
本篇中,我們正式進入spring cloud的學習。任何一門技術入門書,都是從hello world開始的,本文也不例外。
本篇先介紹了spring cloud 的基本概念、spring cloud 的優缺點及發展現狀,随後以一個最簡單的spring cloud示例示範了其部分核心思想,即服務的注冊與發現、服務網關,使讀者對spring cloud有了初步的了解,為後面的項目開發奠定基礎。