本文主要介紹Spring Gateway透過整合nacos實現路由動態配置,達到不重啟API閘道器實現動態暴露內部微服務介面的目的。主要流程如下:
一、建立Maven專案test-gateway, pom檔案如下:
二、建立啟動類Apllication.java,內容如下:
package com。test。gateway;import org。springframework。boot。SpringApplication;import org。springframework。boot。autoconfigure。SpringBootApplication;import org。springframework。cloud。client。discovery。EnableDiscoveryClient;import org。springframework。context。annotation。ComponentScan;@EnableDiscoveryClient@SpringBootApplication@ComponentScan(basePackages = { “com。test。gateway”})public class GatewayApplication { public static void main(String[] args) { System。setProperty(“csp。sentinel。app。type”, “1”); SpringApplication。run(GatewayApplication。class, args); }}
三、建立閘道器呼叫nacos配置類GatewayConfig.java
package com。test。gateway。config;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; }}
四、建立動態路由管理服務
1、建立動態路管理類DynamicRouteServiceImpl。java
package com。test。gateway。config;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”; }}
2、建立透過nacos對路由動態管理類DynamicRouteServiceImplByNacos。java
package com。test。gateway。config;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
五、建立閘道器服務配置檔案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 dynamic router confignacos: gateway: route: config: data-id: gateway_dynamic_router group: DEFAULT_GROUP
1、test_gateway_commons。yml配置檔案內容下:
#sentinel 相關配置spring: cloud: sentinel: transport: dashboard: http://127。0。0。1。2: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: ‘*’
2、JSON路由配置檔案gateway_dynamic_router的內容如下:
[{ “id”: “order-router”, “order”: 0, “predicates”: [{ “args”: { “pattern”: “/orders/**” }, “name”: “Path” }], “uri”: “lb://order-service”},{ “id”: “user-router”, “order”: 2, “predicates”: [{ “args”: { “pattern”: “/users/**” }, “name”: “Path” }], “filters”:[ { “name”:“StripPrefix”, “args”:{“_genkey_0”:1} } ], “uri”: “lb://test-user-service”}]
透過以上步驟就實現了Spring Gateway整合nacos實現路由動態配置的功能。以後只要修改gateway_dynamic_router 檔案就可以實現服務的微服務的介面暴露和下線功能。
demo程式碼地址如下:https://gitee。com/sharepublicly/test-gateway