VDN 微服務架構搭建篇(三)基于 Nacos 的 Spring Cloud Gateway 動態路由管理

VDN 微服務架構搭建篇(三):基于 Nacos 的 Spring Cloud Gateway 動態路由管理

在微服務架構中,網關 是整個系統的入口,負責 流量管理、請求路由、安全控制等關鍵功能
Spring Cloud Gateway 作為 Spring 生態官方推薦的網關方案,具備 異步非阻塞 的高性能特性,并支持 動態路由、限流、負載均衡等功能

但在傳統網關架構中,路由規則往往寫死在配置文件中,每次修改都需要 手動調整配置 & 重啟服務,這對于 高可用系統 來說并不友好。

本文將介紹如何使用 Spring Cloud Gateway + Nacos 配置中心 實現 動態路由管理,支持 自動發現、實時更新,讓網關在運行時自動感知微服務變化,無需重啟即可刷新路由規則,從而 提升微服務治理的靈活性和高可用性


一、Spring Cloud Gateway 基礎配置

1.1 添加依賴

pom.xml 中引入 Spring Cloud Gateway 和 Nacos 相關依賴:

<dependencies><!-- Spring Cloud Gateway --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency><!-- Nacos 服務發現 --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><!-- Nacos 配置中心 --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId></dependency><!-- Knife4j 網關文檔 --><dependency><groupId>com.github.xiaoymin</groupId><artifactId>knife4j-gateway-spring-boot-starter</artifactId></dependency>
</dependencies>

1.2 在 Nacos 注冊微服務

application.yml 配置 Nacos 相關信息,使服務可以自動注冊到 Nacos:

spring:application:name: vdn-systemcloud:nacos:discovery:server-addr: 127.0.0.1:8848username: nacospassword: nacosgroup: vdnnamespace: dev17config:server-addr: ${spring.cloud.nacos.discovery.server-addr}username: ${spring.cloud.nacos.discovery.username}password: ${spring.cloud.nacos.discovery.password}namespace: ${spring.cloud.nacos.discovery.namespace}group: ${spring.cloud.nacos.discovery.group}file-extension: yaml

1.3 配置網關的靜態路由

application.yml 中配置 靜態路由(僅用于演示,后續會改為動態路由):

spring:cloud:gateway:routes:- id: vdn-systemuri: lb://vdn-systempredicates:- Path=/sys/**

二、Nacos 動態路由管理

2.1 在 Nacos 配置中心創建動態路由

(1)在 Nacos 控制臺添加配置
  • Data ID: gateway-routes.json
  • Group: vdn
  • Namespace: dev17
  • 內容(JSON 格式):
[{"id": "vdn-system","uri": "lb://vdn-system","predicates": ["Path=/sys/**"]}
]
(2)在 bootstrap.yml 中添加以下配置
spring:application:name: vdn-gatewaycloud:nacos:discovery:# Nacos服務器地址server-addr: localhost:8848username: nacospassword: nacosgroup: vdn# Nacos命名空間namespace: dev17config:server-addr: ${spring.cloud.nacos.discovery.server-addr}username: ${spring.cloud.nacos.discovery.username}password: ${spring.cloud.nacos.discovery.password}namespace: ${spring.cloud.nacos.discovery.namespace}# 配置分組名稱group: ${spring.cloud.nacos.discovery.group}# 文件擴展名,指示配置文件格式file-extension: yaml

2.2 監聽 Nacos 變更 & 動態更新路由

NacosRouteDefinitionRepository 類中實現 監聽 Nacos 變更,動態更新 Gateway 路由


import com.alibaba.cloud.nacos.NacosConfigManager;
import com.alibaba.cloud.nacos.NacosConfigProperties;
import com.alibaba.nacos.api.config.listener.Listener;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.common.utils.StringUtils;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionRepository;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;/*** Nacos 動態路由管理* <p>* 該類用于管理 Spring Cloud Gateway 的路由,并將其存儲在 Nacos 配置中心中。* 通過監聽 Nacos 配置的變更,實現網關路由的動態刷新。*/
@Component
public class NacosRouteDefinitionRepository implements RouteDefinitionRepository {private final Logger log = LoggerFactory.getLogger(NacosRouteDefinitionRepository.class);// 用于發布 Spring 事件(刷新路由)private final ApplicationEventPublisher publisher;// Nacos 配置屬性private final NacosConfigProperties nacosConfigProperties;// Nacos 配置管理器private final NacosConfigManager nacosConfigManager;// JSON 解析工具private final ObjectMapper objectMapper;// Nacos 中存儲路由的 `dataId`private static final String DATA_ID = "gateway-routes.json";// 配置獲取超時時間(單位:毫秒)private static final int CONFIG_TIMEOUT_MS = 3000;/*** 構造方法** @param publisher            Spring 事件發布器,用于動態刷新網關路由* @param nacosConfigProperties Nacos 配置屬性*/@Autowiredpublic NacosRouteDefinitionRepository(ApplicationEventPublisher publisher, NacosConfigProperties nacosConfigProperties) {this.publisher = publisher;this.nacosConfigProperties = nacosConfigProperties;this.nacosConfigManager = new NacosConfigManager(nacosConfigProperties);this.objectMapper = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);// 初始化 Nacos 配置監聽器nacosListener();}/*** Nacos 配置監聽器* <p>* 監聽 Nacos 中 `gateway-routes.json` 發生變更時,觸發 Gateway 重新加載路由。*/private void nacosListener() {// 使用單線程線程池,避免 Listener 需要 Executor 時出錯ExecutorService executorService = Executors.newSingleThreadExecutor();try {nacosConfigManager.getConfigService().addListener(DATA_ID, nacosConfigProperties.getGroup(), new Listener() {@Overridepublic Executor getExecutor() {return executorService;}@Overridepublic void receiveConfigInfo(String configInfo) {log.info("收到新的路由配置: {}", configInfo);// 發布 Spring 事件,觸發網關路由刷新publisher.publishEvent(new RefreshRoutesEvent(this));}});} catch (NacosException e) {log.error("Nacos 監聽器初始化失敗", e);} finally {// 關閉線程池,避免資源泄露executorService.shutdown();}}/*** 獲取 Nacos 中的路由配置* <p>* 該方法會從 Nacos 讀取 `gateway-routes.json` 配置,并解析為 RouteDefinition 列表。** @return 返回 Flux<RouteDefinition>,用于 Gateway 加載路由*/@Overridepublic Flux<RouteDefinition> getRouteDefinitions() {try {// 從 Nacos 讀取配置String routeConfig = nacosConfigManager.getConfigService().getConfig(DATA_ID, nacosConfigProperties.getGroup(), CONFIG_TIMEOUT_MS);// 路由列表List<RouteDefinition> routeDefinitionList = new ArrayList<>();// 如果配置不為空,則解析 JSONif (StringUtils.hasText(routeConfig)) {routeDefinitionList = objectMapper.readValue(routeConfig, new TypeReference<>() {});}return Flux.fromIterable(routeDefinitionList);} catch (Exception e) {log.error("從 Nacos 獲取路由定義失敗", e);return Flux.error(e);}}/*** 保存路由定義* <p>* 該方法會將新的路由定義追加到 `gateway-routes.json` 中,并同步更新到 Nacos。** @param route 需要保存的路由定義* @return 返回 Mono<Void>*/@Overridepublic Mono<Void> save(Mono<RouteDefinition> route) {return route.flatMap(r -> {try {// 將新的 RouteDefinition 轉換為 JSONString routeJson = objectMapper.writeValueAsString(r);// 發布到 NacosnacosConfigManager.getConfigService().publishConfig(DATA_ID, nacosConfigProperties.getGroup(), routeJson);return Mono.empty();} catch (Exception e) {log.error("保存路由定義失敗", e);return Mono.error(e);}});}/**·* 刪除路由定義* <p>* 該方法會從 `gateway-routes.json` 中移除指定的路由 ID,并同步更新 Nacos。** @param routeId 需要刪除的路由 ID* @return 返回 Mono<Void>*/@Overridepublic Mono<Void> delete(Mono<String> routeId) {return routeId.flatMap(id -> {try {// 獲取 Nacos 中的路由配置String routeConfig = nacosConfigManager.getConfigService().getConfig(DATA_ID, nacosConfigProperties.getGroup(), CONFIG_TIMEOUT_MS);// 解析 JSON 為 RouteDefinition 列表List<RouteDefinition> routeDefinitionList = objectMapper.readValue(routeConfig, new TypeReference<>() {});// 刪除指定 ID 的路由routeDefinitionList.removeIf(rd -> rd.getId().equals(id));// 重新生成 JSON 并更新到 NacosString updatedRouteJson = objectMapper.writeValueAsString(routeDefinitionList);nacosConfigManager.getConfigService().publishConfig(DATA_ID, nacosConfigProperties.getGroup(), updatedRouteJson);return Mono.empty();} catch (Exception e) {log.error("刪除路由定義失敗,ID: {}", id, e);return Mono.error(e);}});}
}

三、總結

  1. 動態路由刷新:網關無需重啟,即可自動刷新路由配置。
  2. 中心化管理:所有路由規則存儲于 Nacos 配置中心,便于維護。
  3. 自動發現 & 負載均衡:結合 Nacos 注冊中心,可自動發現新微服務并添加路由。

通過本文的介紹,你已經掌握了 如何基于 Spring Cloud Gateway + Nacos 實現動態路由管理 🎯。
你可以在項目中直接應用這個方案,讓網關更智能、更高效! 🚀🚀🚀


寫在最后

上一篇:👉 VDN 微服務架構搭建篇(二)服務注冊與配置中心Nacos
下一篇:👉 待完善

源碼🚀🚀🚀

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/68173.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/68173.shtml
英文地址,請注明出處:http://en.pswp.cn/web/68173.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

LLAMA-Factory安裝教程(解決報錯cannot allocate memory in static TLS block的問題)

步驟一&#xff1a; 下載基礎鏡像 # 配置docker DNS vi /etc/docker/daemon.json # daemon.json文件中 { "insecure-registries": ["https://swr.cn-east-317.qdrgznjszx.com"], "registry-mirrors": ["https://docker.mirrors.ustc.edu.c…

Java高頻面試之SE-18

hello啊&#xff0c;各位觀眾姥爺們&#xff01;&#xff01;&#xff01;本baby今天又來了&#xff01;哈哈哈哈哈嗝&#x1f436; BIO NIO AIO的區別&#xff1f; 在 Java 網絡編程中&#xff0c;BIO、NIO 和 AIO 是三種不同的 I/O 模型&#xff0c;它們的核心區別在于 阻塞…

藍橋杯刷題DAY3:Horner 法則 前綴和+差分數組 貪心

所謂刷題&#xff0c;最重要的就是細心 &#x1f4cc; 題目描述 在 X 進制 中&#xff0c;每一數位的進制不固定。例如&#xff1a; 最低位 采用 2 進制&#xff0c;第二位 采用 10 進制&#xff0c;第三位 采用 8 進制&#xff0c; 則 X 進制數 321 的十進制值為&#xff…

BUU24 [GXYCTF2019]BabyUpload 1

開局上傳文件 上傳muma.php 上傳.htaccess文件也被打回 再次求助互聯網&#xff0c;才發現這提示給的多么明顯&#xff0c;上傳.htaccess文件是檢查文件類型&#xff08;Contnet-Type&#xff09;&#xff0c;上傳muma.php是檢查后綴里頭有沒有ph &#xff0c;檢查文件類型那…

RabbitMQ 從入門到精通:從工作模式到集群部署實戰(三)

文章目錄 使用CLI管理RabbitMQrabbitmqctlrabbitmq-queuesrabbitmq-diagnosticsrabbitmq-pluginsrabbitmq-streamsrabbitmq-upgraderabbitmqadmin 使用CLI管理RabbitMQ RabbitMQ CLI 工具需要安裝兼容的 Erlang/OTP版本。 這些工具假定系統區域設置為 UTF-8&#xff08;例如en…

3.攻防世界 weak_auth

題目描述提示 是一個登錄界面&#xff0c;需要密碼登錄 進入題目頁面如下 弱口令密碼爆破 用1 or 1 #試試 提示用admin登錄 則嘗試 用戶名admin密碼&#xff1a;123456 直接得到flag 常用弱口令密碼&#xff08;可復制&#xff09; 用戶名 admin admin-- admin or -- admin…

優化深度神經網絡

訓練集、開發集(驗證集)、測試集 偏差與方差 正則化 L2正則 Dropout 隨機丟棄部分神經元輸入&#xff0c;經常用于計算機視覺的神經網絡內&#xff0c;因為通常沒有足夠的訓練數據&#xff0c;很容易出現過擬合的問題 數據增強 訓練集規一化 可以使其圖像更均勻&#xff0c;…

【玩轉 Postman 接口測試與開發2_018】第14章:利用 Postman 初探 API 安全測試

《API Testing and Development with Postman》最新第二版封面 文章目錄 第十四章 API 安全測試1 OWASP API 安全清單1.1 相關背景1.2 OWASP API 安全清單1.3 認證與授權1.4 破防的對象級授權&#xff08;Broken object-level authorization&#xff09;1.5 破防的屬性級授權&a…

Spring @PropertySource:讓你的應用配置更加模塊化和可維護

PropertySource注解在Spring中的作用&#xff0c;就像是給Spring應用配了一個“外部配置箱”。 想象一下&#xff0c;你在開發一個Spring應用時&#xff0c;有很多配置信息需要設置&#xff0c;比如數據庫的連接信息、應用的某些功能開關等。如果這些信息都硬編碼在代碼中&…

RK3576——USB3.2 OTG無法識別到USB設備

問題&#xff1a;使用硬盤接入到OTG接口無熱插拔信息&#xff0c;接入DP顯示屏無法正常識別到顯示設備&#xff0c;但是能通過RKDdevTool工具燒錄系統。 問題分析&#xff1a;由于熱插拔功能實現是靠HUSB311芯片完成的&#xff0c;因此需要先確保HUSB311芯片驅動正常工作。 1. …

docker-compose 配置nginx

前言 前端打包的dist文件在宿主機&#xff0c;nginx運行在docker-compose 問題 nginx.conf 在本地配置可以生效&#xff0c;但是鏈接到容器就報錯 基于本地的nginx運行&#xff0c;本地nginx.conf 如下 server {listen 8081;location / {root /usr/local/software/testweb/…

基于SpringBoot+ Vue的家教管理系統

隨著互聯網技術的發展&#xff0c;信息化管理已經深入到各個行業中。在教育領域&#xff0c;家教管理系統的需求日益增長。傳統的手工管理方式在面對大量信息時&#xff0c;容易出現管理效率低下、數據錯誤率高、修改困難等問題。本文將介紹基于Spring Boot框架、MySQL數據庫開…

【數據結構】樹哈希

目錄 一、樹的同構1. 定義2. 具體理解(1) 結點對應(2) 孩子相同(3) 遞歸性質 3. 示例 二、樹哈希1.定義2.哈希過程&#xff08;1&#xff09;葉節點哈希&#xff08;2&#xff09;非葉節點哈希&#xff08;3&#xff09;組合哈希值 3.性質&#xff08;1&#xff09; 唯一性 \re…

使用DeepSeek的技巧筆記

來源&#xff1a;新年逼自己一把&#xff0c;學會使用DeepSeek R1_嗶哩嗶哩_bilibili 前言 對于DeepSeek而言&#xff0c;我們不再需要那么多的提示詞技巧&#xff0c;但還是要有兩個注意點&#xff1a;你需要理解大語言模型的工作原理與局限,這能幫助你更好的知道AI可完成任務…

【工具篇】ChatGPT:開啟人工智能新紀元

一、ChatGPT 是什么 最近,ChatGPT 可是火得一塌糊涂,不管是在科技圈、媒體界,還是咱們普通人的日常聊天里,都能聽到它的大名。好多人都在討論,這 ChatGPT 到底是個啥 “神器”,能讓大家這么著迷?今天咱就好好嘮嘮。 ChatGPT,全稱是 Chat Generative Pre-trained Trans…

【centOS】搭建公司內網git環境-GitLab 社區版(GitLab CE)

1. 安裝必要的依賴 以 CentOS 7 系統為例&#xff0c;安裝必要的依賴包&#xff1a; sudo yum install -y curl policycoreutils openssh-server openssh-clients postfix sudo systemctl start postfix sudo systemctl enable postfix2. 添加 GitLab 倉庫 curl -sS https:/…

$route 和 $router 的區別是什么?

在 Vue Router 中,$route 和 $router 是兩個不同的對象,它們各自承擔著不同的角色。下面是它們的主要區別: 一、$route 定義$route 是當前路由的信息對象,包含了與當前路由相關的狀態和參數。它是一個只讀對象。 2. 主要屬性 params:動態路由參數,例如 /user/:id 中的 …

node.js 08 express的使用和熱重載nodemon的安裝

一.express的安裝和使用 安裝 npm i express 使用 //引入express const express require(express)//啟動服務器 const app express()//設置get請求地址&#xff0c;獲取請求地址信息&#xff0c;和發送返回的數據 app.get(/bailan,(req, res) > {//req.query可以獲取到客…

Python因為網絡原因安裝依賴庫報錯

現象 在終端運行以下指令 pip install pyautogui pillow keyboard 出現報錯&#xff0c;終端信息如下&#xff1a; PS D:\code\Python> pip install pyautogui pillow keyboard Collecting pyautoguiUsing cached PyAutoGUI-0.9.54.tar.gz (61 kB)Installing build depe…

面試問題記錄1

問題一&#xff1a;性能測試步驟 性能測試步驟主要包括以下幾個階段&#xff1a; ?1. 需求分析階段? 明確測試目標&#xff0c;了解性能測試需求&#xff0c;包括業務列表、性能指標、測試環境、數據量等詳細需求?12。熟悉項目相關的資源&#xff0c;如架構設計、軟硬件環…