前言
當(dāng)我們的網(wǎng)關(guān)Gateway程序開發(fā)完成之后,需要部署到生產(chǎn)環(huán)境,這個時候你的程序不能是單點(diǎn)運(yùn)行的,肯定是多節(jié)點(diǎn)啟動(獨(dú)立部署或者Docker等容器部署),防止單節(jié)點(diǎn)故障導(dǎo)致整個服務(wù)不能訪問,網(wǎng)關(guān)是對客戶端的入口與出口,在生產(chǎn)運(yùn)行中極為重要,哪怕是簡單的重啟也會導(dǎo)致部分請求的丟失。
網(wǎng)關(guān)的路由配置這個時候就是一個大問題,是代碼里面編寫還是配置文件配置?他們都有一個致命的缺點(diǎn),當(dāng)有新的程序需要接入到網(wǎng)關(guān)進(jìn)行路由或者有服務(wù)需要下線時候需要修改代碼或者配置,然后重啟整個網(wǎng)關(guān)程序,導(dǎo)致其他正常的服務(wù)路由受到了影響。
所以在實(shí)際生產(chǎn)環(huán)境中為了保證高可靠和高可用,是盡量要避免重啟網(wǎng)關(guān),所以實(shí)現(xiàn)動態(tài)路由是非常有必要的;
本文主要介紹 Spring Cloud Gateway 實(shí)現(xiàn)的思路,并且把路由信息存放在外部源中,這粒以Nacos為數(shù)據(jù)源來講解
實(shí)現(xiàn)要點(diǎn)
要實(shí)現(xiàn)動態(tài)路由只需關(guān)注下面4個點(diǎn)
- 網(wǎng)關(guān)啟動時,動態(tài)路由的數(shù)據(jù)怎樣加載進(jìn)來
- 靜態(tài)路由與動態(tài)路由以那個為準(zhǔn)
- 監(jiān)聽動態(tài)路由的數(shù)據(jù)源變化
- 數(shù)據(jù)有變化時怎樣通知gateway刷新路由
ps:靜態(tài)路由指的是配置文件里寫死的路由配置
具體實(shí)現(xiàn)
Spring Cloud Gateway 中加載路由信息分別由以下幾個類負(fù)責(zé)
- PropertiesRouteDefinitionLocator:從配置文件中讀取路由信息(如YML、Properties等)
- RouteDefinitionRepository:從存儲器中讀取路由信息(如內(nèi)存、配置中心、redis、MySQL等)
- DiscoveryClientRouteDefinitionLocator:從注冊中心中讀取路由信息(如Nacos、Eurka、Zookeeper等)
我們可以通過自定義 RouteDefinitionRepository 的實(shí)現(xiàn)類來實(shí)現(xiàn)動態(tài)路由的目的
實(shí)現(xiàn)動態(tài)路由的數(shù)據(jù)加載
我們可以查看源碼RouteDefinitionRepository的存儲的實(shí)現(xiàn)類,只有InMemoryRouteDefinitionRepository,此實(shí)現(xiàn)類是存放在內(nèi)存中的。
我們可以重新定義一個nacos作為存儲的實(shí)現(xiàn),看下面的代碼



上面代碼核心的是 重寫 getRouteDefinitions 方法實(shí)現(xiàn)路由信息的讀取 ;這個方法中涉及到了ConfigService對象Api的方法。
管理Api方法,這個老顧這里不詳細(xì)說了;小伙伴們可以理解為就是操作nacos config的對象
配置Nacos監(jiān)聽器,監(jiān)聽路由配置信息的變化,也是利用api方法,也就是addListener方法;此方法一看就知道,就是用來監(jiān)聽config信息變化的。
此addListener方法中路由變化只需要往 ApplicationEventPublisher 推送一個 RefreshRoutesEvent 事件,即刻gateway會自動監(jiān)聽該事件并調(diào)用 getRouteDefinitions 方法更新路由信息 。
這樣就達(dá)到了動態(tài)更新路由了。
配置類
為了更好的把此動態(tài)路由作為公共core,我們需要利用配置類,達(dá)到是否啟用的方式;可以讓開發(fā)者自行配置。

上面的配置類,有兩個重要的@ConditionalOnProperty,這個就是用來控制是否啟用動態(tài)路由,以及是否用nacos作為存儲。
里面還有@Value注解定義我們存儲路由信息的DataId和Group,application.yml如果不配置默認(rèn)值為scg-routes和SCG_GATEWAY
添加Nacos路由配置
在同一個namespace中創(chuàng)建scg-routes和SCG_GATEWAY

格式選擇json,json體里面的格式其實(shí)就是RouteDefinition類的屬性

注意上面的配置的json是數(shù)組格式哦,也就是可以有很多路由哦
[{
"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"
}]
測試
在網(wǎng)關(guān)項目中的application.yml中配置
rainbow:
gateway:
dynamicRoute:
enabled: true
啟動網(wǎng)關(guān),就可以了;為了方便看到網(wǎng)關(guān)當(dāng)前的路由信息,我們需要引入
<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,我們可以發(fā)現(xiàn)路由及時得到了更改。
老顧只修改了route_id的名稱,路由就及時更新了

我們也看到了控制臺日志也有相應(yīng)的變化

總結(jié)
gateway的動態(tài)路由是非常實(shí)用的功能,在生產(chǎn)環(huán)境中是必備功能,小伙伴們一定要掌握哦,當(dāng)然小伙伴們也可以用其他的數(shù)據(jù)源。謝謝!!!