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();
    }
}
相关文章
SpringBoot使用ProxyServlet实现HTTP反向代理
SpringBoot使用ProxyServlet实现HTTP反向代理
1939 0
|
9月前
|
NoSQL Java Redis
springboot怎么使用Redisson
通过以上步骤,已经详细介绍了如何在Spring Boot项目中使用Redisson,包括添加依赖、配置Redisson、创建配置类以及使用Redisson实现分布式锁和分布式集合。Redisson提供了丰富的分布式数据结构和工具,可以帮助开发者更高效地实现分布式系统。通过合理使用这些工具,可以显著提高系统的性能和可靠性。
3165 34
|
8月前
|
消息中间件 运维 Java
搭建Zookeeper、Kafka集群
本文详细介绍了Zookeeper和Kafka集群的搭建过程,涵盖系统环境配置、IP设置、主机名设定、防火墙与Selinux关闭、JDK安装等基础步骤。随后深入讲解了Zookeeper集群的安装与配置,包括数据目录创建、节点信息设置、SASL认证配置及服务启动管理。接着描述了Kafka集群的安装,涉及配置文件修改、安全认证设置、生产消费认证以及服务启停操作。最后通过创建Topic、发送与查看消息等测试验证集群功能。全网可搜《小陈运维》获取更多信息。
741 1
|
9月前
|
NoSQL Java API
微服务——SpringBoot使用归纳——Spring Boot 中集成Redis——Spring Boot 集成 Redis
本文介绍了在Spring Boot中集成Redis的方法,包括依赖导入、Redis配置及常用API的使用。通过导入`spring-boot-starter-data-redis`依赖和配置`application.yml`文件,可轻松实现Redis集成。文中详细讲解了StringRedisTemplate的使用,适用于字符串操作,并结合FastJSON将实体类转换为JSON存储。还展示了Redis的string、hash和list类型的操作示例。最后总结了Redis在缓存和高并发场景中的应用价值,并提供课程源代码下载链接。
2128 0
|
10月前
|
前端开发 Java Nacos
🛡️Spring Boot 3 整合 Spring Cloud Gateway 工程实践
本文介绍了如何使用Spring Cloud Alibaba 2023.0.0.0技术栈构建微服务网关,以应对微服务架构中流量治理与安全管控的复杂性。通过一个包含鉴权服务、文件服务和主服务的项目,详细讲解了网关的整合与功能开发。首先,通过统一路由配置,将所有请求集中到网关进行管理;其次,实现了限流防刷功能,防止恶意刷接口;最后,添加了登录鉴权机制,确保用户身份验证。整个过程结合Nacos注册中心,确保服务注册与配置管理的高效性。通过这些实践,帮助开发者更好地理解和应用微服务网关。
1832 0
🛡️Spring Boot 3 整合 Spring Cloud Gateway 工程实践
|
Java Spring
SpringBoot: 启动Banner在线生成工具
SpringBoot: 启动Banner在线生成工具
36743 1
SpringBoot: 启动Banner在线生成工具
|
消息中间件 存储 网络协议
RabbitMQ的使用
这篇文章详细介绍了RabbitMQ的消息中间件概念、核心组件、通过Docker的安装方法和基本使用步骤,并展示了如何在Spring Boot中整合RabbitMQ,包括依赖配置、消息的发送和接收示例。
RabbitMQ的使用
|
数据可视化 JavaScript
Vue3项目使用G6可视化组件实现一个树形机构图
在Vue 3项目中使用G6可视化组件库实现树形机构图的构建和展示。
3138 1
Vue3项目使用G6可视化组件实现一个树形机构图