前言
當我們的網關Gateway程序開發完成之后,需要部署到生產環境,這個時候你的程序不能是單點運行的,肯定是多節點啟動(獨立部署或者Docker等容器部署),防止單節點故障導致整個服務不能訪問,網關是對客戶端的入口與出口,在生產運行中極為重要,哪怕是簡單的重啟也會導致部分請求的丟失。
網關的路由配置這個時候就是一個大問題,是代碼里面編寫還是配置文件配置?他們都有一個致命的缺點,當有新的程序需要接入到網關進行路由或者有服務需要下線時候需要修改代碼或者配置,然后重啟整個網關程序,導致其他正常的服務路由受到了影響。
所以在實際生產環境中為了保證高可靠和高可用,是盡量要避免重啟網關,所以實現動態路由是非常有必要的;
本文主要介紹 Spring Cloud Gateway 實現的思路,并且把路由信息存放在外部源中,這粒以Nacos為數據源來講解
實現要點
要實現動態路由只需關注下面4個點
- 網關啟動時,動態路由的數據怎樣加載進來
- 靜態路由與動態路由以那個為準
- 監聽動態路由的數據源變化
- 數據有變化時怎樣通知gateway刷新路由
ps:靜態路由指的是配置文件里寫死的路由配置
具體實現
Spring Cloud Gateway 中加載路由信息分別由以下幾個類負責
- PropertiesRouteDefinitionLocator:從配置文件中讀取路由信息(如YML、Properties等)
- RouteDefinitionRepository:從存儲器中讀取路由信息(如內存、配置中心、redis、MySQL等)
- DiscoveryClientRouteDefinitionLocator:從注冊中心中讀取路由信息(如Nacos、Eurka、Zookeeper等)
我們可以通過自定義 RouteDefinitionRepository 的實現類來實現動態路由的目的
實現動態路由的數據加載
我們可以查看源碼RouteDefinitionRepository的存儲的實現類,只有InMemoryRouteDefinitionRepository,此實現類是存放在內存中的。
我們可以重新定義一個nacos作為存儲的實現,看下面的代碼
上面代碼核心的是 重寫 getRouteDefinitions 方法實現路由信息的讀取 ;這個方法中涉及到了ConfigService對象Api的方法。
管理Api方法,這個老顧這里不詳細說了;小伙伴們可以理解為就是操作nacos config的對象
配置Nacos監聽器,監聽路由配置信息的變化,也是利用api方法,也就是addListener方法;此方法一看就知道,就是用來監聽config信息變化的。
此addListener方法中路由變化只需要往 ApplicationEventPublisher 推送一個 RefreshRoutesEvent 事件,即刻gateway會自動監聽該事件并調用 getRouteDefinitions 方法更新路由信息 。
這樣就達到了動態更新路由了。
配置類
為了更好的把此動態路由作為公共core,我們需要利用配置類,達到是否啟用的方式;可以讓開發者自行配置。
上面的配置類,有兩個重要的@ConditionalOnProperty,這個就是用來控制是否啟用動態路由,以及是否用nacos作為存儲。
里面還有@Value注解定義我們存儲路由信息的DataId和Group,application.yml如果不配置默認值為scg-routes和SCG_GATEWAY
添加Nacos路由配置
在同一個namespace中創建scg-routes和SCG_GATEWAY
格式選擇json,json體里面的格式其實就是RouteDefinition類的屬性
注意上面的配置的json是數組格式哦,也就是可以有很多路由哦
[{
"id": "baidu",
"order": 0,
"predicates": [{
"args": {
"pattern": "/baidu/**"
},
"name": "Path"
}],
"uri": "https://www.baidu.com"
},{
"id": "sina",
"order": 2,
"predicates": [{
"args": {
"pattern": "/sina/**"
},
"name": "Path"
}],
"uri": "http://www.sina.com.cn"
}]
測試
在網關項目中的application.yml中配置
rainbow:
gateway:
dynamicRoute:
enabled: true
啟動網關,就可以了;為了方便看到網關當前的路由信息,我們需要引入
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
并且在application.yml中配置
management:
endpoints:
web:
exposure:
include: '*'
endpoint:
gateway:
enabled: true
health:
show-details: always
這樣我們就可以訪問http://localhost:8081/actuator/gateway/routes,就可以看到路由信息
小伙伴們可以嘗試修改一下nacos中的dataId為scg-routes,我們可以發現路由及時得到了更改。
老顧只修改了route_id的名稱,路由就及時更新了
我們也看到了控制臺日志也有相應的變化
總結
gateway的動態路由是非常實用的功能,在生產環境中是必備功能,小伙伴們一定要掌握哦,當然小伙伴們也可以用其他的數據源。謝謝!!!