Spring Cloud 官方文檔說了,它是一個完整的微服務體系,用戶能夠經過使用 Spring Cloud 快速搭建一個本身的微服務系統。那麼 Spring Cloud 到底是如何使用的呢?他到底有哪些組件?java
spring-cloud-commons
組件裏面,就有 Spring Cloud 默認提供的全部組件功能的抽象接口,有的還有默認實現。目前的 2020.0.x (按照以前的命名規則應該是 iiford),也就是spring-cloud-commons-3.0.x
包括:git
DiscoveryClient
,從註冊中心發現微服務。ServiceRegistry
,註冊微服務到註冊中心。LoadBalancerClient
,客戶端調用負載均衡。其中,重試策略從spring-cloud-commons-2.2.6
加入了負載均衡的抽象中。CircuitBreaker
,負責什麼狀況下將服務斷路並降級而後,通常一個完整的微服務系統還包括:github
在以前的系列中,咱們將 Spring cloud 升級到了 Hoxton 版本,組件體系是:web
而且實現了以下的功能:算法
註冊中心相關:spring
微服務實例相關:數據庫
metamap
中的zone
配置,來區分不一樣集羣的實例。只有實例的metamap
中的zone
配置同樣的實例才能互相調用。網關相關:apache
metamap
中的zone
配置鑑別所處集羣,僅把請求轉發到相同集羣的微服務實例在後續的使用,開發,線上運行過程當中,咱們還遇到了一些問題:編程
接下來,咱們要對現有依賴進行升級,而且對現有的功能進行一些拓展和延伸,造成一套完整的 Spring Cloud 微服務體系與監控體系。json
本次項目代碼,請參考:https://github.com/HashZhang/spring-cloud-scaffold/tree/master/spring-cloud-iiford
此次咱們抽象出更加具體的各類場景的依賴。通常的,咱們的整個項目通常會包括:
爲什麼微服務要抽象分離出響應式的和傳統 servlet 的呢?
<?xml version="1.0" encoding="UTF-8"?> <project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.4.4</version> </parent> <modelVersion>4.0.0</modelVersion> <groupId>com.github.hashjang</groupId> <artifactId>spring-cloud-iiford</artifactId> <packaging>pom</packaging> <version>1.0-SNAPSHOT</version> <properties> <project.version>1.0-SNAPSHOT</project.version> </properties> <dependencies> <!--junit單元測試--> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <scope>test</scope> </dependency> <!--spring-boot單元測試--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!--mockito擴展,主要是須要mock final類--> <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-inline</artifactId> <version>3.6.28</version> <scope>test</scope> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>2020.0.2</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.6.1</version> <configuration> <!--最好用JDK 12版本及以上編譯,11.0.7對於spring-cloud-gateway有時候編譯會有bug--> <!--雖然官網說已解決,可是11.0.7仍是偶爾會出現--> <source>11</source> <target>11</target> </configuration> </plugin> </plugins> </build> </project>
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>spring-cloud-iiford</artifactId> <groupId>com.github.hashjang</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>spring-cloud-iiford-common</artifactId> <properties> <guava.version>30.1.1-jre</guava.version> <fastjson.version>1.2.75</fastjson.version> <disruptor.version>3.4.2</disruptor.version> <jaxb.version>2.3.1</jaxb.version> <activation.version>1.1.1</activation.version> </properties> <dependencies> <!--內部緩存框架統一採用caffeine--> <!--這樣Spring cloud loadbalancer用的本地實例緩存也是基於Caffeine--> <dependency> <groupId>com.github.ben-manes.caffeine</groupId> <artifactId>caffeine</artifactId> </dependency> <!-- guava 工具包 --> <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>${guava.version}</version> </dependency> <!--內部序列化統一採用fastjson--> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>${fastjson.version}</version> </dependency> <!--日誌須要用log4j2--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-log4j2</artifactId> </dependency> <!--lombok簡化代碼--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> <!--log4j2異步日誌須要的依賴,全部項目都必須用log4j2和異步日誌配置--> <dependency> <groupId>com.lmax</groupId> <artifactId>disruptor</artifactId> <version>${disruptor.version}</version> </dependency> <!--JDK 9以後的模塊化特性致使javax.xml不自動加載,因此須要以下模塊--> <dependency> <groupId>javax.xml.bind</groupId> <artifactId>jaxb-api</artifactId> <version>${jaxb.version}</version> </dependency> <dependency> <groupId>com.sun.xml.bind</groupId> <artifactId>jaxb-impl</artifactId> <version>${jaxb.version}</version> </dependency> <dependency> <groupId>org.glassfish.jaxb</groupId> <artifactId>jaxb-runtime</artifactId> <version>${jaxb.version}</version> </dependency> <dependency> <groupId>com.sun.xml.bind</groupId> <artifactId>jaxb-xjc</artifactId> <version>${jaxb.version}</version> </dependency> <dependency> <groupId>javax.activation</groupId> <artifactId>activation</artifactId> <version>${activation.version}</version> </dependency> </dependencies> </project>
1. 緩存框架 caffeine
很高效的本地緩存框架,接口設計與 Guava-Cache 徹底一致,能夠很容易地升級。性能上,caffeine 源碼裏面就有和 Guava-Cache, ConcurrentHashMap,ElasticSearchMap,Collision 和 Ehcache 等等實現的對比測試,而且測試給予了 yahoo 測試庫,模擬了近似於真實用戶場景,而且,caffeine 參考了不少論文實現不一樣場景適用的緩存,例如:
因此,咱們選擇 caffeine 做爲咱們的本地緩存框架
參考:https://github.com/ben-manes/caffeine
2. guava
guava 是 google 的 Java 庫,雖然本地緩存咱們不使用 guava,可是 guava 還有不少其餘的元素咱們常常用到。
參考:https://guava.dev/releases/snapshot-jre/api/docs/
3. 內部序列化從 fastjson 改成 jackson
json 庫通常都須要預熱一下,後面會提到怎麼作。
咱們項目中有一些內部序列化是 fastjson 序列化,可是看 fastjson 已經好久沒有更新,有不少 issue 了,爲了不之後出現問題(或者漏洞,或者性能問題)增長線上可能的問題點,咱們這一版本作了兼容。在下一版本會把 fastjson 去掉。後面會詳細說明如何去作。
4. 日誌採用 log4j2
主要是看中其異步日誌的特性,讓打印大量業務日誌不成爲性能瓶頸。可是,仍是不建議在線上環境輸出代碼行等位置信息,具體緣由以及解決辦法後面會提到。因爲 log4j2 異步日誌特性依賴 disruptor,還須要加入 disruptor 的依賴。
參考:
5. 兼容 JDK 9+ 須要添加的一些依賴
JDK 9以後的模塊化特性致使 javax.xml 不自動加載,而項目中的不少依賴都須要這個模塊,因此手動添加了這些依賴。
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>spring-cloud-iiford</artifactId> <groupId>com.github.hashjang</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>spring-cloud-iiford-service-common</artifactId> <dependencies> <dependency> <groupId>com.github.hashjang</groupId> <artifactId>spring-cloud-iiford-common</artifactId> <version>${project.version}</version> </dependency> <!--註冊到eureka--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <!--不用Ribbon,用Spring Cloud LoadBalancer--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-loadbalancer</artifactId> </dependency> <!--微服務間調用主要靠 openfeign 封裝 API--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> <!--resilience4j 做爲重試,斷路,限併發,限流的組件基礎--> <dependency> <groupId>io.github.resilience4j</groupId> <artifactId>resilience4j-spring-cloud2</artifactId> </dependency> <!-- https://mvnrepository.com/artifact/io.github.resilience4j/resilience4j-feign --> <dependency> <groupId>io.github.resilience4j</groupId> <artifactId>resilience4j-feign</artifactId> </dependency> <!--actuator接口--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <!--調用路徑記錄--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-sleuth</artifactId> </dependency> <!--暴露actuator相關端口--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <!--暴露http接口, servlet框架採用nio的undertow,注意直接內存使用,減小GC--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-undertow</artifactId> </dependency> </dependencies> </project>
這裏面相關的依賴,咱們後面會用到。
對於 Webflux 響應式風格的微服務,其實就是將 spring-boot-starter-web
替換成 spring-boot-starter-webflux
便可
參考:pom.xml