本文示例基於Spring Boot 1.5.x實現,如對Spring Boot不熟悉,能夠先學習個人這一篇:《Spring Boot 1.5.x 基礎學習示例》。關於微服務基本概念不瞭解的童鞋,能夠先閱讀下始祖Martin Fowler的《Microservice》,本文不作介紹和描述。html
表明:Dubbo(Java)、Orleans(.Net)等java
特色:和語言綁定緊密node
表明:Spring Cloud等git
現狀:適合混合式開發(例如藉助Steeltoe OSS可讓ASP.Net Core與Spring Cloud集成),正值當年github
表明:Service Mesh(服務網格) => 例如Service Fabric、lstio、Linkerd、Conduit等算法
現狀:在快速發展中,更新迭代比較快spring
基礎的雲平臺爲微服務提供了資源能力(計算、存儲和網絡等),容器做爲最小工做單元被Kubernetes調度和編排,Service Mesh(服務網格)管理微服務的服務通訊,最後經過API Gateway向外暴露微服務的業務接口。bootstrap
目前,我所在的項目組已經在採用這種技術架構了,服務網格採用的是Linkerd,容器編排採用的是K8S,Spring Cloud已經沒用了。But,不表明Spring Cloud沒有學習的意義,對於中小型項目團隊,Spring Cloud仍然是快速首選。後端
首先,儘管Spring Cloud帶有「Cloud」這個單詞,但它並非雲計算解決方案,而是在Spring Boot基礎之上構建的,用於快速構建分佈式系統的通用模式的工具集。瀏覽器
其次,使用Spring Cloud開發的應用程序很是適合在Docker和PaaS(好比Pivotal Cloud Foundry)上部署,因此又叫作雲原生應用(Cloud Native Application)。雲原生能夠簡單地理解爲面向雲環境的軟件架構。
總結 :Spring Cloud是一個基於Spring Boot實現的雲原生應用開發工具,它爲基於JVM的雲原生應用開發中涉及的配置管理、服務發現、熔斷器、智能路由、微代理、控制總線、分佈式會話和集羣狀態管理等操做提供了一種簡單的開發方式。
Spring Cloud具備以下特色:
Spring Cloud做爲第二代微服務的表明性框架,已經在國內衆多大中小型的公司有實際應用案例。許多公司的業務線所有擁抱Spring Cloud,部分公司選擇部分擁抱Spring Cloud。例如,拍拍貸資深架構師楊波老師就根據本身的實際經驗以及對Spring Cloud的深刻調研,並結合國內一線互聯網大廠的開源項目應用實踐結果,認爲Spring Cloud技術棧中的有些組件離生產級開發尚有必定距離,最後提出了一個可供中小團隊參考的微服務架構技術棧,又被稱爲「中國特點的微服務架構技術棧1.0」:
上圖中涉及到的組件,這裏不作具體介紹,有興趣的童鞋能夠瀏覽波波老師的這篇文章:《一個可供中小團隊參考的微服務架構技術棧》。
備註:下面資料都是咱們項目組新同事以及老同事(.Net技術背景)所採用的學習資料,並不保證適合於全部人。本示例主要也主要是基於下面的資料而寫的sample code。
(1)周立:《Spring Cloud與Docker 微服務架構實戰》
(2)程序猿DD:《Spring Cloud 微服務實戰》、《Spring Cloud基礎教程(Dalston版本)(強力推薦)》
(3)純潔的微笑,《Spring Cloud系列文章》
示例地址:https://github.com/EdisonChou/EDC.SpringCloud.Samples
此部分示例位於:part1_service-register-discovery
此部分示例主要演示瞭如何基於Eureka實現服務的註冊與發現,其中包括兩個版本:
① 單節點版本 (開發環境調試用) => 位於eureka-service-sn (sn表明single node)項目內
這裏須要注意的地方是:在開發環境須要關閉Eureka的自我保護機制,否則你沒法輕易看到服務移除的效果,須要在application.yml中以下設置:
eureka: server: enableSelfPreservation: false # 本地調試環境下關閉自我保護機制
這是由於Eureka考慮到生產環境中可能存在的網絡分區故障,會致使微服務與Eureka Server之間沒法正常通訊。它的架構哲學是寧肯同時保留全部微服務(健康的微服務和不健康的微服務都會保留),也不盲目註銷任何健康的微服務。
關於自我保護機制,更多內容能夠參考:《Spring Cloud Eureka全解之自我保護機制》
② HA多節點版本 (部署/生產環境用) => 位於eureka-service-ha-1 & eureka-service-ha-2這兩個項目內
此版本須要注意的是兩個節點的application.yml保持一致,但因爲其中使用了peer1和peer2的hostname,在本地開發環境須要給Windows(我假設你使用的是Windows系統)設置hosts文件以下:
127.0.0.1 peer1 peer2
擴展:除了Eureka以外,還能夠選擇通用型較強的Consul,關於Consul的基本概念與服務端的安裝配置能夠看看個人這一篇《.Net Core微服務之基於Consul實現服務註冊於發現》瞭解一下。最後,不得不說,Spring Boot 和 Spring Cloud中核心組件封裝的註解真的是太強大了,不少操做一個註解直接搞定,無須過多的coding。
此部分示例位於:part2_client-load-balance
此部分示例主要演示瞭如何基於Ribbon實現客戶端的負載均衡,建議啓動方式:先啓動Eureka,再啓動UserService和MovieService。經過訪問MovieService的API接口 /log-instance 進行日誌查看,測試結果以下圖所示:
從上圖能夠看出,經過客戶端的負載均衡算法,依次訪問了不一樣的服務節點。
此部分示例位於:part3_feign
此部分示例主要演示了基於Feign如何實現聲明式調用,包括如下內容:
(1)基本整合Feign進行單參數與多參數的請求:位於movie-service這個項目內
須要注意的就是別忘了在啓動類加上@EnableFeignClients註解
@SpringBootApplication @EnableDiscoveryClient @EnableFeignClients // 要使用Feign,須要加上此註解 public class MovieServiceApplication { public static void main(String[] args) { SpringApplication.run(MovieServiceApplication.class, args); } }
(2)自定義Feign配置的使用:位於movie-service-feign-customizing這個項目內
下面的Feign接口就使用了自定義的配置類FeignConfiguration。
@FeignClient(name = "user-service", configuration = FeignConfiguration.class) public interface UserFeignClient { /** * 使用feign自帶的註解@RequestLine * @see https://github.com/OpenFeign/feign * @param id 用戶id * @return 用戶信息 */ @RequestLine("GET /{id}") User findById(@Param("id") Long id); }
(3)Feign的日誌的使用:位於movie-service-feign-logging這個項目內
須要注意的是:Feign雖然提供了logger,可是其日誌打印只會對DEBUG級別作出響應。日誌級別一共有4種類型,以下所示:
Logger.Level 可選值:
* NONE: 不記錄任何日誌(默認值)
* BASIC: 僅記錄請求方法、URL、響應狀態碼以及執行時間
* HEADERS: 記錄BASIC級別的基礎之上,記錄請求和響應的header
* FULL: 記錄請求和響應的header,body和元數據
要輸出日誌打印,application.yml內要設置DEBUG級別:
logging: level: # 將Feign接口的日誌級別設置爲DEBUG,由於Feign的Logger.Level只針對DEBUG作出響應 com.mbps.cd.movieservice.feign.UserFeignClient: DEBUG
最後,針對FULL級別的日誌打印效果以下圖所示:
此部分示例位於:part4_hystrix
此部分示例主要演示如何基於Hystrix實現容錯處理,主要包括如下內容:
(1)通用方式整合Hystrix:此示例位於movie-service項目中
針對普通的方法,只需加上HystrixCommand註解及定義回退方法便可,例如:
@HystrixCommand(fallbackMethod = "findByIdFallback") @GetMapping(value = "/user/{id}") public User findById(@PathVariable Long id) { return restTemplate.getForObject("http://user-service/" + id, User.class); } public User findByIdFallback(Long id){ User user = new User(); user.setId(-1L); user.setUsername("Default User"); return user; }
(2)Feign使用Hystrix:此示例位於movie-service-feign-hystrix項目中
針對Feign,它是以接口形式工做的,好在Spring Cloud已默認爲Feign整合了Hystrix,不過默認是關閉的,須要手動在配置文件中開啓:
feign: hystrix: enabled: true
在以前的版本(Dalston以前的版本)中是默認開啓的,至於爲什麼要改成默認禁用,能夠看看這裏:https://github.com/spring-cloud/spring-cloud-netflix/issues/1277
而後直接在FeignClient註解中加入fallback屬性便可,例以下面所示:
@FeignClient(name = "user-service", fallback = FeignClientFallback.class) public interface UserFeignClient { @GetMapping(value = "/{id}") User findById(@PathVariable("id") Long id); } @Component class FeignClientFallback implements UserFeignClient{ @Override public User findById(Long id) { User user = new User(); user.setId(-1L); user.setUsername("Default User"); return user; } }
若是想要在Feign發生回退時可以留下日誌供查看回退緣由,那麼可使用FallbackFactory,示例項目:movie-service-feign-fallback-factory.
當發生回退時,日誌輸出信息以下:
除此以外,關於Hystrix部分,還有監控的主題,這裏因爲我所在的項目組的技術架構中不會涉及到,也就沒有弄,有興趣的童鞋能夠關注一下Hystrix自帶的監控以及基於Turbine的聚合監控。參考文章:《Hystrix監控面板(Dalston版)》與《Hystrix監控數據聚合》。
此部分示例位於:part5_zuul
此部分示例主要演示如何基於Zuul實現API網關,主要包括如下內容:
(1)整合Zuul編寫API網關:位於zuul-service項目中
能夠測試驗證的內容:
對於路由端點,須要改一下如下配置,才能正常顯示路由端點信息,不然會報401的錯誤:
management: security: enabled: false # 默認爲true,改成false以即可以看到routes
(2)Zuul的過濾器:主要位於zuul-service-filter這個項目中
對於Zuul的請求聲明週期來講,一共有4種標準過濾器類型:
此示例中演示了PRE類型的過濾器,部分場景下,想要禁用部分過濾器,只須要在配置文件中設置便可,例如這裏禁用PreRequestLogFilter過濾器:
(3)Zuul的容錯與回退:主要位於zuul-service-fallback這個項目中
Zuul自身就帶有Hystrix,可是它監控的粒度是微服務級別,而不是某個API,當某個API不可用時,會統一拋500錯誤碼的異常頁。咱們能夠爲Zuul添加回退,以實現更友好的返回信息。實現也很簡單,只須要實現FallbackProvider接口便可。這裏要注意的是,對於Edgware以前的版本(即Dalston及更低版本)須要實現的是ZuulFallbackProvider接口,而Edgware及以後的版本要實現的是FallbackProvider接口。由於FallbackProvider是ZuulFallbackProvider的子接口,而它的好處就是多了一個接口能夠獲取可能形成回退的緣由,具體能夠參考這一篇文章:《Spring Cloud Edgware新特性之八:Zuul回退的改進》。下面是本示例中訪問user-service接口(user-service被我手動關閉)後的返回結果:
(4)Zuul的高可用架構
生產環境中通常都須要部署高可用的Zuul以免單點故障,實際開發中有兩種狀況:
① Zuul的客戶端也註冊到了Eureka Server上(好比:MVC App, SPA 等)
此時Zuul的高可用和其餘微服務沒區別,都是藉助Eureka和Ribbon來實現負載均衡。
② Zuul的客戶端未註冊到Eureka Server上(好比手機App端等)
現實中這種場景或許更常見,此時須要藉助一個額外的負載均衡器來實現Zuul的高可用,好比:Nginx、HAProxy以及F5等。
更多Zuul高可用的內容,能夠瀏覽周立老師的這一篇:《Zuul的高可用》
(5)使用Zuul聚合微服務:此示例位於zuul-service-aggregation項目中
許多場景下可能一個外部請求要查詢Zuul後端的多個服務,這時可使用Zuul來聚合服務請求,即只需請求一次,由Zuul來請求各個服務,而後組織好數據發送給客戶端(好比App客戶端)。示例中主要基於RxJava與Zuul來結合實現的微服務請求的聚合。
Spring Cloud Config爲分佈式系統外部化配置提供了服務端和客戶端的支持,包括Config Server和Config Client兩部分,其架構圖以下圖所示:
其中,各個微服務在啓動時會請求Config Server以獲取所須要的配置屬性,而後緩存這些屬性以提升性能,以下圖所示:
此部分示例位於:part6_config
此部分示例主要演示如何基於Spring Cloud Config實現統一配置中心,主要包括如下內容:
(1)基本的Config Server與Config Client編寫:此示例位於config-service與config-client中
此示例須要用到一些已放到git的配置文件,這裏我已將其放到了github方便你們能夠直接拿來測試用,倉庫地址爲:https://github.com/EdisonChou/EDC.SpringCloud.Samples.Config
端點與配置文件的映射規則以下:
/{application}/{profile}[/{label}]
/{application}-{profile}.yml
/{label}/{application}-{profile}.yml
/{application}-{profile}.properties
/{label}/{application}-{profile}.properties
其中,application: 表示微服務的虛擬主機名,即配置的spring.application.name
profile: 表示當前的環境,dev, test or production?
label: 表示git倉庫分支,master or relase or others repository name? 默認是master
項目中,config-service的配置文件以下:
啓動順序:先啓動config-server,再啓動config-client,由於config-client在啓動時就回去config-server獲取配置,若是這時config-server未啓動則會報錯。
這裏須要注意的就是在config-client中,對於spring cloud config的配置應該放在bootstrap.yml中而不是application.yml中,不然會不起做用。這裏涉及到一個spring cloud的「引導上下文」的概念,能夠參考這篇《深刻理解Spring Cloud引導上下文》來了解一下。
(2)使用/refresh端點手動刷新配置:仍然位於config-client項目中
要想在運行期間刷新配置,須要兩點改造:加上@RefreshScope註解
@RestController @RefreshScope // @RefreshScope註解不能少,不然即便調用/refresh,配置也不會刷新 public class ConfigClientController { @Value("${profile}") private String profile; @GetMapping("/profile") public String hello(){ return this.profile; } }
此外,針對Spring Boot 1.5.x,還須要給config-client端關閉安全認證,不然沒法正常refresh:
management: security: enabled: false
以後,就能夠經過對config-client發起POST請求刷新配置了:
不過,若是全部微服務都須要手動刷新配置,工做量會很大。因此,在實際環境中,通常會實現配置的自動刷新。
(3)使用Spring Cloud Bus自動刷新配置:此示例位於config-server-cloud-bus與config-client-cloud-bus項目中
此示例使用到的架構以下圖所示,它將Config Server加入消息總線之中,並使用Config Server的/bus/refersh端點來實現配置的刷新。這樣,各個微服務只須要關注自身的業務邏輯,而無需再本身手動刷新配置。
Tip:Spring Cloud Bus基於輕量級地消息代理(例如RabbitMQ、Kafka等)鏈接分佈式系統的節點,就能夠經過廣播的方式來傳播狀態的更改(例如配置的更新)或者其餘的管理指令。咱們能夠將Spring Cloud Bus想象成一個分佈式的Spring Boot Actuator。
運行順序:先啓動config-service-cloud-bus,再啓動兩個config-client-cloud-bus(第一個默認端口8081,第二個端口改成8082),修改github中sampleservice-foo-dev.properties中的profile值後commit & push,而後POST請求config-service-cloud-bus的/bus/refersh端點,最後再次訪問兩個client的/profile端點進行驗證。
若是部分場景想要知道Spring Cloud Bus事件傳播的細節,能夠經過如下設置來跟蹤事件總線:
spring: cloud: bus: trace: enabled: true # 開啓cloud bus跟蹤
(4)與Eureka的配合使用:此示例位於config-service-eureka與config-client-eureka兩個項目中
(5)Config Server的高可用:涉及到Git倉庫的高可用、RabbitMQ的高可用以及Config Server自身的高可用。
對於Git倉庫的高可用,第三方Git倉庫相似於GitHub等自己已經實現了高可用,而針對自建Git倉庫如GitLab,能夠參考GitLab官方文檔搭建高可用:https://about.gitlab.com/high-availability/
對於Config Server自身的高可用,也能夠分爲未註冊到Eureka和註冊到Eureka兩種情形,具體能夠參考Zuul的高可用的架構圖。
此外,對於配置內容的加密,此示例沒有涉及,它依賴於JCE(Java Cryptography Extension),能夠參考這一篇《Spring Cloud配置文件加密》瞭解一下。
擴展:關於統一配置中心,還能夠選擇更好用的Apollo(攜程的開源項目),能夠看看個人這一篇《.Net Core微服務之基於Apollo實現統一配置中心》瞭解一下。
首先,值得一提的是Spring Cloud Sleuth大量借用了Google Dapper,Twitter Zipkin和Apache HTrace的設計,咱們得了解一些術語,例如:span、trace、annotation等,詳細能夠參考這篇《Spring Cloud系列之分佈式鏈路監控Spring Cloud Sleuth》。
此示例位於:part7_sleuth
此部分示例主要演示如何基於Spring Cloud Sleuth實現分佈式鏈路監控,主要包括如下內容:
(1)基礎整合Spring Cloud Sleuth:位於user-service-trace與movie-service-trace項目中,主要查看控制檯輸出日誌
(2)Spring Cloud Sleuth與Zipkin的配合使用:位於zipkin-service-server、user-service-trace-zipkin與movie-service-trace-zipkin三個項目中
Zipkin是Twitter開源的分佈式跟蹤系統,基於Dapper論文設計而來,主要功能是收集系統的時序數據,從而追蹤微服務架構的系統延時問題,此外還提供了一個很是友好的界面來幫助追蹤分析數據。
下圖是一個接入Zipkin以後的服務調用簡易流程圖:
運行順序:首先運行zipkin-service-server,其次運行user-service-zipkin與movie-service-zipkin,而後訪問http://localhost:8010/user/1獲得數據結果,最後訪問zipkin server首頁,填入起始時間、結束時間等篩選條件後,點擊Find a trace按鈕,能夠看到trace列表,以下圖所示:
點擊「依賴分析」,能夠獲得下圖,有助於咱們分析依賴關係:
須要注意的是,在開發調試時,由於默認的採樣百分比是10%,Sleuth會忽略大量span,所以咱們能夠在開發環境將其設置爲100%:
spring: sleuth: sampler: # 指定需採樣的請求的百分比,默認是0.1(即10%),這裏方便查看設爲100%(實際環境不要這樣設置) percentage: 1.0
(3)使用RabbitMQ收集數據:此示例位於zipkin-service-server-stream與user-service-trace-zipkin-stream兩個項目中
此外,Spring Cloud Sleuth還能夠與ELK配合使用,不過此示例沒有涉及,感興趣的朋友能夠參考這一篇《Spring Cloud Sleuth與ELK集成》。固然,示例中的跟蹤數據都是存放到內存中,可是跟蹤數據仍是建議存放到ElasticSearch中,生產環境切莫只存儲到內存中。
IDE => Intellij Idea Community 2018
(PS: 若是是.Net程序猿背景,強烈建議更改快捷鍵與Visual Studio保持一致,這樣能加快開發效率,如不瞭解如何修改,能夠參考鄒瓊俊《從.Net到Java - Idea and Start Spring Boot》)
Plugin => 阿里巴巴代碼規約