一、 简介
-
Spring Cloud Gateway 是 Spring 官网基于 Spring 5.0 、 Spring Boot 2.0 、Project Reactor 等技术开发的网关服务。 -
Spring Cloud Gateway 基于Filter链提供网关基本功能:安全、监控/埋点、限流等。 -
Spring Cloud Gateway 为微服务架构提供简单、有效且统一的API路由管理方式。 -
Spring Cloud Gateway 是替代 Netflix Zuul 的一套解决方案。
?1.1、名词概念
-
路由(route): 路由信息由 一个ID 、一个目的URL 、一组断言工厂 、一组Filter 组成。如果路由断言为 真,说明请求URL和配置路由匹配,就可以通过路由去匹配对应的服务,否则不允通过。 -
断言(Predicate):断言函数输入类型是 Spring 5.0框架 中的 ServerWebExchange ,允许开发者去定义匹配来自于HTTP Request中的任何信息比如请求头和参数。 -
过滤器(Filter): Spring Cloud Gateway中的 Filter 分为两种类型,分别是Gateway Filter和Global Filter,过滤器将会对匹配到的 请求 和 响应 进行修改处理 。
?1.2、服务核心
?1.3、服务架构
?不管是来自于客户端(PC或移动端)的请求,还是服务内部调用。一切对服务的请求都可经过网关,然后再由网关来实现 鉴权、动态路由 等等操作。
?网关就是整个服务的统一入口,来自各个地方请求通过网关之后在进行下一步的调度转发。
二、 部署
?在配置好 服务中心,具体服务提供 之后,重新添加一个项目模块,项目名自定义。
?2.1、依赖管理
?网关只需要在服务中心进行注册,然后通过网关服务调取其他的服务接口,完成请求的转发即可。
<?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">
<parent>
<artifactId>bill-manager-springCloud</artifactId>
<groupId>com.beordie</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>gateway</artifactId>
<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>
</dependencies>
</project>
?2.2、启动类
?通过 springboot 注解启动,添加服务中心的扫描注解。
@SpringBootApplication
@EnableDiscoveryClient
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
?2.3、配置文件
?主要配置相应的 服务中心地址 、路由规则 ,以及涉及 跨域资源请求 的配置。
server:
port: 8086
tomcat:
uri-encoding: UTF-8
spring:
application:
name: gateway
cloud:
gateway:
routes:
- id: bill-service-route
uri: lb://bill-service
predicates:
- Path=/api/**
filters:
- StripPrefix=1
globalcors:
corsConfigurations:
'[/**]':
allowedOrigins: "*"
allowedMethods:
- GET
eureka:
client:
service-url:
defaultZone: HTTP://127.0.0.1:10086/eureka
instance:
prefer-ip-address: true
三、 路由
?3.1、id
- id: bill-service-route
?表示当前设置路由的标识,可以随便进行定义。
?3.2、uri
uri: HTTP://127.0.0.1:9091
uri: lb://bill-service
? 将符合 Path 规则的一切请求,都代理到 uri 参数指定的地址,也就是代理到 http://127.0.0.1:9091 的服务。
? 在刚才的路由规则中,把路径对应的服务地址写死了!如果同一服务有多个实例的话,这样做显然不合理。
? 使用 lb://bill-service 这样的形式,通过 lb: 加上服务的名字,也就是在对应服务配置文件中指定的 application-name ,也可以从服务中心注册的服务名找。
- 路由配置中 uri 所用的协议为 lb 时(以
uri: lb://bill-service 为例),gateway 将使用 LoadBalancerClient 把 bill-service 通过 eureka 解析为实际的主机和端口,并进行 ribbon 负载均衡。
?3.3、predicates
- Path=/api/**
?定义请求当前路由的 url格式 ,也就是说 HTTP://127.0.0.1:8086/api/ 下面的所有请求都会朱发到当前路由进行处理。
?3.4、filters
?功能和名字意义相同,就是配置路由的过滤器的一些功能。
- 添加前缀:对请求地址添加前缀路径之后再作为代理的服务地址。
- PrefixPath=/bill
- 去除前缀:将请求地址中路径去除一些前缀路径之后再作为代理的服务地址,数字表示去除几个前缀。
- StripPrefix=1
四、 跨域
? 在 js 请求访问中,如果访问的地址与当前服务器的 域名 、 ip 或者 端口号 不一致则称为跨域请求。若不解决则不能获取到对应地址的返回结果(能够请求,但是结果会被浏览器所拦截)。
?一般网关都是所有微服务的统一入口,必然在被调用的时候会出现跨域问题。
? 表示对所有访问到网关服务器的请求地址都进行跨域设置。
globalcors:
corsConfigurations:
'[/**]':
?4.1、源地址
?指定允许访问的服务器地址,如:http://localhost:10000 也是可以的, 如果使用 * 就表示所有的访问都可以。
allowedOrigins: "*"
?4.2、请求方式
?指定可以访问的请求方式,可以指定多种。
allowedMethods:
- GET
- POST
- HEAD
五、 过滤器
?5.1、简介
?Gateway 作为网关的其中一个重要功能,就是实现请求的鉴权。而这个动作往往是通过网关提供的过滤器来实现的。前面的 路由功能 也是使用过滤器实现的。
Gateway自带过滤器有几十个,常见自带过滤器有:
过滤器名称 | 功能 |
---|
AddRequestHeader | 对匹配上的请求加上Header | AddRequestParameters | 对匹配上的请求路由添加参数 | AddResponseHeader | 对从网关返回的响应添加Header | StripPrefix | 对匹配上的请求路径去除前缀 |
?5.2、 配置全局默认过滤器
? 这些自带的过滤器的使用和路由配置时的方法一致,也可以将这些过滤器配置成不只是针对某个路由,而是可以对所有路由生效,也就是配置默认过滤器。
default-filters:
- AddResponseHeader=X-Response-Foo, Bar
- AddResponseHeader=name, beordie
? 和上面一样的配置完成之后,每次的请求响应都会携带两个请求头信息,对应的名称和参数和配置的一致,可以在浏览器中对 Response Header 进行查看。
?5.3、自定义局部过滤器
- 编写过滤器,需要继承 AbstractGatewayFilterFactory 并且需要定义内部类来完成参数的赋值。
- 过滤器名需要以
GatewayFilterFactory 结尾。
package com.beordie.filters;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.http.server.reactive.*;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
@Component
public class MyParamGatewayFilterFactory extends
AbstractGatewayFilterFactory<MyParamGatewayFilterFactory.Config> {
static final String PARAM_NAME = "param";
public MyParamGatewayFilterFactory() {
super(Config.class);
}
public List<String> shortcutFieldOrder() {
return Arrays.asList(PARAM_NAME);
}
@Override
public GatewayFilter apply(Config config) {
return (exchange, chain) -> {
ServerHttpRequest request = exchange.getRequest();
if(request.getQueryParams().containsKey(config.param)){
request.getQueryParams().get(config.param).
forEach(value -> System.out.printf("------------局部过滤器--------%s = %s------",
config.param, value));
}
return chain.filter(exchange);
};
}
public static class Config{
private String param;
public String getParam() {
return param;
}
public void setParam(String param) {
this.param = param;
}
}
}
?然后就可以在配置文件对拦截器进行使用。
- MyParam=name
?请求在通过时,过滤去就会试图去查找参数名叫做 name 的携带参数,并且进行控制台的打印操作。
?5.4、 自定义全局过滤器
-
全局过滤器不需要在配置文件中进行配置,直接定义将会配置在程序中 -
需要实现 GlobalFilter , Ordered 两个接口。 package com.beordie.filters;
import org.apache.commons.lang.StringUtils;
import org.springframework.boot.web.servlet.filter.OrderedFilter;
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.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
public class MyGlobalFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
System.out.println("--------------全局过滤器MyGlobalFilter------------------");
String token = exchange.getRequest().getHeaders().getFirst("token");
if(StringUtils.isBlank(token)){
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().setComplete();
}
return chain.filter(exchange);
}
@Override
public int getOrder() {
return 1;
}
}
六、 扩展知识
?6.1、负载均衡和熔断
?Gateway中默认就已经集成了 Ribbon 负载均衡和 Hystrix 熔断机制。但是所有的超时策略都是走的默认值,比如熔断超时时间只有1S,很容易就触发了。因此建议手动进行配置.
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 6000
ribbon:
ConnectTimeout: 1000
ReadTimeout: 2000
MaxAutoRetries: 0
MaxAutoRetriesNextServer: 0
?6.2、Gateway的高可用
?6.3、Gateway与Feign的区别
- Gateway 作为整个应用的流量入口,接收所有的请求,如PC、移动端等,并且将不同的请求转发至不同的处理微服务模块,其作用可视为nginx;大部分情况下用作权限鉴定、服务端流量控制。
- Feign 则是将当前微服务的部分服务接口暴露出来,并且主要用于各个微服务之间的服务调用 。
|