SpringCloud Gateway使用redis实现动态路由的方法
1.将actuator端点暴露出来
management:
endpoints:
web:
exposure:
include:"*"
2.redis配置
https://www.nhooo.com/article/203766.htm
3.将原内存路由持久化到redis
@Component publicclassRedisRouteDefinitionRepositoryimplementsRouteDefinitionRepository{ /** *hash存储的key */ publicstaticfinalStringGATEWAY_ROUTES="gateway_dynamic_route"; @Resource privateStringRedisTemplateredisTemplate; /** *获取路由信息 *@return */ @Override publicFluxgetRouteDefinitions(){ List routeDefinitions=newArrayList<>(); redisTemplate.opsForHash().values(GATEWAY_ROUTES).stream() .forEach(routeDefinition->routeDefinitions.add(JSON.parseObject(routeDefinition.toString(),RouteDefinition.class))); returnFlux.fromIterable(routeDefinitions); } @Override publicMono save(Mono route){ returnroute.flatMap(routeDefinition->{ redisTemplate.opsForHash().put(GATEWAY_ROUTES,routeDefinition.getId(),JSONObject.toJSONString(routeDefinition)); returnMono.empty(); }); } @Override publicMono delete(Mono routeId){ returnrouteId.flatMap(id->{ if(redisTemplate.opsForHash().hasKey(GATEWAY_ROUTES,id)){ redisTemplate.opsForHash().delete(GATEWAY_ROUTES,id); returnMono.empty(); } returnMono.defer(()->Mono.error(newNotFoundException("routedefinitionisnotfound,routeId:"+routeId))); }); } }
4.重写动态路由服务
@Service publicclassGatewayDynamicRouteServiceimplementsApplicationEventPublisherAware{ @Resource privateRedisRouteDefinitionRepositoryredisRouteDefinitionRepository; privateApplicationEventPublisherapplicationEventPublisher; /** *增加路由 *@paramrouteDefinition *@return */ publicintadd(RouteDefinitionrouteDefinition){ redisRouteDefinitionRepository.save(Mono.just(routeDefinition)).subscribe(); applicationEventPublisher.publishEvent(newRefreshRoutesEvent(this)); return1; } /** *更新 *@paramrouteDefinition *@return */ publicintupdate(RouteDefinitionrouteDefinition){ redisRouteDefinitionRepository.delete(Mono.just(routeDefinition.getId())); redisRouteDefinitionRepository.save(Mono.just(routeDefinition)).subscribe(); applicationEventPublisher.publishEvent(newRefreshRoutesEvent(this)); return1; } /** *删除 *@paramid *@return */ publicMono>delete(Stringid){ returnredisRouteDefinitionRepository.delete(Mono.just(id)).then(Mono.defer(()->Mono.just(ResponseEntity.ok().build()))) .onErrorResume(t->tinstanceofNotFoundException,t->Mono.just(ResponseEntity.notFound().build())); } @Override publicvoidsetApplicationEventPublisher(ApplicationEventPublisherapplicationEventPublisher){ this.applicationEventPublisher=applicationEventPublisher; } }
5.对外暴露接口
@RestController @RequestMapping("/gateway") publicclassGatewayDynamicRouteController{ @Resource privateGatewayDynamicRouteServicegatewayDynamicRouteService; @PostMapping("/add") publicStringcreate(@RequestBodyRouteDefinitionentity){ intresult=gatewayDynamicRouteService.add(entity); returnString.valueOf(result); } @PostMapping("/update") publicStringupdate(@RequestBodyRouteDefinitionentity){ intresult=gatewayDynamicRouteService.update(entity); returnString.valueOf(result); } @DeleteMapping("/delete/{id}") publicMono>delete(@PathVariableStringid){ returngatewayDynamicRouteService.delete(id); } }
测试
测试前删除我们配置的静态路由,因为静态路由和redis动态路由同时存在时取并集。
访问http://localhost:2000/actuator/gateway/routes,可以看到只有默认路由。
[ { "route_id":"CompositeDiscoveryClient_consul", "route_definition":{ "id":"CompositeDiscoveryClient_consul", "predicates":[ { "name":"Path", "args":{ "pattern":"/consul/**" } } ], "filters":[ { "name":"RewritePath", "args":{ "regexp":"/consul/(?.*)", "replacement":"/${remaining}" } } ], "uri":"lb://consul", "order":0 }, "order":0 }, { "route_id":"CompositeDiscoveryClient_idc-gateway", "route_definition":{ "id":"CompositeDiscoveryClient_idc-gateway", "predicates":[ { "name":"Path", "args":{ "pattern":"/idc-gateway/**" } } ], "filters":[ { "name":"RewritePath", "args":{ "regexp":"/idc-gateway/(? .*)", "replacement":"/${remaining}" } } ], "uri":"lb://idc-gateway", "order":0 }, "order":0 }, { "route_id":"CompositeDiscoveryClient_idc-provider1", "route_definition":{ "id":"CompositeDiscoveryClient_idc-provider1", "predicates":[ { "name":"Path", "args":{ "pattern":"/idc-provider1/**" } } ], "filters":[ { "name":"RewritePath", "args":{ "regexp":"/idc-provider1/(? .*)", "replacement":"/${remaining}" } } ], "uri":"lb://idc-provider1", "order":0 }, "order":0 }, { "route_id":"CompositeDiscoveryClient_idc-provider2", "route_definition":{ "id":"CompositeDiscoveryClient_idc-provider2", "predicates":[ { "name":"Path", "args":{ "pattern":"/idc-provider2/**" } } ], "filters":[ { "name":"RewritePath", "args":{ "regexp":"/idc-provider2/(? .*)", "replacement":"/${remaining}" } } ], "uri":"lb://idc-provider2", "order":0 }, "order":0 } ]
这个时候访问http://192.168.124.5:2000/idc-provider1/provider1/1根据结果可以推测能正确路由到provider1,测试结果一致。
创建provider1路由,将路径设置为/p1/**,测试是否生效。
POST请求http://localhost:2000/gateway/add
{ "id":"provider1", "predicates":[ { "name":"Path", "args":{ "_genkey_0":"/p1/**" } }, { "name":"RemoteAddr", "args":{ "_genkey_0":"192.168.124.5/16" } } ], "filters":[ { "name":"StripPrefix", "args":{ "_genkey_0":"1" } } ], "uri":"lb://idc-provider1", "order":0 }
查看redis存储,或者请求http://localhost:2000/actuator/gateway/routes ,都可以看到配置成功。
到此这篇关于SpringCloudGateway使用redis实现动态路由的文章就介绍到这了,更多相关SpringCloudGateway动态路由内容请搜索毛票票以前的文章或继续浏览下面的相关文章希望大家以后多多支持毛票票!