网关:统一的入口
- 请求路由的转发
- 负载均衡
- 流量控制,,, sentinel可以融入网关,对全局qps做统一限流
- 身份认证
- 协议转换 : 前段发过来的是json,,但是后端远程调用的协议用的别的协议,,就需要将json转换成适配的数据
- 系统监控
- 安全防护
spring cloud gateway 有两个版本的网关,,一般都使用响应式网关spring-cloud-starter-gateway
网关不属于业务,,属于架构的一部分
spring cloud gateway
spring cloud gateway里面可以配置多个路由规则,,每个路由规则都是自己的 predicate断言,,filter过滤器,uri:目的地,,,
RouteDefinition : 路由定义的类
- id
- uri
- predicates :PredicateDefinition
- filters : FilterDefinition

GatewayHandlerMapping : 请求映射,,,知道某些规则要转给哪里,,但是怎么转过去,需要GatewayWebHandler去处理,,可能处理链路上,有多个过滤器
自定义断言
每一个路由规则的断言和过滤器,,都是通过工厂去创建的,,
AbstractRoutePredicateFactory这个下面有很多的实现类,,就是实现的路由规则
gateway内置了很多断言的规则:

也可以自己集成这个抽象类,去实现自定义的断言规则,,断言的名字和类名的前面几个字母一致,,,
yml
spring:
cloud:
gateway:
routes:
- id: bing-route
uri: https://cn.bing.com
predicates:
- name: Path
args:
pattern: /search
- name: Query
args:
param: q
regexp: haha
# 使用vip这个断言器
# - Vip=ser,waterkid
- name: Vip
# Config里面配置的参数 http://localhost/search?q=haha&user=waterkid
args:
param: user
value: waterkid
自定义名字叫Vip的规则:
java
package com.cj.predicate;
import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory;
import org.springframework.cloud.gateway.handler.predicate.GatewayPredicate;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
/**
* 这个泛型 是 当前工厂的配置
*/
@Component
public class VipRoutePredicateFactory extends AbstractRoutePredicateFactory<VipRoutePredicateFactory.Config> {
public VipRoutePredicateFactory() {
super(Config.class);
}
@Override
public List<String> shortcutFieldOrder() {
// 参数的字段排序,,,, 第一个参数映射到 Config的param,,第二个参数映射到 Config的regexp中
return Arrays.asList("param","value");
}
@Override
public Predicate<ServerWebExchange> apply(Config config) {
return new GatewayPredicate() {
@Override
public boolean test(ServerWebExchange serverWebExchange) {
// ServerWebExchange 里面封装了请求和响应
// 是否转发
ServerHttpRequest request = serverWebExchange.getRequest();
MultiValueMap<String, String> queryParams = request.getQueryParams();
String first = queryParams.getFirst(config.param);
// 参数有值,,并且配置的值和传入的值一样
if (StringUtils.hasText(first) && first.equals(config.value)){
return true;
}
return false;
}
};
}
/**
* 可以配置的参数
*/
public static class Config{
private String param;
private String value;
public String getParam() {
return param;
}
public void setParam(String param) {
this.param = param;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
}
断言规则:

过滤器
gateway也内置了很多过滤器,,过滤器也是通过工厂去创建的
自定义网关过滤器
自定义一个携带token响应头的后置过滤:
java
package com.cj.filter;
import org.apache.http.nio.pool.NIOConnFactory;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.factory.AbstractNameValueGatewayFilterFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import java.util.UUID;
/**
* AbstractNameValueGatewayFilterFactory: 能传递两个参数 name 和 value
*/
@Component
public class OnceTokenGatewayFilterFactory extends AbstractNameValueGatewayFilterFactory {
@Override
public GatewayFilter apply(NameValueConfig config) {
return new GatewayFilter() {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// 每次响应之前,,添加一个一次性令牌
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
ServerHttpResponse response = exchange.getResponse();
HttpHeaders headers = response.getHeaders();
String name = config.getName();
String value = config.getValue();
if (value.equalsIgnoreCase("uuid")) {
value = UUID.randomUUID().toString();
}
if ("jwt".equalsIgnoreCase(value)) {
value = "jwtToken";
}
headers.add(name, value);
}));
}
};
}
}
yml
spring:
cloud:
gateway:
routes:
- id: order-route
# load balancer .转到 order---service
uri: lb://service-order
# 满足规则转发 ,,, 这里转过去了之后,,订单服务会找一模一样的 uri,,就会404
predicates:
- name: Path
args:
patterns: /api/order/**
# 允许尾部url多一个 /
matchTrailingSlash: true
filters:
# 路径重写
- RewritePath=/api/order/?(?<segment>.*),/$\{segment}
# 添加响应头
- AddResponseHeader=X-Response-abc,123
# 自定义过滤器
- OnceToken=X-Response-Token,uuid
自定义全局过滤器: 对所有请求都生效
java
package com.cj.filter;
import lombok.extern.slf4j.Slf4j;
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.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
/**
* 全局filter
* response time :
*/
@Component
@Slf4j
public class RtGlobalFilter implements GlobalFilter, Ordered {
/**
*
* @param exchange 这里面封装了 请求和响应的对象
* @param chain provides a way to delegate to the next filter
* @return
*/
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
ServerHttpResponse response = exchange.getResponse();
String uri = request.getURI().toString();
long start = System.currentTimeMillis();
log.info("请求{} 开始,时间为:{}",uri,start);
// // 响应式编程,,是全异步逻辑
// Mono<Void> filter = chain.filter(exchange)// 异步放行,,下面的代码,,不会等待这个放行结束
// .doFinally((result)->{
// // 在这里写放行结束的逻辑
// long end = System.currentTimeMillis();
// log.info("请求{} 结束,时间为:{}",uri,end-start);
// });
// 响应式编程,,是全异步逻辑
Mono<Void> filter = chain.filter(exchange);// 异步放行,,下面的代码,,不会等待这个放行结束
// doFinally会返回新的Mono,,
Mono<Void> newFilter = filter.doFinally((result) -> {
// 在这里写放行结束的逻辑
long end = System.currentTimeMillis();
log.info("请求{} 结束,时间为:{}", uri, end - start);
});
return newFilter;
}
@Override
public int getOrder() {
return 0;
}
}
gateway跨域
跨域的本质,,就是服务端返回浏览器要求的指定cors响应头,,让浏览器放行原本被同源策略拦截的跨域请求
浏览器为了安全,制定了同源策略,,,不同源的请求,,浏览器会拦截响应,,除非服务端明确,允许跨域的响应头,浏览器才会放行
gateway配置跨域:
yml
spring:
cloud:
gateway:
globalcors:
cors-configurations:
'[/**]':
allowed-origin-patterns: '*'
allowed-headers: '*'
allowed-methods: '*'