6 网关 Spring Cloud Gateway

目录

1 简介

2 搭建网关

3 动态路由

4 路由前缀

5 过滤器

5.1 Gateway 自带的过滤器

​5.2 自定义全局过滤器


1 简介

  • 不管是来自客户端的请求,还是服务内部调用,一切对服务的请求都可经过网关。
  • 网关实现鉴权、动态路由等等操作。
  • Gateway是我们服务的统一入口。

Spring Cloud Gateway本身也是一个微服务,需要注册到Eureka,其功能特性如下:

  • 基于 Spring Framework 5,Project Reactor 和 Spring Boot 2.0
  • 动态路由
  • Predicates 和 Filters 作用于特定路由
  • 集成 Hystrix 断路器
  • 集成 Spring Cloud DiscoveryClient
  • 简单好用的 Predicates 和 Filters
  • 限流
  • 路径重写

 相关术语

  • Route(路由):这是网关的基本模块。它由一个 ID,一个目标 URI,一组断言和一组过滤器(可不写)定义。如果断言为真,则路由匹配。
  • Predicate(断言):这是一个 Java 8 的 Predicate。输入类型是一个 ServerWebExchange。我们可以使用它来匹配来自 HTTP 请求的任何内容,例如 headers 或参数。
  • Filter(过滤器):这是org.springframework.cloud.gateway.filter.GatewayFilter的实例,我们可以使用它修改请求和响应。

2 搭建网关

搭建网关微服务,实现服务路由分发
实现效果:当访问 http://访问网关的服务/user/findById?id=1时,网关路由至 http://127.0.0.1:9091/user/findById?id=1

步骤

  1. 创建SpringBoot工程gateway_server
  2. 勾选starter:网关、Eureka客户端
  3. 编写基础配置:端口,应用名称,注册中心地址
  4. 编写路由规则:唯一标识id,路由url地址,路由限定规则
  5. 启动网关服务进行测试

# 端口
server.port: 10010
# 应用名
spring.application.name: api-gateway
# 注册中心地址
eureka.client.service-url.defaultZone: http://127.0.0.1:10086/eureka

#配置路由转发规则
spring:
  cloud:
    gateway:
      #配置多个路由
      routes:
          #当前路由的唯一标识
        - id: user-service-route
          #转发到服务的地址
          uri: http://127.0.0.1:8080
          #断言:当前路由的转发规则(拦截规则)所有请求地址都会先经过路由,经过路由后判断请求地址是否符合断言的规则
          #把请求中上下文为带:http://127.0.0.1:10010/feign_consumer/** 的所有请求都拦截下来
          #并路由到:http://127.0.0.1:8080/feign_consumer/**
          predicates:
            - Path=/feign_consumer/**

测试:输入 http://localhost:10010/feign_consumer/2,用的是网关的port,但是实际访问的是服务的消费者 http://localhost:8080/feign_consumer/2(服务消费者再去调用生产者,当然也可以直接访问服务生产者)。此外注意:这里测试访问的是服务消费者,接下来涉及到动态路由,所以直接访问服务提供者。配置文件里面的断言也会修改,所以下里面的内容请注意!

3 动态路由

在刚才路由规则中,我们把路径对应服务地址写死了!如果服务提供者集群的话,这样做不合理。

正确的做法是:根据服务名称,从Eureka注册中心查找服务对应的所有实例列表,然后进行动态路由(利用Ribbon进行负载均衡访问 ),我们只需要写一些配置即可完成上述操作。如下:

# 端口
server.port: 10010
# 应用名
spring.application.name: api-gateway
# 注册中心地址
eureka.client.service-url.defaultZone: http://127.0.0.1:10086/eureka

#配置路由转发规则
spring:
  cloud:
    gateway:
      #全局过滤器
      default-filters:
        - AddResponseHeader=happy-a,happy
      #配置多个路由
      routes:
          #第1个路由:通过网关访问服务消费者,负载均衡是服务消费者客户端提供的功能
        - id: user-service-route
          #转发到服务的地址(地址被写死,没法集群访问)
          uri: http://127.0.0.1:8080
          #断言:当前路由的转发规则(拦截规则)所有请求地址都会先经过路由,经过路由后判断请求地址是否符合断言的规则
          #把请求中上下文为带:http://127.0.0.1:10010/feign_consumer/** 的所有请求都拦截下来
          #并路由到:http://127.0.0.1:8080/feign_consumer/**
          predicates:
            - Path=/feign_consumer/**
          #第2个路由:通过网关直接访问服务生产者集群(其实就是负载均衡)
        - id: user-service-route2
          #动态路由解决访问集群的问题:lb://服务名称
          uri: lb://user-service
          #所有请求都拦截,从而方便增加路由前缀
          predicates:
            - Path=/**
          #局部过滤器
          filters:
            #添加前缀
            #原始请求: http://127.0.0.1:10010/findById?id=1
            #实际访问: http://127.0.0.1:10010/user/findById?id=1
            #- PrefixPath=/user
            #去除前缀:数字是几就去除几个前缀,前缀写什么都无所谓
            #原始请求: http://127.0.0.1:10010/a/user/findById?id=1
            #实际访问: http://127.0.0.1:10010/user/findById?id=1
            - StripPrefix=1

4 路由前缀

在gateway中可以通过配置路由的过滤器PrefixPath 实现映射路径中的前缀添加,起到隐藏接口地址的作用,避免接口地址暴露。

注意:添加前缀和去除前缀只能二选一!

  • 添加前缀

原始请求: http://127.0.0.1:10010/findById?id=1
实际访问: http://127.0.0.1:10010/user/findById?id=1

  • 去除前缀

StripPrefix后面数字是几就去除几个前缀,前缀写什么都无所谓
原始请求: http://127.0.0.1:10010/a/user/findById?id=1
实际访问: http://127.0.0.1:10010/user/findById?id=1 (去除了1个前缀a)

5 过滤器

5.1 Gateway 自带的过滤器

过滤器是网关的重要功能,主要用于实现请求的鉴权,“路由前缀”功能也是使用过滤器实现的。过滤器的使用场景如下:

  • 请求鉴权:如果没有访问权限,直接进行拦截(主要场景)
  • 异常处理:记录异常日志
  • 服务调用时长统计

Gateway自带过滤器有几十个,常见的过滤器有:

参考链接:过滤器官网说明

过滤器名称说明
AddRequestHeader对匹配上的请求加上Header
AddRequestParameters对匹配上的请求增加请求参数
AddResponseHeader对从网关返回的响应添加Header
StripPrefix对匹配上的请求路径去除前缀
PrefixPath对匹配上的请求路径添加前缀

过滤器类型

  • 局部过滤器:只作用在当前配置的路由上。
  • 全局过滤器:作用在所有路由上。

全局过滤器配置

以 AddRequestParameters 过滤器为例,在请求响应头添加一个键值对:

局部过滤器

上面的例子中设置了路由前缀和后缀,用的就是局部过滤器



5.2 自定义全局过滤器

  • 在前面的学习中,使用的是自带的过滤器功能,如果涉及到和业务逻辑相关的开发,则需要自定义过滤器
  • 接下来,针对全局过滤器写一个简单的例子:如果请求参数中有token则允许访问,否则不允许访问,鉴权的过程在这里暂时忽略,只是去模拟过滤器的拦截效果。

自定义过滤器案例实现步骤:

  1. 新建filter包,实现GlobalFilter(过滤器功能)和 Ordered(指定过滤器功能的执行顺序)接口,创建全局过滤器类MyGlobalFilter
  2. 编写业务逻辑:重写filter方法,如果请求中有token参数,则认为请求有效,放行,否则不放行,注意:过滤器必须注入SpringIOC容器中
  3. 测试:http://localhost:10010/feign_consumer/2 访问不到,http://localhost:10010/feign_consumer/2?token=123 可以访
/**
 * 全局鉴权过滤器,必须注入到spring容器中才能生效
 */
@Component
public class MyGlobalFilter implements GlobalFilter, Ordered {
    //所有请求地址都会经过当前的过滤方法
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //拿到请求和响应对象
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();
        //从请求参数中获取token:由于请求参数中可能存在两个名字一样的参数,故只取参数中第一个叫“token”的
        String token = request.getQueryParams().getFirst("token");
        //如果存在token则放行,如果不存在则拦截,并提示用户未被授权(不判断token本身是否符合要求)
        if (null == token) {
            //拦截,提示用户未授权,返回错误状态码401(未授权),404(资源未找到),500(服务器错误)
            //实际情况直接返回到登陆页面
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            return response.setComplete();
        }
        //请求放行
        return chain.filter(exchange);
    }

    //返回值:当前自定义过滤器的执行顺序,返回值越小,越靠前执行
    @Override
    public int getOrder() {
        return 0;
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值