目录
二、 使用 Spring Cloud Gateway 实现路由功能
三、 使用 Spring Cloud Gateway 实现过滤器功能
四、 使用 Spring Cloud Gateway 实现熔断功能
一、 Spring Cloud Gateway 简介
1 概述
Spring cloud gateway
是
spring
官方基于
Spring 5.0
、
Spring Boot2.0
和
Project Reactor
等技术开发的网关,
Spring Cloud Gateway
旨在为微服务架构提供简单、有效和统一的
API
路由管理方式,
Spring Cloud Gateway
作为
Spring Cloud
生态系统中的网关,目标是替代
Netflix Zuul
,其不仅提供统一的路由方式,并且还基于
Filer
链的方式提供了网关基本的
功能,例如:安全、监控
/
埋点、限流等。
2 核心概念
2.1 API 网关
API
网关出现的原因是微服务架构的出现,不同的微服务一般会有不同的网络地址,
而外部客户端可能需要调用多个服务的接口才能完成一个业务需求,如果让客户端直接与
各个微服务通信,会有以下的问题:
客户端会多次请求不同的微服务,增加了客户端的复杂性。
存在跨域请求,在一定场景下处理相对复杂。
认证复杂,每个服务都需要独立认证。
难以重构,随着项目的迭代,可能需要重新划分微服务。例如,可能将多个服务合并
成一个或者将一个服务拆分成多个。如果客户端直接与微服务通信,那么重构将会很难实
施。
某些微服务可能使用了防火墙
/
浏览器不友好的协议,直接访问会有一定的困难。
以上这些问题可以借助
API
网关解决。
API
网关是介于客户端和服务器端之间的中
间层,所有的外部请求都会先经过
API
网关这一层。也就是说,
API
的实现方面更多的
考虑业务逻辑,而安全、性能、监控可以交由
API
网关来做,这样既提高业务灵活性又
不缺安全性。
使用
API
网关后示意图:
使用
API
网关后的优点如下:
易于监控。可以在网关收集监控数据并将其推送到外部系统进行分析。
易于认证。可以在网关上进行认证,然后再将请求转发到后端的微服务,而无须在每
个微服务中进行认证。
统一接入。减少了客户端与各个微服务之间的交互次数。
2.2 路由
路由是网关最基础的部分,路由信息有一个
ID
、一个目的
URL
、一组断言和一组
Filter
组成。如果断言路由为真,则说明请求的
URL
和配置匹配。
2.3 过滤器
一个标准的
Spring webFilter
。
Spring cloud gateway
中的
filter
分为两种类型的
Filter
,
分别是
Gateway Filter
和
Global Filter
。过滤器
Filter
将会对请求和响应进行修改处理。执
行示意图如下:
如上图所示,
Spring cloudGateway
发出请求。然后再由
Gateway Handler Mapping
中
找到与请求相匹配的路由,将其发送到
Gateway web handler
。
Handler
再通过指定的过滤
器链将请求发送到我们实际的服务执行业务逻辑,然后返回。
二、 使用 Spring Cloud Gateway 实现路由功能
1 入门案例
1.1 创建 Gateway 项目
1.1.1 pom文件
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.11.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.star</groupId>
<artifactId>springcloud-06-gateway</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springcloud-06-gateway</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.SR4</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
1.1.2 配置文件
#设置端口号
server:
port: 8081
#设置应用名称
spring:
application:
name: cloud-gateway
cloud:
gateway:
discovery:
locator:
enabled: false #关闭Gateway服务注册和发现的功能
lower-case-service-id: true #将请求路径上的服务名配置为小写
#手工绑定路由规则
routes:
- id: service01 #唯一命名
uri: lb://service01 # 转发路径,lb 代表 loadbalance,即从 Eureka 中获取的服务列表负载均衡器。
#openfeign-client 即服务名称,相当于openfeign-client 即服务名称,相当于 http://localhost:8081/
predicates: # 定义映射
- Path=/aaa/** # 发送到 Gateway 网关上的请求路径映射,此映射匹 配的路径都会转发到 uri 上。
#具体地址为: lb://openfeign-client/client/**
filters:
- StripPrefix=1 # 请求转发时,会自动过滤请求转发的第一节地址,即 client。最终地址为: lb://openfeign-client/**
- AddRequestParameter=age,30
- AddRequestParameter=name,TeacherWu
- AddRequestParameter=token,123
- AddRequestHeader=myHeader,myHeaderValue
- Authentication=token
- name: Hystrix #开器Hystrix过滤器
args:
name: fallbackcmd
fallbackUri: forward:/fallback #设置Hystrix回调方法的请求路径
- id: service02
uri: lb://service02
predicates:
- Path=/bbb/**
filters:
- StripPrefix=1
#设置注册中心连接信息
eureka:
client:
service-url:
defaultZone: http://localhost:8080/eureka
#hystrix服务降级
hystrix:
command:
default:
execution:
timeout:
# 如果enabled设置为false,则请求超时交给ribbon控制,为true,则超时作为容错根据
enabled: true
isolation:
thread:
timeoutInMilliseconds: 1000 # 超时时间,默认1000ms
1.1.3 启动类
@SpringBootApplication
@EnableCircuitBreaker
public class Springcloud06GatewayApplication {
public static void main(String[] args) {
SpringApplication.run(Springcloud06GatewayApplication.class, args);
}
}
2 配置文件手工绑定路由规则
2.1 POM 文件
不需要修改
2.2 配置文件
通过routes绑定
#设置端口号
server:
port: 8081
#设置应用名称
spring:
application:
name: cloud-gateway
cloud:
gateway:
discovery:
locator:
enabled: false #关闭Gateway服务注册和发现的功能
lower-case-service-id: true #将请求路径上的服务名配置为小写
#手工绑定路由规则
routes:
- id: service01 #唯一命名
uri: lb://service01 # 转发路径,lb 代表 loadbalance,即从 Eureka 中获取的服务列表负载均衡器。
#openfeign-client 即服务名称,相当于openfeign-client 即服务名称,相当于 http://localhost:8081/
predicates: # 定义映射
- Path=/aaa/** # 发送到 Gateway 网关上的请求路径映射,此映射匹 配的路径都会转发到 uri 上。
#具体地址为: lb://openfeign-client/client/**
filters:
- StripPrefix=1 # 请求转发时,会自动过滤请求转发的第一节地址,即 client。最终地址为: lb://openfeign-client/**
- AddRequestParameter=age,30 # 在请求中自动增加一个请求参数,参数名为 age,参数值为 30。可以用于提供固定参数。
- AddRequestParameter=name,TeacherWu # 每个 AddRequestParameter 过滤器,只能提供一个请求参数,提供多请求参数,需要定义多个过滤器
- AddRequestParameter=token,123
- AddRequestHeader=myHeader,myHeaderValue e # 在请求中自动增加 一个请求头参数,参数名为 my-header,参数值为 test-header-value。
- Authentication=token
- name: Hystrix #开器Hystrix过滤器
args:
name: fallbackcmd
fallbackUri: forward:/fallback #设置Hystrix回调方法的请求路径
- id: service02
uri: lb://service02
predicates:
- Path=/bbb/**
filters:
- StripPrefix=1
#设置注册中心连接信息
eureka:
client:
service-url:
defaultZone: http://localhost:8080/eureka
#hystrix服务降级
hystrix:
command:
default:
execution:
timeout:
# 如果enabled设置为false,则请求超时交给ribbon控制,为true,则超时作为容错根据
enabled: true
isolation:
thread:
timeoutInMilliseconds: 1000 # 超时时间,默认1000ms
2.3 启动类
不需要修改
三、 使用 Spring Cloud Gateway 实现过滤器功能
Spring Cloud gateway
的
filter
分为两种:
GatewayFilter
和
Globalfilter
。
GlobalFilter
会
应用到所有的路由上,而
Gatewayfilter
将应用到单个路由或者一个分组的路由上。
多个过滤器会根据配置文件中的定义来决定执行顺序。
如果提供的自定义过滤器实现了
Ordered
接口,则可以通过接口中的方法
getOrder
来
决定执行顺序。具体顺序由
getOrder
方法返回结果升序排列。
1 Spring Cloud Gateway 内置过滤器
GatewayFilter
是一个接口,通过查看源码,其有很多实现类,不同的实现类实现不同
的过滤功能。具体如下:
常用过滤器有:
AddRequestParameterGatewayFilterFactory -
在指定请求中增加请求参数的过滤器。
AddRequestHeaderGatewayFilterFactory -
在指定请求中增加请求头参数的过滤器。
StripPrefixGatewayFilterFactory -
在指定请求中处理路径前缀的过滤器。
在
Gateway
中使用过滤器的方式非常简单,只要在配置文件中通过过滤器命名前缀即
可 快 速 使 用 , 如 使 用
AddRequestParameterGatewayFilterFactory
, 可 以 通 过
AddRequestParameter
在配置文件中配置使用;如使用
StripPrefixGatewayFilterFactory
,可
以通过
StripPrefix
在配置文件中配置使用。
具体配置过程如下:
#设置端口号
server:
port: 8081
#设置应用名称
spring:
application:
name: cloud-gateway
cloud:
gateway:
discovery:
locator:
enabled: false #关闭Gateway服务注册和发现的功能
lower-case-service-id: true #将请求路径上的服务名配置为小写
#手工绑定路由规则
routes:
- id: service01 #唯一命名
uri: lb://service01 # 转发路径,lb 代表 loadbalance,即从 Eureka 中获取的服务列表负载均衡器。
#openfeign-client 即服务名称,相当于openfeign-client 即服务名称,相当于 http://localhost:8081/
predicates: # 定义映射
- Path=/aaa/** # 发送到 Gateway 网关上的请求路径映射,此映射匹 配的路径都会转发到 uri 上。
#具体地址为: lb://openfeign-client/client/**
filters:
- StripPrefix=1 # 请求转发时,会自动过滤请求转发的第一节地址,即 client。最终地址为: lb://openfeign-client/**
- AddRequestParameter=age,30 # 在请求中自动增加一个请求参数,参数名为 age,参数值为 30。可以用于提供固定参数。
- AddRequestParameter=name,TeacherWu # 每个 AddRequestParameter 过滤器,只能提供一个请求参数,提供多请求参数,需要定义多个过滤器
- AddRequestParameter=token,123
- AddRequestHeader=myHeader,myHeaderValue e # 在请求中自动增加 一个请求头参数,参数名为 my-header,参数值为 test-header-value。
- Authentication=token
- name: Hystrix #开器Hystrix过滤器
args:
name: fallbackcmd
fallbackUri: forward:/fallback #设置Hystrix回调方法的请求路径
- id: service02
uri: lb://service02
predicates:
- Path=/bbb/**
filters:
- StripPrefix=1
#设置注册中心连接信息
eureka:
client:
service-url:
defaultZone: http://localhost:8080/eureka
#hystrix服务降级
hystrix:
command:
default:
execution:
timeout:
# 如果enabled设置为false,则请求超时交给ribbon控制,为true,则超时作为容错根据
enabled: true
isolation:
thread:
timeoutInMilliseconds: 1000 # 超时时间,默认1000ms
2 自定义过滤器
2.1 自定义 GatewayFilter - 网关过滤器
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import java.util.Arrays;
import java.util.List;
/**
* 登录校验过滤器工厂
* 泛型是此工厂构造时自动注入的配置对象。此配置对象由Spring容器提供。
* 根据配置文件中提供的后置配置内容,自动进行配置。
* 如: 当前类型中定义Config有一个属性token,此属性为字符串类型。那么对应的配置是, Authentication=xxx,xxx就是要传递的token属性值。
* 在当前实现中,Config中的token属性即是请求参数中用于标明登录标记的请求参数名。
*/
@Component
public class AuthenticationGatewayFilterFactory extends AbstractGatewayFilterFactory<AuthenticationGatewayFilterFactory.Config> {
public AuthenticationGatewayFilterFactory() {
super(AuthenticationGatewayFilterFactory.Config.class);
}
/**
* Spring构造Config对象时,读取的配置文件数据对应Config对象中的哪一个属性,即property命名。
* @return
*/
@Override
public List<String> shortcutFieldOrder() {
return Arrays.asList("tokenName");
}
//完成核心过滤业务逻辑
@Override
public GatewayFilter apply(Config config) {
return new GatewayFilter() {
//ServerWebExchange命名为服务网络交换器,存放着重要的请求-响应属性、请求实例和响应实例等等
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String token = exchange.getRequest().getQueryParams().getFirst(config.getTokenName());
//请求头中不存在token,用户未登录,返回登录。
if(token == null || token.isEmpty()){
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().setComplete();
}
// 用户已登录,进入后续执行流程
return chain.filter(exchange);
}
};
}
public static class Config{
private String tokenName;
public String getTokenName() {
return tokenName;
}
public void setTokenName(String tokenName) {
this.tokenName = tokenName;
}
}
}
2.2 自定义 GlobalFilter - 全局过滤器
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
/**
* 日志全局过滤器
*/
@Component
public class LoggerGlobalFilter implements GlobalFilter {
private Logger logger = LoggerFactory.getLogger(LoggerGlobalFilter.class);
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
logger.info("logger日志输出!");
return chain.filter(exchange);
}
}
四、 使用 Spring Cloud Gateway 实现熔断功能
Spring Cloud Gateway
也可以利用
Hystrix
的熔断特性,在流量过大时进行服务降级。
1 POM 依赖
同上
2 熔断处理代码
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class FallbackController {
@GetMapping("/fallback")
public String fallback(){
return "服务降级fallcack方法执行!";
}
}
3 配置文件
#设置端口号
server:
port: 8081
#设置应用名称
spring:
application:
name: cloud-gateway
cloud:
gateway:
discovery:
locator:
enabled: false #关闭Gateway服务注册和发现的功能
lower-case-service-id: true #将请求路径上的服务名配置为小写
#手工绑定路由规则
routes:
- id: service01 #唯一命名
uri: lb://service01 # 转发路径,lb 代表 loadbalance,即从 Eureka 中获取的服务列表负载均衡器。
#openfeign-client 即服务名称,相当于openfeign-client 即服务名称,相当于 http://localhost:8081/
predicates: # 定义映射
- Path=/aaa/** # 发送到 Gateway 网关上的请求路径映射,此映射匹 配的路径都会转发到 uri 上。
#具体地址为: lb://openfeign-client/client/**
filters:
- StripPrefix=1 # 请求转发时,会自动过滤请求转发的第一节地址,即 client。最终地址为: lb://openfeign-client/**
- AddRequestParameter=age,30 # 在请求中自动增加一个请求参数,参数名为 age,参数值为 30。可以用于提供固定参数。
- AddRequestParameter=name,TeacherWu # 每个 AddRequestParameter 过滤器,只能提供一个请求参数,提供多请求参数,需要定义多个过滤器
- AddRequestParameter=token,123
- AddRequestHeader=myHeader,myHeaderValue e # 在请求中自动增加 一个请求头参数,参数名为 my-header,参数值为 test-header-value。
- Authentication=token
- name: Hystrix #开器Hystrix过滤器
args:
name: fallbackcmd
fallbackUri: forward:/fallback #设置Hystrix回调方法的请求路径
- id: service02
uri: lb://service02
predicates:
- Path=/bbb/**
filters:
- StripPrefix=1
#设置注册中心连接信息
eureka:
client:
service-url:
defaultZone: http://localhost:8080/eureka
#hystrix服务降级
hystrix:
command:
default:
execution:
timeout:
# 如果enabled设置为false,则请求超时交给ribbon控制,为true,则超时作为容错根据
enabled: true
isolation:
thread:
timeoutInMilliseconds: 1000 # 超时时间,默认1000ms
4 启动类
同上