【Spring Cloud Gateway】学习笔记

17 篇文章 1 订阅
9 篇文章 0 订阅

一、简介

Zuul 2.x版本一直跳票,2019年5月,Netflix终于开源了支持异步调用模式的zuul 2.0版本,真可谓千呼万唤始出来。但是Spring Cloud已经不再集成Zuul2.x了,那么是时候了解—下Spring Cloud Gateway了.

Spring Cloud Gateway是基于Spring生态系统之上构建的API网关,包括: Spring 5,Spring Boot2和Project Reactor。SpringCloud Gateway旨在提供—种简单而有效的方法来路由到API,并为它们提供跨领域的关注点,例如:安全性,监视/指标,限流等。由于Spring 5.0支持 Netty,Http2,而 Spring Boot2.0支持Spring 5.0,因此Spring Cloud Gateway支持Netty和Http2顺理成章。

网关应当具备以下功能:

  • 性能:API高可用,负载均衡,容错机制。
  • 安全:权限身份认证、脱敏,流量清洗,后端签名(保证全链路可信调用),黑名单(非法调用的限制)。
  • 日志:日志记录,—旦涉及分布式,全链路跟踪必不可少。
  • 缓存:数据缓存。
  • 监控:记录请求响应数据,API耗时分析,性能监控。
  • 限流:流量控制,错峰流控,可以定义多种限流规则。
  • 灰度:线上灰度部署,可以减小风险。
  • 路由:动态路由规则。

二、核心概念

路由(Route) ∶路由是网关最基础的部分,路由信息由ID、目标URI、一组断言和一组过滤器组成。如果断言路由为真,则说明请求的URI和配置匹配。
断言(Predicate) : Java8中的断言函数。Spring Cloud Gateway 中的断言函数输入类型是Spring 5.0框架中的ServerWebExchange。Spring Cloud Gateway中的断言函数允许开发者去定义匹配来自于Http Request 中的任何信息,比如请求头和参数等。
过滤器(Filter):一个标准的Spring Web Filter。Spring Cloud Gateway中的Filter分为两种类型,分别是Gateway Filter和Global Filter。过滤器将会对请求和响应进行处理。

三、代码案例

3.1 pom依赖

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

3.2、配置项

 spring:
  application :
    name: gateway-server
  cloud:
    gateway: #路由规则
      routes:
        - id: gateway #路由ID,唯一
          uri: lb:CONSUMER #目标URI,路由到微服务的地址
          predicates: #断言(判断条件)
            - Path=/consumer/** #四且改对应URL的请求,将匹配至的请求追加在目标URI
eureka:
  client:
    service-url:
      defaultZone: http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/,http://eureka7001.com:7001/eureka/

3.3 启动项

启动项无需配置其他的注解

四、路由规则

4.1、path

spring:
  application :
    name : gateway-server #应用名称
  cloud :
	  gateway : #路由规则
	    routes :
	      - id : product-service #路由ID,唯一
	        uri: http://localhost:7878/ #目标URI,路由到到微服务的地址
	        predicates: #断言(判断条件)
	          - Path=/product/** #匹配对应URL的请求,将匹配到的请求追加在目标URI之后
  • 请求http://localhost:9999/product/1将会路由至http://localhost:7878/product/1

4.2、Query

spring:
  application:
    name : gateway-server #应用名称cloud :
  gateway : #路由规则routes:
    - id : product-service #路由ID,唯一
      uri: http://localhost:7078/ #目标URI,路由到到微服务的地址
      predicates : #断言(判断条件)
  #-Query=token #匹配请求参教中包含token的请求
    - Query=token,abc. #匹配请求参数中包含token并且其参数值满足正则表达式abc.的请求
  • Query=token : 比如,http://localhost:9000/product/1?token=123
  • Query=token,abc. :比如,http://localhost:9000/product/1?token=abc1

4.3、Method

spring:
  application :
    name : gateway-server #应用名称cloud :
  gateway : #路由规则routes:
    - id : product-service #路由ID,唯一
      uri: http://localhost:7070/ #目标URI,路由到微服务的地址
      predicates : #断言(判断条件)
        - Method=GET #匹配任意GET请求

4.4、Datetime

spring:
  application :
    name : gateway-server #应用名称cloud :
  gateway : #路由规则routes :
    - id : product-service  #路由ID,唯一
    uri: http://localhost:7870/ #目标URI,路由到微服务的地址
    predicates : #断言(判断条件)
      #匹配中国上海时间2820-82-0220:20:28之后的请求
      - After=2828-82-82T28:20:20.888+88:88[ Asia/Shanghai]

4.5、RemoteAddr

spring:
  application :
    name : gateway-server #应用名称cloud :
  gateway : #路由规则routes :
    - id : product-service #路由ID,唯一
    uri : http://localhost:7078/ #目标URI,路由到微服务的地址
    predicates: #断言《判断条件)
      - RemoteAddr=192.168.10.1/0 #匹配远程地址请求是RemoteAddr 的请求,0表示子网掩码

4.6、Header

spring:
  application :
    name : gateway-server #应用名称cloud :
  gateway : #路由规则routes :
    - id : product-service #路由ID,唯一
    uri : http://localhost:7078/ #目标URI,路由到微服务的地址
    predicates: #断言《判断条件)
     #匹配请求头包含X-Request-Id并且其值匹配正则表达式\d+的请求
     - Header=X-Request-Id, \d+

五、动态路由

5.1、添加依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

5.2、配置项

增加eureka配置项即可

eureka:
  client:
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/

5.3、通过注册中心获取路由

将uri改成uri: lb://CONSUMER/ # lb://服务名

5.4、通过服务名称转发

cloud :
	gateway :
		discovery :
			locator :
				#是否与服务发现组件进行结合,通过serviceId 转发到具体服务实例。
				enabled: true	#是否开启基于服务发现的路由规则
				lower-case-service-id: true #是否将服务名称转小写

六、过滤器

Spring Cloud Gateway根据作用范围划分为GatewayFilterGlobalFilter,二者区别如下:

GatewayFilter:网关过滤器,需要通过spring.cloud.routes.filters配置在具体路由下,只作用在当前路由上或通过spring.cloud .default-filters配置在全局,作用在所有路由上。
GlobalFilter:全局过滤器,不需要在配置文件中配置,作用在所有的路由上,最终通过GatewayFilterAdapter包装成GatewayFilterChain可识别的过滤器,它为请求业务以及路由的URI转换为真实业务服务请求地址的核心过滤器,不需要配置系统初始化时加载,并作用在每个路由上。

6.1、GatewayFilter

6.1.1、path过滤器

6.1.1.1、RewritePathGatewayFilterFactory(重写请求路径)

RewritePath网关过滤器工厂采用路径正则表达式参数和替换参数,使用Java正则表达式来灵活地重写。

filters:	#网关过滤器
	#将/api-gateway/product/1重写为/product/1
	- RewritePath=/api-gateway(?<segment>/?.*),$\{segment}
6.1.1.2、PrefixPathGatewayFilterFactory(请求路径添加指定前缀)

PrefixPath 网关过滤器工厂为匹配的URI。

filters:	#网关过滤器
	#将/1重写为/product/1
	- PrefixPath=/product
6.1.1.3、StripPrefixGatewayFilterFactory(剥离路径个数)

StripPrefix网关过滤器工厂采用一个参数 StripPrefix,该参数表示在将请求发送到下游之前从请求中剥离的路径个数。

filters:	#网关过滤器
	#将/api/123/product/1重写为/product/1
	- StripPrefix=2
6.1.1.4、SetPathGatewayFilterFactory(模板化路径段)

SetPath网关过滤器工厂采用路径模板参数。它提供了一种通过允许模板化路径段来操作请求路径的简单方法,使用了SpringFramework中的uri模板,允许多个匹配段。

predicates:	#断言(判断条件)
	#匹配对应URI的请求,将匹配到的请求追加在目标URI之后
	- Path=/api/product/{sagment}
filters:	#网关过滤器
	#将/api/product/1重写为/product/1
	- SetPath=/product/{segment}

6.1.2、Parameter参数过滤器

AddRequestParameter网关过滤器工厂会将指定参数添加至匹配到的下游请求中。

predicates:	#断言(判断条件)
	#匹配对应UR工的请求,将匹配到的请求追加在目标URI之后
	- Path=/api-gateway/**
filters:	#网关过滤器
	#将/api-gateway/producet/1重写为/product/1
	- RewritePath=/api-gateway(?<segment>/?.*),$\{segment}
	#在下游请求中添加flag=1
	- AddRequestParameter=flag,1

6.1.3、Status状态过滤器

Setstatus网关过滤器工厂采用单个状态参数,它必须是有效的 Spring HttpStatus。它可以是整数404或枚举NOT_FOUND的字符串表示。

filters :	#网关过滤器
	#任何情况下,响应的HTTP状态都将设置为404
	- SetStatus=404
	#404或者对应的校举NOT_FOUND

6.2、GlobalFilter

全局过滤器不需要在配置文件中配置,作用在所有的路由上,最终通过GatewayFilterAdapter包装成GatewayFilterChain可识别的过滤器,它是请求业务以及路由的URI转换为真实业务服务请求地址的核心过滤器,不需要配置系统初始化时加载,并作用在每个路由上。
在这里插入图片描述

6.3、自定义过滤器

即使Spring Cloud Gateway自带许多实用的GatewayFilter Factory、 Gateway Filter、Global Filter,但是在很多情景下我们仍然希望可以自定义自己的过滤器,实现一些操作。

6.3.1、网关过滤器

自定义网关过滤器需要实现以下两个接口:GatewayFilter , Ordered .

6.3.1.1、定义网关过滤器

CustomGatewayFilter.java

public class CustomGatewayFilter implements GatewayFilterOrdered {
	/*
	*过滤器业务逻辑
	* param exchange
	* param chain
	* @return
	*/
	@override
	public Mono<Void> filter(ServerWebExchange exchange,GatewayFilterChain chain) {
		System.out.println("自定义网关过滤器被执行");
		return chain.filter (exchange); //继续向下执行
	}
	/**
	*过滤器执行顺序,数值越小,优先级越高*
	* @return
	*/
	@Override
	public int getOrder(){
		return 0;
	}
}
6.3.1.2、注册过滤器
@Configuration
public class GatewayRoutesConfiguration{
	@Bean
	public RouteLocator routeLocator(RouteLocatorBuilder builder) {
		return builder.routes().route(r -> r
			//断言(判断条件)
			.path("/product/**") 
			//目标URI,路由到微服务的地址
			.uri("lb://product-service" ) 
			//注册自定义网关过滤器
			.filters(new CustomGatewayFilter()) 
			//路由 ID,唯一
			.id("product-service")
		)
		.build();
	}
}

6.3.2、全局过滤器

自定义全局过滤器需要实现以下两个接口:GlobalFilter , ordered。通过全局过滤器可以实现权限校验,安全性验证等功能。

6.3.2.1、定义过滤器

实现指定接口,添加@component注解即可。
全局过滤器无需注册

CustomGlobalFilter.java

@Component
public class CustomGlobalFilter implements GlobalFilterOrdered {
	/*
	*过滤器业务逻辑
	* param exchange
	* param chain
	* @return
	*/
	@Override
	public Mono<Void> filter(ServerWebExchange exchange,GatewayFilterChain chain) {
		System.out.println("自定义全局过滤器被执行");
		return chain.filter (exchange) ; //继续向下执行
	}
	/**
	*过滤器执行顺序﹔教值越小,优先级越高
	* return
	*/
	@Override
	public int getordef(){
		return 0 ;
	}
}

七、限流

Spring Cloud Gateway官方提供了RequestRateLimiterGatewayFilterFactory 过滤器工厂,使用Redis和 Lua脚本实现了令牌桶的方式。

7.1、配置

依赖
新版redis使用的是pool2连接池

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
</dependency>

配置项

filters:
	- StripPrefix=1
	- name: RequestRateLimiter
	  args:
	    redis-rate-limiter.replenishRate: 1 #令牌桶每秒填充速率
	    redis-rate-limiter.burstcapacity: 2 #令牌桶总容量
	    key-resolver: "#{@pathKeyResolver}" #使用SpEL表达式按名称引用bean


redis:
	timeout: 10000			#连接超时时间
	host: 127.0.0.1	#Redis服务器地址
	port: 6379				#Redis服务器端口
	password: root			#Redis服务器密码
	database: 0				#选择哪个库,默认0库
	lettuce:
		pool:
			max-active: 1024	#最大连接数,默认8
			max-wait: 10000		#最大连接阻塞等待时间,单位毫秒,默认 -1
			max-idle: 200		#最大空闲连接,默认8
			min-idle: 5			#最小空闲连接,默认4

还需要一个bean:pathKeyResolver 根据不同限流方式,书写不同

7.2、限流方式

7.2.1、URL限流

bean:pathKeyResolver

@Configuration
public class KeyResolverConfiguration {
    @Bean
    public KeyResolver pathKeyResolver(){
        return exchange -> Mono.just(exchange.getRequest().getURI( ).getPath());
    }
}

7.2.2、参数限流

bean:parameterKeyResolver

@Bean
public KeyResolver parameterKeyResolver(){
return exchange -> Mono.just(exchange.getRequest().getQueryParams().getFirst( k: "userId"));
}

7.2.3、IP限流

bean:ipKeyResolver

@Bean
public KeyResolver ipKeyResolver() {
	return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getHostName());
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值