SpringCloudGateway入门
1.什么是SpringCloudGateway?
Spring Cloud Gateway 网关是SpringCloud官方提供的;
原来有一个Zuul网关,是Netflix公司提供的,现在已经不维护了,后面Netflix公司又出来了一个Zuul2.0网关,但由于一直没有发布稳定版本,所以springcloud等不及了就自己推出一个网关,已经不打算整合zuul2.0了;
Spring Cloud Gateway 项目提供了一个用于在Spring MVC之上构建API网关的库,Spring Cloud Gateway旨在提供一种简单而高效的方法来将请求路由到API,并为它们提供跨领域的关注,例如:安全性,监视/度量和弹性等;
2.SpringCloudGateway有什么功能特性?
建立在Spring Framework 5,Project Reactor和Spring Boot 2.0之上;
能够匹配任何请求属性上的路由;
谓词和过滤器特定于路由;
Hystrix断路器集成;
Spring Cloud DiscoveryClient的集成;
易于编写的谓词和过滤器;
请求速率限制;
路径改写
3.SpringCloudGateway核心概念
- 路由:网关的基本组成部分,由一组路由配置组成。单个路由配置包含id、uri、谓词集合、过滤器集合组成。如果维词校验结果为true则住转发,否则拦截请求。
- 谓词:这是Java 8函数谓词,输入类型是Spring Framework ServerWebExchange,可以匹配HTTP请求中的所有内容,例如请求头或参数;
- 过滤器:这些是使用特定工厂构造的Spring Framework GatewayFilter实例,可以在发送给下游请求之前或之后修改请求和响应;
4.简单的网关demo
- 新建网关服务并设置依赖
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
- 配置applicaytion.yml文件
server:port: 9999
spring:application:name: alan-gatewaycloud:nacos:discovery:server-addr: 192.168.144.100:80gateway:discovery:locator:# 启用DiscoveryClient网关集成,实现服务发现功能enabled: true# 路由集合routes:# 路由id- id: route0# 资源地址 lb表示开启负载均衡uri: lb://consumerpredicates:- Path=consumer/**
- 启动网关及consumer服务,请求网关。网关将请求转发到consumer服务上。
5.SpringCloudGateway的工作原理
6.谓词工厂
Spring Cloud Gateway将路由匹配作为Spring WebFlux HandlerMapping基础架构的一部分,Spring Cloud Gateway包括许多内置的路由谓词工厂,所有这些谓词都与HTTP请求的不同属性匹配,可以将多个路由谓词工厂结合使用;
总共有11个路由谓词工厂:
- The After Route Predicate Factory
- The Before Route Predicate Factory
- The Between Route Predicate Factory
- The Cookie Route Predicate Factory
- The Header Route Predicate Factory
- The Host Route Predicate Factory
- The Method Route Predicate Factory
- The Path Route Predicate Factory
- The Query Route Predicate Factory
- The RemoteAddr Route Predicate Factory
- The Weight Route Predicate Factory
- After路由谓词工厂:After route谓词工厂采用一个参数,即datetime(这是一个Java ZonedDateTime),该谓词匹配在指定日期时间之后发生的请求。
- Before路由谓词工厂:Before路由谓词工厂采用一个参数,即datetime(这是一个Java ZonedDateTime),该谓词匹配在指定日期时间之前发生的请求
- Between路由谓词工厂:路由谓词之间的工厂使用两个参数datetime1和datetime2,它们是java ZonedDateTime对象,该谓词匹配在datetime1之后和datetime2之前发生的请求,datetime2参数必须在datetime1之后
- Cookie 路由谓词工厂:Cookie路由谓词工厂采用两个参数,即cookie名称和一个regexp(这是Java正则表达式),该谓词匹配具有给定名称且其值与正则表达式匹配的cookie
- Header 路由谓词工厂:header 路由谓词工厂使用两个参数,header 名称和一个regexp(这是Java正则表达式),该谓词与具有给定名称的header 匹配,该header 的值与正则表达式匹配
- Host 路由谓词工厂:host路由谓词工厂使用一个参数:主机名模式列表
- Method 路由谓词工厂:方法路由谓词工厂使用方法参数,该参数是一个或多个参数:要匹配的HTTP方法
- Path路由谓词工厂:路径路由谓词工厂使用两个参数:Spring PathMatcher模式列表和一个称为matchOptionalTrailingSeparator的可选标志
- Query路由谓词工厂:查询路由谓词工厂采用两个参数:必需的参数和可选的regexp(这是Java正则表达式)
- RemoteAddr 路由谓词工厂:RemoteAddr路由谓词工厂使用源列表(最小大小为1),这些源是标记(IPv4或IPv6)字符串,例如192.168.0.1/16(其中192.168.0.1是IP地址,而16是子网掩码))
- RemoteAddr 路由谓词工厂:权重路由谓词工厂采用两个参数:group和weight(一个int),权重是按组计算的。
7.GatewayFilter工厂
路由过滤器允许以某种方式修改传入的HTTP请求或传出的HTTP响应,Spring Cloud Gateway包括许多内置的GatewayFilter工厂;
8.自定义谓词
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);}@Overridepublic List<String> shortcutFieldOrder() {return Collections.singletonList("token");}@Overridepublic Predicate<ServerWebExchange> apply(TokenConfig tokenConfig) {// (T t) -> truereturn 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-gatewaycloud:nacos:discovery:server-addr: 192.168.144.100:80gateway:discovery:locator:# 启用DiscoveryClient网关集成,实现服务发现功能enabled: true# 路由集合routes:# 路由id- id: route0# 资源地址 lb表示开启负载均衡uri: lb://consumerpredicates:- Token=123456
9.自定义过滤器
过滤器分为全局过滤器和普通过滤器,全局过滤器不需要在路由中显式配置自动生效。普通过滤器需要在路由中配置后才能生效。
- 普通过滤器 继承AbstractNameValueGatewayFilterFactory
@Component
public class RequestLogGatewayFilterFactory extends AbstractNameValueGatewayFilterFactory {@Overridepublic 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+"******");});});//继续下一个filterreturn chain.filter(exchange);};}
}
- 全局过滤器 实现 GlobalFilter, Ordered
@Component
public class CustomGlobalFilter implements GlobalFilter, Ordered {@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {MultiValueMap<String, String> map = exchange.getRequest().getQueryParams();System.out.println("进入全局过滤器,无需显式配置");return chain.filter(exchange);}@Overridepublic int getOrder() {return 0;}
}
10.集成Ribbon实现负载均衡
实现原理是在全局LoadBalancerClientFilter中进行拦截,然后再该过滤器中依赖LoadBalancerClient loadBalancer,而此负载均衡接口的具体实现是RibbonLoadBalancerClient,即spring cloud gateway已经整合好了ribbon,已经可以实现负载均衡,我们不需要做任何工作,网关对后端微服务的转发就已经具有负载均衡功能;uri: lb//consumer
11.集成Sentinel
- 添加依赖
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
- 添加配置项dashboard
server:port: 9999
spring:application:name: alan-gatewaycloud:nacos:discovery:server-addr: 192.168.144.100:80gateway:discovery:locator:# 启用DiscoveryClient网关集成,实现服务发现功能enabled: true# 路由集合routes:# 路由id- id: route0# 资源地址 lb表示开启负载均衡uri: lb://consumerpredicates:- Token=123456filters:- RequestLog=prefix,gatewaysentinel:transport:dashboard: 127.0.0.1:8080eager: true
- 启用SentinelGatewayFilter,配置SentinelGatewayBlockHandler并注入自定义限流Handler
@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() {@Overridepublic Mono<ServerResponse> handleRequest(ServerWebExchange serverWebExchange, Throwable throwable) {return ServerResponse.status(HttpStatus.BAD_GATEWAY).contentType(MediaType.APPLICATION_JSON).body(BodyInserters.fromObject("服务器太热了,它罢工了~" + throwable.getClass()));}};return blockRequestHandler;}
12.处理跨域问题
什么叫跨域?
协议、ip(域名)、端口有一个不一样就是跨域请求。
添加配置类
/*** 配置网关跨域cors请求支持**/
@Configuration
public class CorsConfig {@Beanpublic 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);}
}
13.Sentinel规则持久化到Nacos
14.白名单配置
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!