SpringCloud Gateway使用redis实现动态路由的方法

1. 将 actuator 端点暴露出来

management:

endpoints:

web:

exposure:

include: "*"

2. redis 配置

https://www.jb51.net/article/203766.htm

3. 将原内存路由持久化到 redis

@Component

public class RedisRouteDefinitionRepository implements RouteDefinitionRepository {

/**

* hash存储的key

*/

public static final String GATEWAY_ROUTES = "gateway_dynamic_route";

@Resource

private StringRedisTemplate redisTemplate;

/**

* 获取路由信息

* @return

*/

@Override

public Flux<RouteDefinition> getRouteDefinitions() {

List<RouteDefinition> routeDefinitions = new ArrayList<>();

redisTemplate.opsForHash().values(GATEWAY_ROUTES).stream()

.forEach(routeDefinition -> routeDefinitions.add(JSON.parseObject(routeDefinition.toString(), RouteDefinition.class)));

return Flux.fromIterable(routeDefinitions);

}

@Override

public Mono<Void> save(Mono<RouteDefinition> route) {

return route.flatMap(routeDefinition -> {

redisTemplate.opsForHash().put(GATEWAY_ROUTES, routeDefinition.getId(), JSONObject.toJSONString(routeDefinition));

return Mono.empty();

});

}

@Override

public Mono<Void> delete(Mono<String> routeId) {

return routeId.flatMap(id -> {

if (redisTemplate.opsForHash().hasKey(GATEWAY_ROUTES, id)) {

redisTemplate.opsForHash().delete(GATEWAY_ROUTES, id);

return Mono.empty();

}

return Mono.defer(() -> Mono.error(new NotFoundException("route definition is not found, routeId:" + routeId)));

});

}

}

4. 重写动态路由服务

@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;

}

}

5. 对外暴露接口

@RestController

@RequestMapping("/gateway")

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);

}

}

测试

测试前删除我们配置的静态路由,因为静态路由和 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/(?<remaining>.*)",

"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/(?<remaining>.*)",

"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/(?<remaining>.*)",

"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/(?<remaining>.*)",

"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  , 都可以看到配置成功。

到此这篇关于SpringCloud Gateway使用redis实现动态路由的文章就介绍到这了,更多相关SpringCloud Gateway动态路由内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • SpringCloud Gateway跨域配置代码实例

    这篇文章主要介绍了SpringCloud Gateway跨域配置代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 Springboot版本:2.1.8.RELEASE SpringCloud版本:Greenwich.SR2 yml配置: spring: cloud: gateway: globalcors: cors-configurations: '[/**]': # 允许携带认证信息 # 允许跨域的源(网站域名/ip),设置*为全部

  • 详解SpringCloud Finchley Gateway 统一异常处理

    SpringCloud Finchley Gateway 统一异常处理 全文搜索[@@]搜索重点内容标记 1 . 问题:使用SpringCloud Gateway时,会出现各种系统级异常,默认返回HTML. 2 . Finchley版本的Gateway,使用WebFlux形式作为底层框架,而不是Servlet容器,所以常规的异常处理无法使用 翻阅源码,默认是使用DefaultErrorWebExceptionHandler这个类实现结构如下: 可以实现参考DefaultErrorWebExcep

  • SpringCloud Finchley Gateway 缓存请求Body和Form表单的实现

    在接入Spring-Cloud-Gateway时,可能有需求进行缓存Json-Body数据或者Form-Urlencoded数据的情况. 由于Spring-Cloud-Gateway是以WebFlux为基础的响应式架构设计,所以在原有Zuul基础上迁移过来的过程中,传统的编程思路,并不适合于Reactor Stream的开发. 网络上有许多缓存案例,但是在测试过程中出现各种Bug问题,在缓存Body时,需要考虑整体的响应式操作,才能更合理的缓存数据 下面提供缓存Json-Body数据或者Form

  • 详解SpringCloudGateway内存泄漏问题

    SpringCloudGateway内存泄漏问题 项目完善差不多,在进入压力测试阶段期间,发现了gateway有内存泄漏问题,问题发现的起因是,当时启动一台gateway,一台对应的下游应用服务,在压力测试期间,发现特别不稳定,并发量时高时低,而且会有施压机卡住的现象,然后找到容器对应的宿主机,并使用container stats命令观察内存,经过观察发现,压力测试时内存会暴涨,并由于超过限制最大内存导致容器挂掉(这里由于用的swarm所以会自动选择节点重启)最终发现由于之前测试服务器配置低,所

  • springboot2.0和springcloud Finchley版项目搭建(包含eureka,gateWay,Freign,Hystrix)

    前段时间spring boot 2.0发布了,与之对应的spring cloud Finchley版本也随之而来了,两者之间的关系和版本对应详见我这边文章:spring boot和spring cloud对应的版本关系 项目地址:spring-cloud-demo spring boot 1.x和spring cloud Dalston和Edgware版本搭建的微服务项目现在已经很流行了,现在很多企业都已经在用了,这里就不多说了. 使用版本说明: spring boot 2.0.x spring

  • 详解SpringCloud Gateway之过滤器GatewayFilter

    在Spring-Cloud-Gateway之请求处理流程文中我们了解最终网关是将请求交给过滤器链表进行处理,接下来我们阅读Spring-Cloud-Gateway的整个过滤器类结构以及主要功能 通过源码可以看到Spring-Cloud-Gateway的filter包中吉接口有如下三个,GatewayFilter,GlobalFilter,GatewayFilterChain,下来我依次阅读接口的主要实现功能. GatewayFilterChain 类图 代码 /** * 网关过滤链表接口 * 用

  • SpringCloud Gateway使用redis实现动态路由的方法

    1. 将 actuator 端点暴露出来 management: endpoints: web: exposure: include: "*" 2. redis 配置 https://www.jb51.net/article/203766.htm 3. 将原内存路由持久化到 redis @Component public class RedisRouteDefinitionRepository implements RouteDefinitionRepository { /** * h

  • SpringCloud Gateway 利用 Mysql 实现动态路由的方法

    需求描述 标准网关动态路由功能是重要的一环,将路由.断言以及过滤器信息,持久化到 Mysql 中,通过配置后台页面实现路由.断言.以及过滤器等配置的增删改查. Spring Cloud Gateway 路由及黑白名单实现背景 Spring Cloud 路由API Spring Cloud Gateway 通过定义 RouteDefinitionRepository 来实现动态路由. //保存路由缓存 public interface RouteDefinitionWriter { Mono<Vo

  • 基于Nacos实现Spring Cloud Gateway实现动态路由的方法

    简介 该文档主要介绍以Nacos为配置中心,实现Spring Cloud GateWay 实现动态路由的功能.Spring Cloud Gateway启动时候,就将路由配置和规则加载到内存里,无法做到不重启网关就可以动态的对应路由的配置和规则进行增加,修改和删除.通过nacos的配置下发的功能可以实现在不重启网关的情况下,实现动态路由. 集成 Spring Cloud GateWay集成 spring-cloud-starter-gateway:路由转发.请求过滤(权限校验.限流以及监控等) s

  • vue 实现动态路由的方法

    很多时候我们在项目的路由都是在前端配置好的 但是有的时候为了进行全面的权限控制,会需要后台给出路由表,前端再渲染.不用在前端配置. 下面主要讲一下思路 1.和后台小哥哥沟通好数据,把我们前端配置的路由表数据给他,他就能看懂了 2.拿到数据需要我们自己再处理 路由中的component后台是给不了的,这里我们只需要后台小哥哥按照我们提供的前端component路径给数据,我们循环加载就可以了 //view就是后台给的数据 return () => import(`@/view/modules/${

  • spring-cloud-gateway动态路由的实现方法

    概述 线上项目发布一般有以下几种方案: 机发布 蓝绿部署 滚动部署 灰度发布 停机发布 这种发布一般在夜里或者进行大版本升级的时候发布,因为需要停机,所以现在大家都在研究 Devops 方案. 蓝绿部署 需要准备两个相同的环境.一个环境新版本,一个环境旧版本,通过负载均衡进行切换与回滚,目的是为了减少服务停止时间. 滚动部署 就是在升级过程中,并不一下子启动所有新版本,是先启动一台新版本,再停止一台老版本,然后再启动一台新版本,再停止一台老版本,直到升级完成.基于 k8s 的升级方案默认就是滚动

  • Nginx gateway集群和动态网关的实现思路

    目录 基于nginx部署gateway集群 动态Gateway 使用数据库实现动态路由 网关是系统的唯一对外的入口,介于客户端和服务器端之间的中间层,处理非业务功能,提供路由请求.鉴权.监控.缓存.限流等功能.无论你查看任何一个微服务项目架构,你都会发现在客户端和服务器端之间有一个网关,移动端的任何请求都必须经过网关才能到达服务端. 网关怎么实现集群:使用nginx实现. 基于nginx部署gateway集群 1.将网关项目多个部署启动例如:网关1 127.0.0.1:81网关1 127.0.0

  • vue iview实现动态路由和权限验证功能

    github上关于vue动态添加路由的例子很多,本项目参考了部分项目后,在iview框架基础上完成了动态路由的动态添加和菜单刷新.为了帮助其他需要的朋友,现分享出实现逻辑,欢迎一起交流学习. Github地址 iview-dynamicRouter 实现目标 客户端从服务端拿到路由和权限数据后,刷新项目的路由和菜单列表,并进行权限控制. 项目基础 基础框架: iview组件库官方模板项目 iview-admin 的template分支项目,此项目为 iview-admin 的基础框架代码.项目地

  • SpringCloud Gateway动态路由配置详解

    目录 路由 动态 路由模型实体类 动态路径配置 路由模型JSON数据 路由 gateway最主要的作用是,提供统一的入口,路由,鉴权,限流,熔断:这里的路由就是请求的转发,根据设定好的某些条件,比如断言,进行转发. 动态 动态的目的是让程序更加可以在运行的过程中兼容更多的业务场景. 涉及到两个服务,一个是门户服务(作用是提供给运营人员管理入口--包括:管理路由.绑定路由),一个是网关服务(gateway组件,为门户服务提供:查询路由信息.添加路由.删除路由.编辑路由接口). 路由模型实体类 /*

  • Spring Cloud Gateway + Nacos 实现动态路由

    本节开始介绍 SpringCloud Gateway 中动态路由的实现方法,包括: Nacos 集成动态路由配置,更新配置文件即自动更新路由 MySQL + 二级缓存实现,主要基于 Gateway 的一些特性进行重写,实现路由信息的自动更新 这篇文章主要介绍第一种方式:将配置文件放到 Nacos 进行托管,网关服务通过引入 Nacos 而自动更新路由配置信息.实现较为简单. 本节代码在:https://github.com/laolunsi/spring-boot-examples,参考例 23

  • springcloud Zuul动态路由的实现

    前言 Zuul 是Netflix 提供的一个开源组件,致力于在云平台上提供动态路由,监控,弹性,安全等边缘服务的框架.也有很多公司使用它来作为网关的重要组成部分,碰巧今年公司的架构组决定自研一个网关产品,集动态路由,动态权限,限流配额等功能为一体,为其他部门的项目提供统一的外网调用管理,最终形成产品(这方面阿里其实已经有成熟的网关产品了,但是不太适用于个性化的配置,也没有集成权限和限流降级). 不过这里并不想介绍整个网关的架构,而是想着重于讨论其中的一个关键点,并且也是经常在交流群中听人说起的:

随机推荐