Spring Gateway 整合Nacos 實現動態路由配置

透過Spring Gateway 整合Nacos實現配置管理,並且實現動態路由管理。

一、建立test-gateway專案,POM檔案如下:

4。0。0 com。golte。parent golte-parent 1。0。0 com。golte。gateway golte-gateway 0。0。1-SNAPSHOT golte-gateway Gateway project for Spring Boot 1。8 Hoxton。SR8 2。2。3。RELEASE 1。2。73 org。springframework。cloud spring-cloud-starter-gateway com。alibaba。cloud spring-cloud-starter-alibaba-nacos-config com。alibaba。cloud spring-cloud-starter-alibaba-nacos-discovery <!—— sentinel提供的gataway介面卡 ——> com。alibaba。cloud spring-cloud-alibaba-sentinel-gateway <!—— 對外暴露 Spring Boot 監控指標 ——> org。springframework。boot spring-boot-starter-actuator org。springframework。boot spring-boot-starter-test test org。junit。vintage junit-vintage-engine com。alibaba fastjson ${fastjson。version} org。springframework。cloud spring-cloud-dependencies ${spring。cloud。version} pom import com。alibaba。cloud spring-cloud-alibaba-dependencies ${alibaba。cloud。version} pom import test-gateway org。springframework。boot spring-boot-maven-plugin

二、建立專案配置檔案bootstrap.yml

server: port: 80spring: profiles: active: dev application: name: test-gateway cloud: nacos: config: namespace: ${spring。profiles。active} server-addr: http://127。0。0。1:8848 extension-configs[0]: data-id: test_gateway_commons。yml group: DEFAULT_GROUP refresh: true#Nacos動態路由配置,json格式nacos: gateway: route: config: data-id: gateway_dynamic_router group: DEFAULT_GROUP

a、test_gateway_commons。yml內容如下:

#sentinel 相關配置spring: cloud: sentinel: transport: dashboard: http://127。0。0。1:8080 port: 8719 scg: fallback: mode: response response-status: 455 response-body: error! nacos: discovery: namespace: dev server-addr: 127。0。0。1:8848management: endpoints: web: exposure: include: ‘*’

三、建立閘道器配置類 GatewayConfig.java

import org。springframework。beans。factory。annotation。Value;import org。springframework。context。annotation。Configuration;@Configurationpublic class GatewayConfig { public static final long DEFAULT_TIMEOUT = 30000; public static String NACOS_SERVER_ADDR; public static String NACOS_NAMESPACE; public static String NACOS_ROUTE_DATA_ID; public static String NACOS_ROUTE_GROUP; @Value(“${spring。cloud。nacos。discovery。server-addr}”) public void setNacosServerAddr(String nacosServerAddr) { NACOS_SERVER_ADDR = nacosServerAddr; } @Value(“${spring。cloud。nacos。discovery。namespace}”) public void setNacosNamespace(String nacosNamespace) { NACOS_NAMESPACE = nacosNamespace; } @Value(“${nacos。gateway。route。config。data-id}”) public void setNacosRouteDataId(String nacosRouteDataId) { NACOS_ROUTE_DATA_ID = nacosRouteDataId; } @Value(“${nacos。gateway。route。config。group}”) public void setNacosRouteGroup(String nacosRouteGroup) { NACOS_ROUTE_GROUP = nacosRouteGroup; }}

四、建立動態路由服務DynamicRouteServiceImpl.java

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。RouteDefinitionWriter;import org。springframework。context。ApplicationEventPublisher;import org。springframework。context。ApplicationEventPublisherAware;import org。springframework。stereotype。Service;import lombok。extern。slf4j。Slf4j;import reactor。core。publisher。Mono;/** * 動態更新路由閘道器service * 1)實現一個Spring提供的事宜推送介面ApplicationEventPublisherAware * 2)提供動態路由的基礎方式,可透過獲取bean操作該類的方式。該類提供新增路由、更新路由、刪除路由,然後實現公佈的功效。 */@Slf4j@Servicepublic class DynamicRouteServiceImpl implements ApplicationEventPublisherAware { @Autowired private RouteDefinitionWriter routeDefinitionWriter; /** * 公佈事宜 */ @Autowired private ApplicationEventPublisher publisher; @Override public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) { this。publisher = applicationEventPublisher; } /** * 刪除路由 * @param id * @return */ public String delete(String id) { try { log。info(“gateway delete route id {}”,id); this。routeDefinitionWriter。delete(Mono。just(id)); return “delete success”; } catch (Exception e) { return “delete fail”; } } /** * 更新路由 * @param definition * @return */ public String update(RouteDefinition definition) { try { log。info(“gateway update route {}”,definition); this。routeDefinitionWriter。delete(Mono。just(definition。getId())); } catch (Exception e) { return “update fail,not find route routeId: ”+definition。getId(); } try { routeDefinitionWriter。save(Mono。just(definition))。subscribe(); this。publisher。publishEvent(new RefreshRoutesEvent(this)); return “success”; } catch (Exception e) { return “update route fail”; } } /** * 增添路由 * @param definition * @return */ public String add(RouteDefinition definition) { log。info(“gateway add route {}”,definition); routeDefinitionWriter。save(Mono。just(definition))。subscribe(); this。publisher。publishEvent(new RefreshRoutesEvent(this)); return “success”; }}

五、建立透過Nacos讀取動態路由配置服務DynamicRouteServiceImplByNacos.java

import java。util。List;import java。util。Properties;import java。util。concurrent。Executor;import javax。annotation。PostConstruct;import org。springframework。beans。factory。annotation。Autowired;import org。springframework。cloud。gateway。route。RouteDefinition;import org。springframework。context。annotation。DependsOn;import org。springframework。stereotype。Component;import com。alibaba。fastjson。JSON;import com。alibaba。nacos。api。NacosFactory;import com。alibaba。nacos。api。config。ConfigService;import com。alibaba。nacos。api。config。listener。Listener;import com。alibaba。nacos。api。exception。NacosException;import lombok。extern。slf4j。Slf4j;/** * * 透過nacos下發動態路由設定,監聽Nacos中gateway-route設定 * */@Component@Slf4j@DependsOn({ “gatewayConfig” }) // 依賴於gatewayConfig beanpublic class DynamicRouteServiceImplByNacos { @Autowired private DynamicRouteServiceImpl dynamicRouteService; private ConfigService configService; @PostConstruct public void init() { log。info(“gateway route init。。。”); try { configService = initConfigService(); if (configService == null) { log。warn(“initConfigService fail”); return; } String configInfo = configService。getConfig(GatewayConfig。NACOS_ROUTE_DATA_ID, GatewayConfig。NACOS_ROUTE_GROUP, GatewayConfig。DEFAULT_TIMEOUT); log。info(“獲取閘道器當前設定:\r\n{}”, configInfo); List definitionList = JSON。parseArray(configInfo, RouteDefinition。class); for (RouteDefinition definition : definitionList) { log。info(“update route : {}”, definition。toString()); dynamicRouteService。add(definition); } } catch (Exception e) { log。error(“初始化閘道器路由時發生錯誤”, e); } dynamicRouteByNacosListener(GatewayConfig。NACOS_ROUTE_DATA_ID, GatewayConfig。NACOS_ROUTE_GROUP); } /** * 監聽Nacos下發的動態路由設定 * * @param dataId * @param group */ public void dynamicRouteByNacosListener(String dataId, String group) { try { configService。addListener(dataId, group, new Listener() { @Override public void receiveConfigInfo(String configInfo) { log。info(“舉行閘道器更新:\n\r{}”, configInfo); List definitionList = JSON。parseArray(configInfo, RouteDefinition。class); for (RouteDefinition definition : definitionList) { log。info(“update route : {}”, definition。toString()); dynamicRouteService。update(definition); } } @Override public Executor getExecutor() { log。info(“getExecutor\n\r”); return null; } }); } catch (NacosException e) { log。error(“從nacos吸收動態路由設定失足!!!”, e); } } /** * 初始化閘道器路由 nacos config * * @return */ private ConfigService initConfigService() { try { Properties properties = new Properties(); properties。setProperty(“serverAddr”, GatewayConfig。NACOS_SERVER_ADDR); properties。setProperty(“namespace”, GatewayConfig。NACOS_NAMESPACE); return configService = NacosFactory。createConfigService(properties); } catch (Exception e) { log。error(“初始化閘道器路由時發生錯誤”, e); return null; } }}

六、配置動態路由配置檔案gateway_dynamic_router,內容如下:

[{ “id”: “user-admin-router”, “order”: 5, “predicates”: [{ “args”: { “pattern”: “/useradmin/**” }, “name”: “Path” }], “filters”:[ { “name”:“StripPrefix”, “args”:{“_genkey_0”:1} } ], “uri”: “lb://test-user-admin”},{ “id”: “user-app-router”, “order”: 4, “predicates”: [{ “args”: { “pattern”: “/users/**” }, “name”: “Path” }], “filters”:[ { “name”:“StripPrefix”, “args”:{“_genkey_0”:1} } ], “uri”: “lb://test-user-app”}]

透過以上步驟就完成Spring Gateway 整合Nacos 實現動態路由配置功能。以後只要透過修改Nacos的配置檔案就可以時間服務的動態上下線了。不需要再重啟網關了。