Spring Cloud Gateway 网关是SpringCloud官方提供的;
原来有一个Zuul网关,是Netflix公司提供的,现在已经不维护了,后面Netflix公司又出来了一个Zuul2.0网关,但由于一直没有发布稳定版本,所以springcloud等不及了就自己推出一个网关,已经不打算整合zuul2.0了;
Spring Cloud Gateway 项目提供了一个用于在Spring MVC之上构建API网关的库,Spring Cloud Gateway旨在提供一种简单而高效的方法来将请求路由到API,并为它们提供跨领域的关注,例如:安全性,监视/度量和弹性等;
建立在Spring Framework 5,Project Reactor和Spring Boot 2.0之上;
能够匹配任何请求属性上的路由;
谓词和过滤器特定于路由;
Hystrix断路器集成;
Spring Cloud DiscoveryClient的集成;
易于编写的谓词和过滤器;
请求速率限制;
路径改写
alan-gateway
alan-gateway
测试网关服务,不需要spring-web服务
org.springframework.cloud
spring-cloud-starter-gateway
com.alibaba.cloud
spring-cloud-starter-alibaba-nacos-discovery
org.projectlombok
lombok
server:
port: 9999
spring:
application:
name: alan-gateway
cloud:
nacos:
discovery:
server-addr: 192.168.144.100:80
gateway:
discovery:
locator:
# 启用DiscoveryClient网关集成,实现服务发现功能
enabled: true
# 路由集合
routes:
# 路由id
- id: route0
# 资源地址 lb表示开启负载均衡
uri: lb://consumer
predicates:
- Path=consumer/**
Spring Cloud Gateway将路由匹配作为Spring WebFlux HandlerMapping基础架构的一部分,Spring Cloud Gateway包括许多内置的路由谓词工厂,所有这些谓词都与HTTP请求的不同属性匹配,可以将多个路由谓词工厂结合使用;
总共有11个路由谓词工厂:
路由过滤器允许以某种方式修改传入的HTTP请求或传出的HTTP响应,Spring Cloud Gateway包括许多内置的GatewayFilter工厂;
TokenConfig
public class TokenConfig
{
private String token;
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
}
TokenRoutePredicateFactory名字必须是XXXX+RoutePredicateFactory
@Component
public class TokenRoutePredicateFactory extends AbstractRoutePredicateFactory<TokenConfig> {
public TokenRoutePredicateFactory() {
super(TokenConfig.class);
}
@Override
public List<String> shortcutFieldOrder() {
return Collections.singletonList("token");
}
@Override
public Predicate<ServerWebExchange> apply(TokenConfig tokenConfig) {
// (T t) -> true
return exchange -> {
MultiValueMap<String, String> valueMap = exchange.getRequest().getQueryParams();
boolean flag = false;
List<String> list = new ArrayList<>();
valueMap.forEach((k, v) -> {
list.addAll(v);
});
for (String s : list) {
if (StringUtils.equalsIgnoreCase(s, tokenConfig.getToken())) {
flag = true;
break;
}
}
return flag;
};
}
}
谓词配置:
spring:
application:
name: alan-gateway
cloud:
nacos:
discovery:
server-addr: 192.168.144.100:80
gateway:
discovery:
locator:
# 启用DiscoveryClient网关集成,实现服务发现功能
enabled: true
# 路由集合
routes:
# 路由id
- id: route0
# 资源地址 lb表示开启负载均衡
uri: lb://consumer
predicates:
- Token=123456
过滤器分为全局过滤器和普通过滤器,全局过滤器不需要在路由中显式配置自动生效。普通过滤器需要在路由中配置后才能生效。
@Component
public class RequestLogGatewayFilterFactory extends AbstractNameValueGatewayFilterFactory {
@Override
public GatewayFilter apply(NameValueConfig config) {
return (ServerWebExchange exchange, GatewayFilterChain chain)->{
MultiValueMap<String, String> valueMap = exchange.getRequest().getQueryParams();
valueMap.forEach((k,v)->{
System.out.println(k);
System.out.println("==========================");
v.forEach(s->{
System.out.println("*****"+s+"******");
});
});
//继续下一个filter
return chain.filter(exchange);
};
}
}
@Component
public class CustomGlobalFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
MultiValueMap<String, String> map = exchange.getRequest().getQueryParams();
System.out.println("进入全局过滤器,无需显式配置");
return chain.filter(exchange);
}
@Override
public int getOrder() {
return 0;
}
}
实现原理是在全局LoadBalancerClientFilter中进行拦截,然后再该过滤器中依赖LoadBalancerClient loadBalancer,而此负载均衡接口的具体实现是RibbonLoadBalancerClient,即spring cloud gateway已经整合好了ribbon,已经可以实现负载均衡,我们不需要做任何工作,网关对后端微服务的转发就已经具有负载均衡功能;uri: lb//consumer
org.springframework.boot
spring-boot-starter-actuator
com.alibaba.cloud
spring-cloud-starter-alibaba-sentinel
com.alibaba.csp
sentinel-spring-cloud-gateway-adapter
1.7.2
server:
port: 9999
spring:
application:
name: alan-gateway
cloud:
nacos:
discovery:
server-addr: 192.168.144.100:80
gateway:
discovery:
locator:
# 启用DiscoveryClient网关集成,实现服务发现功能
enabled: true
# 路由集合
routes:
# 路由id
- id: route0
# 资源地址 lb表示开启负载均衡
uri: lb://consumer
predicates:
- Token=123456
filters:
- RequestLog=prefix,gateway
sentinel:
transport:
dashboard: 127.0.0.1:8080
eager: true
@Bean
@Order(-1)
public GlobalFilter sentinelGatewayFilter() {
return new SentinelGatewayFilter();
}
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler(BlockRequestHandler myBlockRequestHandler) {
// Register the block exception handler for Spring Cloud Gateway.
//重定向bloack处理
// GatewayCallbackManager.setBlockHandler(new RedirectBlockRequestHandler("http://www.baidu.com"));
//自定义bloack处理
GatewayCallbackManager.setBlockHandler(myBlockRequestHandler);
return new SentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer);
}
/**
* 自定义的BlockRequestHandler
*
* @return
*/
@Bean(name = "myBlockRequestHandler")
public BlockRequestHandler myBlockRequestHandler() {
BlockRequestHandler blockRequestHandler = new BlockRequestHandler() {
@Override
public Mono<ServerResponse> handleRequest(ServerWebExchange serverWebExchange, Throwable throwable) {
return ServerResponse.status(HttpStatus.BAD_GATEWAY)
.contentType(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromObject("服务器太热了,它罢工了~" + throwable.getClass()));
}
};
return blockRequestHandler;
}
什么叫跨域?
协议、ip(域名)、端口有一个不一样就是跨域请求。
添加配置类
/**
* 配置网关跨域cors请求支持
*
*/
@Configuration
public class CorsConfig {
@Bean
public CorsWebFilter corsFilter() {
CorsConfiguration config = new CorsConfiguration();
config.addAllowedMethod("*"); //是什么请求方法,比如 GET POST PUT DELATE .....
config.addAllowedOrigin("*"); //来自哪个域名的请求,*号表示所有
config.addAllowedHeader("*"); //是什么请求头
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(new PathPatternParser());
source.registerCorsConfiguration("/**", config);
return new CorsWebFilter(source);
}
}