Spring Cloud Gateway是Spring官网基于Spring 5.0、 Spring Boot 2.0、Project Reactor等技术开发的网关服务。
而加强安全保护。Spring Cloud Gateway本身也是一个微服务,需要注册到Eureka服务注册中心。
网关的核心功能是:过滤和路由。
路由(route)
路由信息的组成:由一个ID、一个目的URL、一组断言工厂、一组Filter组成。如果路由断言为真,说明请求URL和配置路由匹配。
断言(Predicate)
Spring Cloud Gateway中的断言函数输入类型是Spring 5.0框架中的ServerWebExchange。Spring Cloud Gateway的断言函数允许开发者去定义匹配来自于Http Request中的任何信息比如请求头和参数。
过滤器(Filter)
一个标准的Spring WebFilter。 Spring Cloud Gateway中的Filter分为两种类型的Filter,分别是Gateway Filter和Global Filter。过滤器Filter将会对请求和响应进行修改处理。
利用GateWay将包含有/user的请求路由到http:localhost:9091/user/id服务中。
创建service-gateway工程,引入相关依赖:
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix-eureka-client</artifactId>
</dependency>
</dependencies>
package com.giser.gateway;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class GatewayApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayApplication.class, args);
}
}
server:
port: 10010
spring:
application:
name: api-gateway
security:
user:
name: admin
password: 123
eureka:
client:
service-url:
defaultZone: http://${spring.security.user.name}:${spring.security.user.password}@localhost:10086/eureka,http://${spring.security.user.name}:${spring.security.user.password}@localhost:10087/eureka
instance:
prefer-ip-address: true
需要利用网关来代理user-service服务,将所有符合/user/**规则的请求路由到url指定的服务地址中。
spring:
application:
name: api-gateway
security:
user:
name: admin
password: 123
cloud:
gateway:
routes:
# 路由配置
# 路由ID,可以任意
- id: user-service-router
# 代理的服务地址
uri: http://127.0.0.1:9091
# 路由断言,可以配置映射路径
predicates:
- Path=/user/**
访问路由地址http://localhost:10010/user/8,可以正常请求到服务。
在SpringCloud Gateway中可以配置动态路由,使用在Eureka中注册的服务作为路由地址。只需要在配置文件中通过uri: lb://user-service指定代理服务地址即可。
spring:
application:
name: api-gateway
security:
user:
name: admin
password: 123
cloud:
gateway:
routes:
# 路由配置
# 路由ID,可以任意
- id: user-service-router
# 代理的服务地址
uri: lb://user-service
# 路由断言,可以配置映射路径
predicates:
- Path=/user/**
注意: lb之后的服务名需要在Eureka中注册之后才能使用。
在GateWay中可以通过配置路由的过滤器PrefixPath,实现映射路径地址前缀的添加;通过配置路由的过滤器StripPrefix,实现映射地址前缀的去除。
server:
port: 10099
spring:
application:
name: api-gateway
security:
user:
name: admin
password: 123
cloud:
gateway:
discovery:
locator:
enabled: true
lower-case-service-id: true
routes:
# 路由配置
# 路由ID,可以任意
- id: user-service-router
# 代理的服务地址,lb代表从eureka中获取服务地址
# uri: http://127.0.0.1:9091
uri: lb://user-service
# 路由断言,可以配置映射路径
predicates:
# - Path=/user/**
- Path=/**
filters:
#
- PrefixPath=/user
通过PrefixPath=/user添加路由前缀,例如:
PrefixPath=/user http://localhost:10010/8 --》http://localhost:9091/user/8
PrefixPath=/user/abc http://localhost:10010/8 --》http://localhost:9091/user/abc/8
server:
port: 10099
spring:
application:
name: api-gateway
security:
user:
name: admin
password: 123
cloud:
gateway:
discovery:
locator:
enabled: true
lower-case-service-id: true
routes:
# 路由配置
# 路由ID,可以任意
- id: user-service-router
# 代理的服务地址,lb代表从eureka中获取服务地址
# uri: http://127.0.0.1:9091
uri: lb://user-service
# 路由断言,可以配置映射路径
predicates:
# - Path=/user/**
# - Path=/**
- Path=/api/user/**
filters:
# - PrefixPath=/user
# 1表示过滤一个路径,2表示过滤两个路径等
- StripPrefix=1
通过StripPrefix=1
来指定了路由要去掉的前缀个数。如:路径/api/user/1
将会被代理到/user/1
,例如:
StripPrefix=1 http://localhost:10010/api/user/8 --》http://localhost:9091/user
StripPrefix=2 http://localhost:10010/api/user/8 --》http://localhost:9091/8
GateWay作为网关的一个重要功能是通过网关提供的过滤器实现请求的鉴权。
GateWay自带的过滤器较多,如下图:
GateWay自带的过滤器较多,如下图:
过滤器名称 | 说明 |
---|---|
AddRequestHeader | 对匹配上的请求加上Header |
AddRequestParameters | 对匹配上的请求路由添加参数 |
AddResponseHeader | 对从网关返回的响应添加Header |
StripPre?x | 对匹配上的请求路径去除前缀 |
过滤器类型
Gateway实现方式上,有两种过滤器;
局部过滤器
通过spring.cloud.gateway.routes.filters
配置在具体路由下,只作用在当前路由上;自带的过滤器都可以配置或者自定义按照自带过滤器的方式。如果配置spring.cloud.gateway.default-filters
上会对所有路由生效也算是全局的过滤器;但是这些过滤器的实现上都是要实现GatewayFilterFactory
接口。
全局过滤器
不需要在配置文件中配置,作用在所有的路由上;实现 GlobalFilter 接口即可。
Spring Cloud Gateway 的 Filter 的生命周期也类似Spring MVC的拦截器有两个:pre
和 post
。pre
和 post
分别会在请求被执行前调用和被执行后调用。
spring:
application:
name: api-gateway
cloud:
gateway:
# 默认过滤器,对所有路由生效
default-filters:
# 响应头过滤器,对输出的响应设置其头部属性名称为name,值为giserDev; 如果有多个参数多则重写一行设置不同的参数
- AddResponseHeader=name, giserDev
package com.giser.gateway.filter;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.http.server.reactive.ServerHttpRequest;
import java.util.Arrays;
import java.util.List;
public class MyParamGatewayFilterFactory extends AbstractGatewayFilterFactory<MyParamGatewayFilterFactory.Config> {
public static final String PARAM_NAME = "param";
public MyParamGatewayFilterFactory() {
super(Config.class);
}
@Override
public GatewayFilter apply(Config config) {
return ((exchange, chain) -> {
ServerHttpRequest request = exchange.getRequest();
if (request.getQueryParams().containsKey(config.name)){
request.getQueryParams().get(config.name).forEach(value -> {
System.out.printf("---局部过滤器--%s--%s-", config.name, value);
});
}
return chain.filter(exchange);
});
}
@Override
public List<String> shortcutFieldOrder() {
return Arrays.asList(PARAM_NAME);
}
public static class Config {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
}
Gateway中默认就已经集成了Ribbon负载均衡和Hystrix熔断机制。但是所有的超时策略都是走的默认值,比如熔断超时时间只有1S,很容易就触发了。因此建议手动进行配置:
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 6000
ribbon:
ConnectTimeout: 1000
ReadTimeout: 2000
MaxAutoRetries: 0
MaxAutoRetriesNextServer: 0
一般网关都是所有微服务的统一入口,必然在被调用的时候会出现跨域问题。
跨域: 在js请求访问中,如果访问的地址与当前服务器的域名、ip或者端口号不一致则称为跨域请求。如:从在http://localhost:9090中的js访问 http://localhost:9000的数据,因为端口不同,所以也是跨域请求。
在访问Spring Cloud Gateway网关服务器的时候,出现跨域问题的话;可以在网关服务器中通过配置解决,允许哪些服务是可以跨域请求的;具体配置如下:
spring:
cloud:
gateway:
globalcors:
corsConfigurations:
'[/**]':
#allowedOrigins: * # 这种写法或者下面的都可以,*表示全部
allowedOrigins:
- "http://docs.spring.io"
allowedMethods:
- GET
上述配置表示:可以允许来自 http://docs.spring.io 的get请求方式获取服务数据。
allowedOrigins 指定允许访问的服务器地址,如:http://localhost:10000 也是可以的。
‘[/**]’ 表示对所有访问到网关服务器的请求地址
官网具体说明