1. 程式人生 > >跟我學SpringCloud | 第十七篇:服務閘道器Zuul基於Apollo動態路由

跟我學SpringCloud | 第十七篇:服務閘道器Zuul基於Apollo動態路由

目錄

  • SpringCloud系列教程 | 第十七篇:服務閘道器Zuul基於Apollo動態路由
    • Apollo概述
    • Apollo相比於Spring Cloud Config優勢
    • 工程實戰
    • 示例程式碼

SpringCloud系列教程 | 第十七篇:服務閘道器Zuul基於Apollo動態路由

Springboot: 2.1.7.RELEASE

SpringCloud: Greenwich.SR2

上一篇文章我們介紹了Gateway基於Nacos動態閘道器路由的解決方案《Spring Cloud Alibaba | Gateway基於Nacos動態閘道器路由》,同為Spring Cloud服務閘道器元件的Spring Cloud Zuul在生產環境中使用更為廣泛,那麼它有沒有方便的動態路由解決方案呢?答案當然是肯定的,Zuul作為一個老牌的開源服務閘道器元件,動態路由對它來講是一個十分必要的功能,畢竟我們不能隨便重啟服務閘道器,服務閘道器是一個微服務系統的大門,今天我們介紹的Zuul動態路由的解決方案來自於攜程開源的配置中心Apollo。

Apollo概述

Apollo(阿波羅)是攜程框架部門研發的開源配置管理中心,能夠集中化管理應用不同環境、不同叢集的配置,配置修改後能夠實時推送到應用端,並且具備規範的許可權、流程治理等特性。

Apollo支援4個維度管理Key-Value格式的配置:

  1. application (應用)
  2. environment (環境)
  3. cluster (叢集)
  4. namespace (名稱空間)

Apollo相比於Spring Cloud Config優勢

前面的文章我們也介紹了Spring Cloud Config《跟我學SpringCloud | 第七篇:Spring Cloud Config 配置中心高可用和refresh》,但是它和我們今天要使用的相比,又有什麼劣勢呢?

Spring Cloud Config的精妙之處在於它的配置儲存於Git,這就天然的把配置的修改、許可權、版本等問題隔離在外。通過這個設計使得Spring Cloud Config整體很簡單,不過也帶來了一些不便之處。

功能點 Apollo Spring Cloud Config 備註
配置介面 一個介面管理不同環境、不同叢集配置 無,需要通過git操作
配置生效時間 實時 重啟生效,或手動refresh生效 Spring Cloud Config需要通過Git webhook,加上額外的訊息佇列才能支援實時生效
版本管理 介面上直接提供釋出歷史和回滾按鈕 無,需要通過git操作
灰度釋出 支援 不支援
授權、稽核、審計 介面上直接支援,而且支援修改、釋出許可權分離 需要通過git倉庫設定,且不支援修改、釋出許可權分離
例項配置監控 可以方便的看到當前哪些客戶端在使用哪些配置 不支援
配置獲取效能 快,通過資料庫訪問,還有快取支援 較慢,需要從git clone repository,然後從檔案系統讀取
客戶端支援 原生支援所有Java和.Net應用,提供API支援其它語言應用,同時也支援Spring annotation獲取配置 支援Spring應用,提供annotation獲取配置 Apollo的適用範圍更廣一些

工程實戰

這裡需要準備一個Apollo配置中心,具體如何構建Apollo配置中心我這裡不多做介紹,大家可以參考Apollo的官方文件:https://github.com/ctripcorp/apollo/wiki

  1. 工程依賴pom.xml如下:

程式碼清單:chapter16/pom.xml
***

<dependency>
    <groupId>com.ctrip.framework.apollo</groupId>
    <artifactId>apollo-client</artifactId>
    <version>${apollo-client.version}</version>
</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-netflix-zuul</artifactId>
</dependency>
  1. 配置檔案

app.properties如下:

程式碼清單:chapter16/src/main/resources/META-INF/app.properties
***

app.id=123456789

這裡配置的app.id是在Apollo中建立專案時配置的。

application.yml如下:

程式碼清單:chapter16/src/main/resources/application.yml
***

apollo:
  bootstrap:
    enabled: true
    namespaces: zuul-config-apollo
  Meta: http://localhost:8080

在Apollo上新建一個名稱空間zuul-config-apollo

其餘的配置都配置在Apollo中,具體如圖:

  1. 啟動主類Chapter16Application.java如下:

程式碼清單:chapter16/src/main/java/com/springcloud/chapter16/Chapter16Application.java
***

@SpringBootApplication
@EnableEurekaClient
@EnableZuulProxy
@EnableApolloConfig
public class Chapter16Application {

    public static void main(String[] args) {
        SpringApplication.run(Chapter16Application.class, args);
    }

}

其中@EnableZuulProxy表示開啟Zuul閘道器代理,@EnableApolloConfig表示開啟Apollo配置。

  1. 路由重新整理

程式碼路徑:chapter16/src/main/java/com/springcloud/chapter16/config/ZuulProxyRefresher.java
***

@Component
public class ZuulProxyRefresher implements ApplicationContextAware {

    private ApplicationContext applicationContext;

    @Autowired
    private RouteLocator routeLocator;

    @ApolloConfigChangeListener(value = "zuul-config-apollo")
    public void onChange(ConfigChangeEvent changeEvent) {
        boolean zuulProxyChanged = false;
        for (String changedKey : changeEvent.changedKeys()) {
            if (changedKey.startsWith("zuul.")) {
                zuulProxyChanged = true;
                break;
            }
        }
        if (zuulProxyChanged) {
            refreshZuulProxy(changeEvent);
        }
    }

    private void refreshZuulProxy(ConfigChangeEvent changeEvent) {
        this.applicationContext.publishEvent(new EnvironmentChangeEvent(changeEvent.changedKeys()));
        this.applicationContext.publishEvent(new RoutesRefreshedEvent(routeLocator));
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}

@ApolloConfigChangeListener(value = "zuul-config-apollo")中value的預設引數是application,因為這裡我們自定義了namespace,所以需要指定,我們使用@ApolloConfigChangeListener監聽Apollo的配置下發,有配置更新時會呼叫refreshZuulProxy()重新整理路由資訊。

  1. 測試

我們啟動Client-Apollo工程和Zuul-Apollo工程,開啟瀏覽器訪問:http://localhost:9091/client/hello ,頁面可以正常顯示,我們在Apollo中修改路由資訊,具體如圖:

修改完後點擊發布,待發布成功後,我們重新整理瀏覽器,之前的路由訪問已經報錯404,我們使用修改過後的路由http://localhost:9091/client_new/hello ,頁面可以正常顯示Hello, i am dev from apollo update.,測試成功,我們通過Apollo實現了Zuul的路由資訊動態重新整理。

示例程式碼

Github-示例程式碼

Gitee-示例