Spring Cloud Gateway(一)

Spring Cloud Gateway(一)

Gateway简介

  1. Spring Cloud Gateway用于在Spring WebFlux或Spring WebMVC之上构建API网关。Spring Cloud Gateway旨在提供一种简单而有效的方式来提供统一的路由访问方式,并为它们提供横切关注点,例如:安全、监控、指标和限流等,基于Netty的响应式开发模式。
  2. Gateway的特点
  • 基于Spring和Spring Boot构建;
  • 能够匹配任何请求属性的路由;
  • 断言和过滤器是特定于路由的,重写断言和过滤器很方便;
  • 集成了断路器和Spring Cloud DiscoveryClient;
  • 限制请求速率;
  • 重写路径。
  1. 核心概念
  • 路由(route):路由是网关最基础部分,路由信息由一个ID、一个目的URL、一组断言工厂和一组过滤器组成。如果断言为真,则说明请求URL和配置的路由匹配。

  • 断言(predicate):Gateway中的断言函数输入类型是ServerWebExchange,允许开发者自定义匹配来自Http请求中的任何信息,比如请求头和参数。

  • 过滤器(Filter):一个标准的web过滤器,Gateway中的过滤器分为GatewayFilter和GlobalFilter,过滤器可以对请求和响应进行处理。

路由配置

  1. 创建示例工程api_gateway_server
  • 创建工程导入坐标
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.jzy</groupId>
    <artifactId>api_gateway_server</artifactId>
    <version>1.0-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.6.RELEASE</version>
    </parent>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Greenwich.SR2</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
    </dependencies>

</project>
  • 配置启动类
package org.jzy.gateway;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class GatewayServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(GatewayServerApplication.class, args);
    }
}
  • 编写配置文件
# application.yml
server:
  port: 8090

spring:
  application:
    name: api-gateway-server
  cloud:
    gateway:
      routes: # 配置路由:路由id,路由到微服务的uri,断言
      - id:  product-service
        uri: http://localhost:9001
        predicates: # 路由条件
        - Path=/product/**
        filters: # 路由过滤器
        - RewritePath=/product-service/(?<segment>.*),/$\(segment)
	  discovery:
	    locator: 
	      enabled: true # 开启根据微服务名称自动转发
	      lower-case-service-id: true # 微服务名称小写
  1. RoutePredicateFactory接口实现类实现了多种类型的断言。
请求时间校验条件断言
请求时间满足在配置时间之后
请求时间满足在配置时间之前
请求时间满足在配置时间之间
请求Cookie校验条件断言
请求Header校验条件断言
请求Host校验条件断言
请求Method校验条件断言
请求Path校验条件断言
请求查询参数校验条件断言
请求远程地址校验条件断言
请求指定Cookie正则匹配指定值
请求指定Header正则匹配指定值
请求Headers是否包含指定的名称
请求Host是否匹配指定的值
请求Method匹配配置的方法
请求路径正则匹配指定值
请求查询参数正则匹配指定值
请求远程地址匹配指定值
RoutePredicateFactory
datetime
AfterRoutePredicateFactory
BeforeRoutePredicateFactory
BetweenRoutePredicateFactory
Cookie
Header
Host
Method
Path
Queryparam
RemoteAddr
CookieRoutePredicateFactory
HeaderRoutePredicateFactory
CloudFoundryRouteServiceRoutePredicateFactory
HostRoutePredicateFactory
MethodRoutePredicateFactory
PathRoutePredicateFactory
QueryRoutePredicateFactory
RemoteAddrRoutePredicateFactory
# 路由断言之后的匹配
spring:
  cloud:
    gateway:
      routes: 
      - id:  after_route
        uri: http://localhost:9001
        predicates:
        - After=xxx
# 路由断言之前的匹配
spring:
  cloud:
    gateway:
      routes: 
      - id:  before_route
        uri: http://localhost:9001
        predicates:
        - Before=xxx
# 路由断言Header匹配,比如名称匹配X-Request-Id并且表达式匹配\d+
spring:
  cloud:
    gateway:
      routes: 
      - id:  header_route
        uri: http://localhost:9001
        predicates:
        - Header=X-Request-id, \d+      
# 路由断言Host匹配
spring:
  cloud:
    gateway:
      routes: 
      - id:  host_route
        uri: http://localhost:9001
        predicates:
        - Host=**.org,**.com
# 路由断言可变参数匹配
spring:
  cloud:
    gateway:
      routes: 
      - id:  host_route
        uri: http://localhost:9001
        predicates:
        - Path=/foo/{segment},/bar/{segment}
# 路由断言查询参数匹配
spring:
  cloud:
    gateway:
      routes: 
      - id:  query_route
        uri: http://localhost:9001
        predicates:
        - Query=baz
  1. 动态路由,也就是面向微服务的路由服务,设置uri从注册中心获取。

过滤器

  1. Gateway的Filter只有pre和post。pre这种过滤器在请求被路由之前调用,可以用来实现身份验证、记录日志信息等。post这种过滤器在路由到微服务以后执行,这种过滤器可以用来响应添加标准的HTTP Header、收集统计信息和指标、把响应从微服务发送给客户端等。

  2. GatewayFilter应用到单个路由或一个分组的路由,而GlobalFilter应用到所有的路由。

  3. 局部过滤器GatewayFilter是针对单个路由的过滤器,可以对访问的URL过滤,进行切面处理。Gateway中内置了很多不同类型的局部过滤器,比如RewritePathGatewayFilterFactory类可以重写原始的请求路径。

  4. 全局过滤器GlobalFilter作用于所有的路由,Gateway定义了GlobalFilter接口,用户可以自定义。通过全局过滤器可以实现统一鉴权,安全性验证等功能,并且全局过滤器也是使用最多的过滤器。

  5. 自定义全局过滤器示例

package org.jzy.gateway.filter;

import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

@Component
public class MyFilter implements GlobalFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //执行过滤器中的业务逻辑
        System.out.println("执行自定义全局过滤器");
        //继续往后执行
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        //指定过滤器的执行顺序,返回值越小,执行优先级越高
        return 0;
    }
}

统一鉴权

  1. 鉴权逻辑是当客户端第一次请求服务时,服务端对用户进行信息认证。当认证通过后把用户信息进行加密形成token,返回客户端。以后每次请求,客户端都携带认证的token,服务端对token进行解密,判断token是否过期。
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

@Component
public class AuthenticationFilter implements GlobalFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //请求参数没有携带access-token则认证失败,结束请求
        String token = exchange.getRequest().getQueryParams().getFirst("access-token");
        if (token == null) {
            System.out.println("登录失败");
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            return exchange.getResponse().setComplete();
        }
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return 0;
    }
}

网关限流

一、常见的限流算法

  1. 计数器限流算法(固定窗口限流算法)是最简单的限流实现算法,本质是通过维护一个单位时间的计数器,每次请求计数器加1,当单位时间计数器累加到大于设定的阈值,则以后的请求都被拒绝,直到单位时间已经过去,再将计数器重置为零。

  2. 滑动窗口限流算法是对计数器限流算法的改进,把时间窗口分为多个小周期,每个小周期有自己的计数器。随着时间的滑动,过小的小周期数据被删除,从而更精确地控制流量。比如每分钟处理60个请求,可以把1分钟分为60个窗口,每个窗口一秒只能处理不大于60个请求的数量。滑动窗口算法能够更加平滑地处理流量,减少计数器算法的突增问题。

  3. 漏桶限流算法的原理是控制数据注入网络的速度,平滑网络上的突发流量。它像一个漏桶一样以一定的速度处理进入的请求,超过漏桶容量的请求被拒绝或等待。这种算法适用于需要控制整体流量速率的情况。

  4. 令牌桶限制算法是比较常见的限流算法,基于令牌桶的概念,所有的请求在处理前都需要拿到一个可用的令牌才会被处理。令牌以一定的速率被添加到桶中,当桶满时,新添加的令牌被丢弃或拒绝。请求到达后首先获取令牌桶中的令牌,处理完业务逻辑后,令牌被删除。令牌桶有最低限额,当桶中的令牌达到最低限额时,请求处理完之后将不会删除令牌,以此保证足够的限流。

二、基于Filter的限流

  1. Gateway官方提供了令牌桶的限流支持,基于内置的过滤器工厂实现。在过滤器工厂中是通过Redis和Lua脚本结合的方式进行流量控制。

  2. 使用Filter限流

  • 引入Redis依赖
<!-- redis依赖 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>
<!-- 监控依赖 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
  • 添加配置
spring:
  redis:
    host: localhost
    port: 6379
    database: 0
  cloud:
    gateway:
      routes: # 配置路由:路由id,路由到微服务的uri,断言
      - id:  product-service
        uri: http://localhost:9001
        predicates:
        - Path=/product/**
        filters:
        - name: RequestRateLimiter
          args:
            # 使用SpEL表达式从上下文中获取
            key-resolver: '#{@pathKeyResolver}'
            # 令牌桶每秒填充平均速率
            redis-rate-limiter.replenishRate: 1
            # 令牌桶的上限
            redis-rate-limiter.burstCapacity: 3 
  • 配置redis中key的解析器
package org.jzy.gateway.configuration;

import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

@Configuration
public class KeyResolverConfiguration {
    
    @Bean
    public KeyResolver pathKeyResolver() {
        return new KeyResolver() {
            @Override
            public Mono<String> resolve(ServerWebExchange exchange) {
                return Mono.just(exchange.getRequest().getPath().toString());
            }
        };
    }
    
}
@Configuration
public class KeyResolverConfiguration {

    @Bean
    public KeyResolver pathKeyResolver() {
        //基于请求路径限流
        return exchange -> Mono.just(exchange.getRequest().getPath().toString());
    }

    @Bean
    public KeyResolver userKeyResolver() {
        //基于请求参数的限流
        return exchange -> Mono.just(exchange.getRequest()
                                     .getQueryParams().getFirst("userId"));
    }
}

三、基于Sentinel限流

  1. Sentinel支持对Gateway、Zuul等主流的API网关进行限流。
  • 24
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Spring Cloud是一个用于构建分布式系统的开发工具集合。它提供了一些常用的组件和框架,包括服务注册和发现、负载均衡、断路器、分布式配置等等。在使用Spring Cloud时,有一些常见的错误和注意事项需要注意。 首先,关于Spring BootSpring Cloud版本对应错误。在使用Spring Cloud时,需要确保Spring BootSpring Cloud的版本兼容。不同版本之间可能存在依赖冲突或不兼容的情况,因此需要根据官方文档或者相关文档来选择合适的版本。 另外,Spring Cloud Config是一个用于集中管理和动态获取配置的工具。它支持从Git、SVN或本地文件系统中获取配置文件,并提供了服务器和客户端支持。你可以通过官方使用说明文档了解更多关于Spring Cloud Config的详细信息。 此外,关于选择使用Nacos还是Eureka作为服务注册和发现组件的问题。Nacos是一个功能更强大的服务注册和发现组件,它整合了Spring Cloud Eureka、Spring Cloud Config和Spring Cloud Bus的功能。使用Nacos可以实现配置的中心动态刷新,而不需要为配置中心新增集群或使用消息队列。另一方面,Eureka是Spring Cloud原生全家桶的一部分,相对来说更加稳定一些。选择使用哪个组件需要根据具体的需求和项目特点来决定。 综上所述,Spring Cloud是一个用于构建分布式系统的开发工具集合,它提供了一些常用的组件和框架。在使用Spring Cloud时,需要注意Spring BootSpring Cloud版本的兼容性,并可以使用Spring Cloud Config来动态获取配置。同时,可以选择使用Nacos或Eureka作为服务注册和发现组件,具体选择需要根据项目需求来决定。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

快乐江小鱼

知识创造财富,余额还是小数

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

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

打赏作者

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

抵扣说明:

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

余额充值