Spring Cloud Gateway

网关的作用

无网关会有哪些问题?

  1. 增加客户端请求的复杂度;
  2. 服务端鉴权复杂,每个服务都要鉴权,安全性低;
  3. 无法适配各种协议;

有网关

  • 针对所有请求进行统一鉴权、限流、熔断、日志
  • 协议转化。针对后端多种不同的协议,在网关层统一处理后以Http对外提供服务
  • 提供统一的错误码
  • 请求转发,并且可以基于网关实现内网和外网的隔离

灰度发布

在这里插入图片描述

网关之Zuul

在这里插入图片描述
Zuul是Netflix开源的微服务网关。它的核心由一系列过滤器组成,定义了4种标准类型的过滤器,这些会对应请求的整个生命周期。

Zuul1.x采用的是传统的thread per connection方式来处理请求,也就是针对每一个请求,会为这个请求专门分配一个线程来处理,知道这个请求完成以后才会释放线程,一旦后台服务器响应较慢,就会使得该线程被阻塞,所以它的性能不好。

网关之Gateway

Spring Cloud Gateway是Spring官网团队研发的API网关技术,它的目的是取代Zuul为微服务提供一个简单有效的API网关。

Zuul基于servlet, 需要依赖servlet容器,使用BIO模式,不支持如websocket之类的长链接;而Spring Cloud Gateway通过使用Netty + webflux,使用NIO模式。

作用

  1. 负载均衡
  2. 协议转换
  3. 安全(认证,黑/白名单)
  4. 日志记录
  5. 流量控制 & 熔断
  6. APIfacade
  7. 缓存
  8. 逻辑路由
    • 金丝雀部署
    • 蓝绿部署
    • A/B test

三个关键词

  1. (路由)Route,⽹关最基础的部分,也是⽹关⽐较基础的⼯作单元。路由由⼀个ID、⼀个⽬标URL(最终路由到的地址)、⼀系列的Predicate断⾔(匹配条件判断)和Filter过滤器(精细化控制)组成。如果断⾔为true,则匹配该路由。
    • 1个predicate决定当前route是否匹配
    • 1个uri决定要跳转的路径
    • n个filter
  2. (断⾔)Predicate,参考了Java8中的断⾔java.util.function.Predicate,开发⼈员可以匹配Http请求中的所有内容(包括请求头、请求参数等)(类似于nginx中的location匹配⼀样),如果断⾔与请求相匹配则路由。
  3. (过滤器)Filter,⼀个标准的Spring webFilter,使⽤过滤器,可以在请求之前或者之后执⾏业务逻辑。
    • 基于filter chain模式
    • 根据代码写法分pre & post 两种形式
    • 可以修改request & response

RoutePredicateFactory

在这里插入图片描述

RouteFilterFactory

在这里插入图片描述
Filter的类型:

  1. Pre类型过滤器;
  2. Post类型过滤器。

Filter实现方式:
3. GatewayFilter只会应用到单个路由或者一个分组路由上;
4. GlobalFilter会应用到所有的路由上。

Filter的顺序

在这里插入图片描述在这里插入图片描述

使用

  1. 引入jar包
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
  1. 定义路由规则
server:
  port: 7000

spring:
  application:
    name: GatewayDemo
  cloud:
    gateway:
#      这样写直接将 http:localhost:7000/eurekaProducer/foo 转发到 http:localhost:7000/foo,并实现负载均衡lb    
#      discovery:
#        locator:
#          enabled: true
#          lower-case-service-id: true
      routes:
        - id: lb_manual
          uri: lb://eurekaProducer
          predicates:
            - Path=/api/**
          filters:
            - StripPrefix=1
        ######################################
        - id: redirect
          uri: no://op
          predicates:
            - Path=/notallowed/**
          filters:
            - RedirectTo=302, https://www.baidu.com

eureka:
  instance:
    prefer-ip-address: true
    instance-id:  ${spring.application.name}:${spring.cloud.client.ip-address}:${server.port}
  client:
    service-url:
      defaultZone: http://server1:10010/eureka
    fetch-registry: true
    register-with-eureka: true

Redis实现限流

在Gateway中限流的实现基于内置的限流过滤器配置实现, RequestRateLimiter该过滤器会对访问到当前网关的所有请求执行限流过滤,如果被限流,默认情况下会响应HTTP 429-TooMany Requests。默认提供了RedisRateLimiter的限流实现,它采用令牌桶算法来实现限流功能。

使用

  1. 增加redis支持的jar包
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>
  1. 修改yaml文件
    在原来的基础上增加:
spring:
  redis:
    host: localhost
    port: 6379
    database: 0
  cloud:
    gateway:
      # 所有请求都要进行的filter
      default-filters:
        - name: RequestRateLimiter
          args:
            redis-rate-limiter.replenishRate: 1  # 令牌桶中令牌的填充速度,代表允许每秒执行的请求数。
            redis-rate-limiter.burstCapacity: 3  # 令牌桶的容量。表示每秒用户最大能够执行的请求数量。
            key-resolver: '#{@myKeyResolver}'    # 每次消耗多少token

自定义GlobalFilter

/**
 * 自定义GlobalFilter
 */
@Component
public class LoginFilter implements GlobalFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String token = exchange.getRequest().getHeaders().getFirst("Authorization");
        if (validateToken(token)) {
            return chain.filter(exchange);
        } else {
            setResponseStatus(exchange, HttpStatus.FOUND);

            final ServerHttpResponse response = exchange.getResponse();
            response.getHeaders().set(HttpHeaders.LOCATION, "http://www.baidu.com");
            return response.setComplete();
        }
    }

    private boolean validateToken(String token) {
        return !StringUtils.isEmpty(token) && token.startsWith("demo-");
    }

    @Override
    public int getOrder() {
        return 0;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

抽抽了

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值