gateway介绍
gateway相当于所有服务的门户,将客户端请求与服务端应用相分离,客户端请求通过gateway后由定义的路由和断言进行转发,路由代表需要转发请求的地址,断言相当于请求这些地址时所满足的条件,只有同时符合路由和断言才给予转发。
Spring Cloud Gateway 网关的搭建:
1.加入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!--调用nacos服务 启动类加 @EnableDiscoveryClient-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
注意:一定要排除掉 spring-boot-starter-web 依赖,否则启动报错
2.application.yml配置文件
server:
port: 8083
spring:
application:
name: gateway
cloud:
#加入nacos
# nacos:
# discovery:
# server-addr: 192.168.14.2:8848
gateway:
routes:
- id: rout01
uri: http://httpbin.org:80/
#调用nacos服务
#uri: lb://nacos-app-a
# 断言
predicates:
- Path=/a/**
# - Cookie=mycookie,123
filters:
- StripPrefix=1
- AddRequestParameter=red, blue
- AddResponseHeader=name,zhangbozhi
- ElapsedTime
- id: rout02
uri: http://www.beiyouedu.com/
predicates:
- Path=/b/**
filters:
- StripPrefix=1
# 全局配置
default-filters:
- AddRequestHeader=sign,123
- AddResponseHeader=sss,206
好了,网关项目搭建完成,其实就添加这么一个依赖,关于详细的配置以及作用下文介绍。
3.Spring Cloud Gateway 配置项的说明:
在介绍 Spring Cloud Gateway 的配置项之前,我们先了解几个 Spring Cloud Gateway 的核心术语:
断言(Predicate):参照 Java8 的新特性Predicate,允许开发人员匹配 HTTP 请求中的任何内容,比如请求头或请求参数,最后根据匹配结果返回一个布尔值。
路由(route):由ID、目标URI、断言集合和过滤器集合组成。如果聚合断言结果为真,则转发到该路由。
过滤器(filter):可以在返回请求之前或之后修改请求和响应的内容。
3.1、路由 Route:
Route 主要由 路由id、目标uri、断言集合和过滤器集合组成,那我们简单看看这些属性到底有什么作用。
(1)id:路由标识,要求唯一,名称任意(默认值 uuid,一般不用,需要自定义)
(2)uri:请求最终被转发到的目标地址
(3)order: 路由优先级,数字越小,优先级越高
(4)predicates:断言数组,即判断条件,如果返回值是boolean,则转发请求到 uri 属性指定的服务中
(5)filters:过滤器数组,在请求传递过程中,对请求做一些修改
3.2、断言 Predicate:
Predicate 来自于 Java8 的接口。Predicate 接受一个输入参数,返回一个布尔值结果。该接口包含多种默认方法来将 Predicate 组合成其他复杂的逻辑(比如:与,或,非)。
Predicate 可以用于接口请求参数校验、判断新老数据是否有变化需要进行更新操作。
3.3、过滤器 filter:
Gateway 过滤器的生命周期:
PRE:这种过滤器在请求被路由之前调用。我们可利用这种过滤器实现身份验证、在集群中选择请求的微服务、记录调试信息等。
POST:这种过滤器在路由到微服务以后执行。这种过滤器可用来为响应添加标准的 HTTP Header、收集统计信息和指标、将响应从微服务发送给客户端等。
Gateway 过滤器从作用范围可分为两种:
GatewayFilter:应用到单个路由或者一个分组的路由上(需要在配置文件中配置)
GlobalFilter:应用到所有的路由上(无需配置,全局生效)
(1)局部过滤器 GatewayFilter:
局部过滤器需要在指定路由配置才能生效,默认是不生效的。以 “AddResponseHeaderGatewayFilterFactory” 这个过滤器为例,为原始响应添加Header,配置如下
filters:
- StripPrefix=1
- AddRequestParameter=red, blue
- AddResponseHeader=name,zhangbozhi
(2)全局过滤器
# 全局配置
default-filters:
- AddRequestHeader=sign,123
- AddResponseHeader=sss,206
(3)自定义全局过滤器
package com.example.filter;
import cn.hutool.core.util.IdUtil;
import org.springframework.cloud.commons.util.IdUtils;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
public class CustomGlobaFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
/*exchange 为了安全性都是只读的 ,要是想添加东西就先copy下*/
ServerHttpRequest request2 = request.mutate().header("traceid", IdUtil.fastUUID()).build();
return chain.filter(exchange.mutate().request(request2).build());
}
@Override
public int getOrder() {
return -1;
}
}
注册全局过滤器
package com.example.config;
import com.example.filter.CustomGlobaFilter;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class FilterConfig {
@Bean
public GlobalFilter customFilter(){
return new CustomGlobaFilter();
}
}
(4)自定义局部过滤器
package com.example.filter;
import cn.hutool.core.util.StrUtil;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.core.Ordered;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
//记录接口耗时
//局部定义
public class ElapsedTimeGatewayFilter implements GatewayFilter, Ordered {
private final static String BEAGIN = "begin";
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
exchange.getAttributes().put(BEAGIN, System.currentTimeMillis());
return chain.filter(exchange).then(
Mono.fromRunnable(() -> {
long startTime = exchange.getAttribute(BEAGIN);
long endTime = System.currentTimeMillis();
String url = exchange.getRequest().getURI().getRawPath();
System.out.println(StrUtil.format("{}耗时:{}", url, endTime - startTime));
})
);
}
@Override
public int getOrder() {
return Ordered.HIGHEST_PRECEDENCE;
}
}
注册局部过滤器与全局不同的是需要继承AbstractGatewayFilterFactory接口
package com.example.filter;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.stereotype.Component;
@Component
public class ElapsedTimeGatewayFilterFactory extends AbstractGatewayFilterFactory<Object> {
@Override
public GatewayFilter apply(Object config) {
return new ElapsedTimeGatewayFilter();
}
}