您好,登錄后才能下訂單哦!
本篇內容主要講解“如何配置spring cloud 2.x版本Gateway動態路由”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“如何配置spring cloud 2.x版本Gateway動態路由”吧!
本文采用的Spring cloud為2.1.8RELEASE,version=Greenwich.SR3
寫了幾篇關于Spring Cloud Gateway的文章后發現,Gateway涉及的知識范圍太廣了,真是深刻體會了“一入Spring cloud深似海”。
現實生產環境中,使用Spring Cloud Gateway都是作為所有流量的入口,為了保證系統的高可用,盡量避免系統的重啟,所以需要Spring Cloud Gateway的動態路由來處理。之前的文章《Gateway路由網關教程》提供的路由配置,在系統啟動時候,會將路由配置和規則加載到內存當中,無法做到不重啟服務就可以動態的新增、修改、刪除內存中的路由配置和規則。
Spring Cloud Gateway源碼中提供了GatewayControllerEndpoint類來修改路由配置,但是官方文檔好像并沒有做詳細的使用說明,只是簡單介紹了幾個簡單的api接口。感興趣的小伙伴可以先查看官方文檔(第11章節 Actuator API)。
引致官方文檔:
The
/gateway
actuator endpoint allows to monitor and interact with a Spring Cloud Gateway application. To be remotely accessible, the endpoint has to be enabled and exposed via HTTP or JMX in the application properties.
在原來spring-gateway的基礎上增加spring-boot-starter-actuator依賴
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>
management: endpoints: web: exposure: include: "*"
配置說明:management.endpoints.web.exposure.include 暴露所有的gateway端點
啟動服務,訪問http://localhost:8100/actuator/gateway/routes,這是我們可以看到所有的routes信息。 image-20191102225203034.png 我們也可以訪問單個路由信息:http://localhost:8100/actuator/gateway/routes/CompositeDiscoveryClient_EUREKA-CLIENT
顯示如下:image-20191102225853005.png
Gateway默認使用的是GatewayControllerEndpoint這個類,GatewayControllerEndpoint又繼承了AbstractGatewayControllerEndpoint類。
提供的方法:(只列具了幾個相關方法,其他方法小伙們可以自行查看源碼)
/gateway/routes 查詢所有路由信息
/gateway/routes/{id} 根據路由id查詢單個信息
/gateway/routes/{id} @PostMapping 新增一個路由信息
/gateway/routes/{id} @DeleteMapping 刪除一個路由信息
我們可根據/gateway/routes返回的路由信息,來模仿一個@PostMapping請求參數
{ "uri": "http://httpbin.org:80", "predicates": [ { "args": { "pattern": "/ribbon/**" }, "name": "Path" } ], "filters": [] }
這是我們可以通過postman來發送一個post請求,如圖所示:
response返回1證明已經插入成功,我們可以通過http://localhost:8100/actuator/gateway/routes/查看路由信息,顯示結果如下:
截圖紅框中的信息就是新增加的
我們可以直接用postman模擬DeleteMapping請求,http://localhost:8100/actuator/gateway/routes/addroutes
顯示如下:
這時候我們在訪問http://localhost:8100/actuator/gateway/routes,可以看到新增加的路由已經被刪除成功了。
基于Spring Cloud Gateway默認方法實現的動態路由我就完成了,在前言中我已經提到了,這種方式是基于jvm內存實現,一旦服務重啟,新增的路由配置信息就是完全消失了。所有這個時候我們可以考慮是否可以參考GatewayControllerEndpoint這類,自己實現一套動態路由方法,然后將路由信息持久化。
可以自定義實體類,我這里偷了一個懶,直接用了Gateway的RouteDefinition類,感興趣的小伙伴可以參考RouteDefinition類自己擴展,然后寫一個Convert類將自定義的類轉換成RouteDefinition就可以了。
我這邊采用redis做為路由配置的信息的持久層,所以寫了一個RedisRouteDefinitionRepository。
package spring.cloud.demo.spring.gateway.component; import com.google.common.collect.Lists; import org.springframework.cloud.gateway.route.RouteDefinition; import org.springframework.cloud.gateway.route.RouteDefinitionRepository; import org.springframework.cloud.gateway.support.NotFoundException; import org.springframework.stereotype.Component; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import spring.cloud.demo.spring.gateway.redis.RedisUtils; import spring.cloud.demo.spring.gateway.util.JsonUtils; import javax.annotation.Resource; import java.util.List; /** * @auther: maomao * @DateT: 2019-11-03 */ @Component public class RedisRouteDefinitionRepository implements RouteDefinitionRepository { //存儲的的key private final static String KEY = "gateway_dynamic_route"; @Resource private RedisUtils redisUtils; /** * 獲取路由信息 * @return */ @Override public Flux<RouteDefinition> getRouteDefinitions() { List<RouteDefinition> gatewayRouteEntityList = Lists.newArrayList(); redisUtils.hgets(KEY).stream().forEach(route -> { RouteDefinition result = JsonUtils.parseJson(route.toString(), RouteDefinition.class); gatewayRouteEntityList.add(result); }); return Flux.fromIterable(gatewayRouteEntityList); } /** * 新增 * @param route * @return */ @Override public Mono<Void> save(Mono<RouteDefinition> route) { return route.flatMap(routeDefinition -> { redisUtils.hset(KEY, routeDefinition.getId(), JsonUtils.toString(routeDefinition)); return Mono.empty(); }); } /** * 刪除 * @param routeId * @return */ @Override public Mono<Void> delete(Mono<String> routeId) { return routeId.flatMap(id -> { if (redisUtils.hHashKey(KEY, id)) { redisUtils.hdel(KEY, id); return Mono.empty(); } return Mono.defer(() -> Mono.error(new NotFoundException("route definition is not found, routeId:" + routeId))); }); } }
package spring.cloud.demo.spring.gateway.controller; import lombok.extern.slf4j.Slf4j; import org.springframework.cloud.gateway.route.RouteDefinition; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import reactor.core.publisher.Mono; import spring.cloud.demo.spring.gateway.service.GatewayDynamicRouteService; import javax.annotation.Resource; /** * 自定義動態路由 * @auther: maomao * @DateT: 2019-11-03 */ @RestController @RequestMapping("/gateway") @Slf4j public class GatewayDynamicRouteController { @Resource private GatewayDynamicRouteService gatewayDynamicRouteService; @PostMapping("/add") public String create(@RequestBody RouteDefinition entity) { int result = gatewayDynamicRouteService.add(entity); return String.valueOf(result); } @PostMapping("/update") public String update(@RequestBody RouteDefinition entity) { int result = gatewayDynamicRouteService.update(entity); return String.valueOf(result); } @DeleteMapping("/delete/{id}") public Mono<ResponseEntity<Object>> delete(@PathVariable String id) { return gatewayDynamicRouteService.delete(id); } }
package spring.cloud.demo.spring.gateway.service; import org.springframework.cloud.gateway.event.RefreshRoutesEvent; import org.springframework.cloud.gateway.route.RouteDefinition; import org.springframework.cloud.gateway.support.NotFoundException; import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationEventPublisherAware; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import reactor.core.publisher.Mono; import spring.cloud.demo.spring.gateway.component.RedisRouteDefinitionRepository; import javax.annotation.Resource; /** * @auther: maomao * @DateT: 2019-11-03 */ @Service public class GatewayDynamicRouteService implements ApplicationEventPublisherAware { @Resource private RedisRouteDefinitionRepository redisRouteDefinitionRepository; private ApplicationEventPublisher applicationEventPublisher; /** * 增加路由 * @param routeDefinition * @return */ public int add(RouteDefinition routeDefinition) { redisRouteDefinitionRepository.save(Mono.just(routeDefinition)).subscribe(); applicationEventPublisher.publishEvent(new RefreshRoutesEvent(this)); return 1; } /** * 更新 * @param routeDefinition * @return */ public int update(RouteDefinition routeDefinition) { redisRouteDefinitionRepository.delete(Mono.just(routeDefinition.getId())); redisRouteDefinitionRepository.save(Mono.just(routeDefinition)).subscribe(); applicationEventPublisher.publishEvent(new RefreshRoutesEvent(this)); return 1; } /** * 刪除 * @param id * @return */ public Mono<ResponseEntity<Object>> delete(String id) { return redisRouteDefinitionRepository.delete(Mono.just(id)).then(Mono.defer(() -> Mono.just(ResponseEntity.ok().build()))) .onErrorResume(t -> t instanceof NotFoundException, t -> Mono.just(ResponseEntity.notFound().build())); } @Override public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) { this.applicationEventPublisher = applicationEventPublisher; } }
application.yml配置要暴漏Gateway的所有端點,可以看考之前的配置信息。
啟動Spring cloud Gateway服務,先訪問http://localhost:8100/actuator/gateway/routes,查看已有的路由配置信息。然后我們用postman請求add方法,http://localhost:8100/gateway/add,如果所示:
注意截圖中紅框的內容。證明已經新增成功。
這時我們在訪問http://localhost:8100/actuator/gateway/routes查看結果。如果所示:
同理我們可以訪問update和delete方法,我這里就不過多描述了。
自定義動態路由核心原理其實就要重寫網關模塊,也就是之前提到的RedisRouteDefinitionRepository類。我這里偷懶沒有重新定義對應的實體類,這里需要注意的是,傳入參數一定要按照application.yml中配置的格式,然后轉成json,如果格式不正確會報錯。
gitHub地址
<center><font color=red>《Srping Cloud 2.X小白教程》目錄</font></center>
spring cloud 2.x版本 Eureka Server服務注冊中心教程
spring cloud 2.x版本 Eureka Client服務提供者教程
spring cloud 2.x版本 Ribbon服務發現教程(內含集成Hystrix熔斷機制)
spring cloud 2.x版本 Feign服務發現教程(內含集成Hystrix熔斷機制)
spring cloud 2.x版本 Zuul路由網關教程
spring cloud 2.x版本 config分布式配置中心教程
spring cloud 2.x版本 Hystrix Dashboard斷路器教程
spring cloud 2.x版本 Gateway路由網關教程
spring cloud 2.x版本 Gateway自定義過濾器教程
spring cloud 2.x版本 Gateway熔斷、限流教程
spring cloud 2.x版本 Gateway動態路由教程
到此,相信大家對“如何配置spring cloud 2.x版本Gateway動態路由”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。