Spring Cloud升級之路 - Hoxton - 1.背景介紹與要實現的功能

本系列示例與膠水代碼地址: https://github.com/HashZhang/spring-cloud-scaffoldreact

Spring Cloud仍是比較活躍的,更新一直很快。我通常考慮最新版本SR2發佈以後,再考慮升級(通常SR1還有SR2會有一些新老框架的兼容性升級)。並且因爲須要咱們線上穩定,結合咱們的發佈週期來看,跳一個大版本升級是一個更好的選擇(也就是一年作一次大版本升級)。例如咱們以前的升級路線就是:Brixton -> Daltson -> Finchley -> 當前的Hoxtongit

作了這麼屢次升級,感受能夠出這個系列,來分享咱們項目使用Spring cloud框架實現的框架功能,在升級中遇到的坑,以及如何升級等等。每一個版本都會有實例代碼,並在上一版本實現的功能基礎上,實現更多更實用的功能。全部示例代碼都在開頭提到的項目中,每一個版本系列的最後,還會附上功能測試流程。github

在Hoxton版本Release的同時,Spring Cloud也宣佈,其中的這些項目,已經進入維護模式(再也不開發新功能),用戶最好作以下的替換:web

  • Spring Cloud Netflix Ribbon -> Spring Cloud Load Balancer
  • Spring Cloud NetFlix Zuul -> Spring Cloud Gateway
  • Spring Cloud Hystrix -> Spring Cloud Circuit Breaker + Resilience4J
  • Spring Cloud Netflix Turbine -> Micrometer + Promethus
  • Spring Cloud Netflix Archaius -> Spring Cloud Config Server

能夠看出,Spring Cloud netflix中的zuul, ribbon, hystrix都基本上算是廢了,咱們也能夠拋棄掉Sprnig Cloud Netflix了。還有一個體系也在官方中,就是Spring Cloud Alibaba,可是經過Spring Cloud netflix這件事,我我的感受這種依賴性質的膠水項目,最好仍是咱們架構組本身維護,這塊是比較容易有坑的,本身維護本身用更新起來更高效,並且不會有粘合的項目都不更新了替換起來要人命的代價。算法

Spring Cloud Hoxton,至少對於官方文檔來講,是一個里程碑式的變化。官方文檔終於將全部項目的文檔分開了,而且作了比較多的整理,能夠看出,這個Hoxton必定是有人下定決心要作一個變革了。而且,Spring Cloud在這個版本引入了更多的虛擬化,雲原生依賴,例如Spring-Cloud-kubernetes,確實,有些服務發現,調用策略什麼的,Spring Cloud和k8s體系重複了,這個依賴可使咱們靈活地切換這些功能到底交給誰來作,期待這個項目的完善成熟。spring

這篇文章,會主要列出升級步驟與詳細說明,以及對應的源代碼,和實現的功能。以及如何替換Spring Cloud Netflix體系爲新的組件。apache

原有的功能以及以前的實現

1. 微服務

之前的體系:api

  1. 註冊中心:Eureka
  2. 客戶端封裝:OpenFeign
  3. 客戶端負載均衡:Ribbon
  4. 斷路器與隔離: Hystrix

實現的功能:緩存

  1. 全部集羣公用同一個公共Eureka集羣,集羣之間不互相調用,經過實例的metamap中的zone配置,來區分不一樣集羣的實例。以前經過Ribbon的配置ServerListFilter實現,使用com.netflix.loadbalancer.ZoneAffinityServerListFilter做爲ServerListFilter,參考:Spring cloud實現FeignClient指定Zone調用
  2. 微服務之間調用,有重試,只對GET請求進行重試,鏈接超時,讀取超時還有 4xx 和 5xx 的狀態碼都會重試。這個以前是經過加入spring-retry重試經過ribbon配置實現的。參考:Spring Cloud Finchley OpenFeign的重試配置相關的坑
  3. 微服務調用有線程隔離,例如微服務1調用微服務2和微服務3,調用微服務2的線程和微服務3的線程不同。以前是經過Hystrix配置實現hystrix.threadpool.default.coreSize=50
  4. 實現了實例級別的熔斷,而不是微服務級別的。當調用微服務的兩個實例的時候,當一個實例一直異常,則將這個實例斷路器打開一段時間,而不是整個微服務都不能工做。以前經過Ribbon的配置LoadBalancerRule實現,使用com.netflix.loadbalancer.AvailabilityFilteringRule做爲LoadBalancerRule。參考:Ribbon的AvailabilityFilteringRule的坑

2. 網關

之前的體系:tomcat

  1. API網關:Zuul

實現的功能:

  1. 重試,只對GET請求進行重試,鏈接超時,讀取超時還有 4xx 和 5xx 的狀態碼都會重試。這個以前是經過加入spring-retry重試經過ribbon配置實現的。
  2. 微服務調用有線程隔離,例如微服務1調用微服務2和微服務3,調用微服務2的線程和微服務3的線程不同。以前是經過Hystrix配置實現hystrix.threadpool.default.coreSize=50
  3. 實現了實例級別的熔斷,而不是微服務級別的。當調用微服務的兩個實例的時候,當一個實例一直異常,則將這個實例斷路器打開一段時間,而不是整個微服務都不能工做。以前經過Ribbon的配置LoadBalancerRule實現,使用com.netflix.loadbalancer.AvailabilityFilteringRule做爲LoadBalancerRule。參考:Ribbon的AvailabilityFilteringRule的坑
  4. 特定接口 request body 解密與特定接口 response body 的加密。

3. Eureka-Server

實現的功能:

  1. 實例的快速上線下線,參考:Eureka 服務實例實現快速下線快速感知快速刷新配置解析

如今要實現的功能

1. 微服務

  1. 微服務之間調用依然基於利用 open-feign 的方式,有重試,僅對GET請求而且狀態碼爲4xx和5xx進行重試(對4xx重試是由於滾動升級的時候,老的實例沒有新的 api,重試能夠將請求發到新的實例上)
  2. 某個微服務調用其餘的微服務 A 和微服務 B, 調用 A 和調用 B 的線程池不同。而且調用不一樣實例的線程池也不同。也就是實例級別的線程隔離
  3. 實現實例級別的熔斷。
  4. 使用 zone 隔離,不一樣 zone 之間不能互相調用
  5. 負載均衡的輪詢算法,須要請求與請求之間隔離,不能共用同一個 position 致使某個請求失敗以後的重試仍是原來失敗的實例

2. 網關

  1. 轉發請求,有重試,僅對GET請求而且狀態碼爲4xx和5xx進行重試
  2. 不一樣微服務的不一樣實例線程隔離
  3. 實現實例級別的熔斷。
  4. 使用 zone 隔離,僅轉發請求到同 zone 的實例
  5. 負載均衡的輪詢算法,須要請求與請求之間隔離,不能共用同一個 position 致使某個請求失敗以後的重試仍是原來失敗的實例

3. Eureka

  1. 實現服務實例快速上下線

新的pom依賴

1. 微服務

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.7.RELEASE</version>
    </parent>

    <properties>
        <disruptor.version>3.4.2</disruptor.version>
        <resilience4j-spring-cloud2.version>1.1.0</resilience4j-spring-cloud2.version>
    </properties>

    <dependencies>
        <!--內部緩存框架統一採用caffeine-->
        <!--這樣Spring cloud loadbalancer用的本地實例緩存也是基於Caffeine-->
        <dependency>
            <groupId>com.github.ben-manes.caffeine</groupId>
            <artifactId>caffeine</artifactId>
        </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>

        <!--註冊到eureka-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

        <!--spring cloud rpc相關-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</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>
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
        </dependency>
        <dependency>
            <groupId>io.github.resilience4j</groupId>
            <artifactId>resilience4j-spring-cloud2</artifactId>
            <version>${resilience4j-spring-cloud2.version}</version>
        </dependency>
        <!--log4j2異步日誌須要的依賴,全部項目都必須用log4j2和異步日誌配置-->
        <dependency>
            <groupId>com.lmax</groupId>
            <artifactId>disruptor</artifactId>
            <version>${disruptor.version}</version>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Hoxton.SR4</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>

2. 網關

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.7.RELEASE</version>
    </parent>

    <properties>
        <disruptor.version>3.4.2</disruptor.version>
        <resilience4j-spring-cloud2.version>1.1.0</resilience4j-spring-cloud2.version>
    </properties>

    <dependencies>
        <!--內部緩存框架統一採用caffeine-->
        <!--這樣Spring cloud loadbalancer用的本地實例緩存也是基於Caffeine-->
        <dependency>
            <groupId>com.github.ben-manes.caffeine</groupId>
            <artifactId>caffeine</artifactId>
        </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>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</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>
        <dependency>
            <groupId>io.github.resilience4j</groupId>
            <artifactId>resilience4j-spring-cloud2</artifactId>
            <version>${resilience4j-spring-cloud2.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-circuitbreaker-reactor-resilience4j</artifactId>
        </dependency>
        <!--log4j2異步日誌須要的依賴,全部項目都必須用log4j2和異步日誌配置-->
        <dependency>
            <groupId>com.lmax</groupId>
            <artifactId>disruptor</artifactId>
            <version>${disruptor.version}</version>
        </dependency>
    </dependencies>

    <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>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Hoxton.SR4</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

3. Eureka-Server

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.7.RELEASE</version>
    </parent>

    <properties>
        <disruptor.version>3.4.2</disruptor.version>
    </properties>

    <dependencies>
        <!--內部緩存框架統一採用caffeine-->
        <!--這樣Spring cloud loadbalancer用的本地實例緩存也是基於Caffeine-->
        <dependency>
            <groupId>com.github.ben-manes.caffeine</groupId>
            <artifactId>caffeine</artifactId>
        </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>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</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>
        <!--log4j2異步日誌須要的依賴,全部項目都必須用log4j2和異步日誌配置-->
        <dependency>
            <groupId>com.lmax</groupId>
            <artifactId>disruptor</artifactId>
            <version>${disruptor.version}</version>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Hoxton.SR4</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>
相關文章
相關標籤/搜索