一、如何引入网关
要在您的项目中包括Spring Cloud Gateway,请使用group ID为org.springframework.Cloud和artifact ID 为Spring Cloud starter Gateway的启动器。有关使用当前Spring Cloud Release Train设置构建系统的详细信息,请参阅Spring Cloud Project页面。
如果包括启动器,但不希望启用网关,请设置 。spring.cloud.gateway.enabled=false
Spring Cloud Gateway 基于 Spring Boot 2.x、Spring WebFlux 和 Project Reactor 构建。 因此,当您使用 Spring Cloud Gateway 时,您知道的许多熟悉的同步库(例如 Spring 数据和 Spring 安全性)和模式可能不适用。 如果您不熟悉这些项目,我们建议您在使用Spring Cloud Gateway之前先阅读他们的文档以熟悉一些新概念。
Spring Cloud Gateway 需要 Spring Boot 和 Spring Webflux 提供的 Netty 运行时。 它不适用于传统的 Servlet 容器或作为 WAR 构建时。
二、词汇表
- Route:网关的基本构建基块。 它由 ID、目标 URI、谓词集合和筛选器集合定义。如果聚合谓词为 true,则匹配路由。
- Predicate:这是一个Java 8函数谓词。输入类型是 Spring Framework ServerWebExchange。 这使您可以匹配 HTTP 请求中的任何内容,例如标头或参数。
- Filter:这些是使用特定工厂构造的网关筛选器实例。 在这里,您可以在发送下游请求之前或之后修改请求和响应。
三、工作原理
下图提供了 Spring 云网关工作原理的高级概述:
客户端向 Spring Cloud 网关发出请求。如果网关处理程序映射确定请求与路由匹配,则会将其发送到网关 Web 处理程序。 此处理程序通过特定于请求的筛选器链运行请求。 筛选器用虚线划分的原因是筛选器可以在发送代理请求之前和之后运行逻辑。 执行所有“预”过滤器逻辑。然后发出代理请求。发出代理请求后,将运行“post”筛选器逻辑。
在没有端口的路由中定义的 URI 分别获取 HTTP 和 HTTPS URI 的默认端口值 80 和 443。
四、配置Route Predicate Factories and Gateway Filter Factories
有两种方法可以配置谓词和筛选器:快捷方式和完全展开的参数。下面的大多数示例都使用快捷方式。
名称和参数名称将作为代码列在每个部分的第一个或两个符号中。参数通常按快捷方式配置所需的顺序列出。
4.1. 快捷键配置
快捷方式配置由筛选器名称识别,后跟等号 (),后跟以逗号 () 分隔的参数值。=,
应用程序.yml
spring: cloud: gateway: routes: - id: after_route uri: https://example.org predicates: - Cookie=mycookie,mycookievalue
前面的示例使用两个参数(cookie 名称和要匹配的值)定义路由谓词工厂。Cookiemycookiemycookievalue
4.2. 完全展开的参数
完全展开的参数看起来更像是具有名称/值对的标准 yaml 配置。通常,会有一个密钥和一个密钥。键是用于配置谓词或筛选器的键值对映射。nameargsargs
application.yml
spring: cloud: gateway: routes: - id: after_route uri: https://example.org predicates: - name: Cookie args: name: mycookie regexp: mycookievalue
这是上面显示的谓词的快捷方式配置的完整配置
五、开发指南
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency>
这些是编写网关的一些自定义组件的基本指南。
1、编写自定义路由谓词工厂
为了编写路由谓词,您需要实现RoutePredicateFactory。有一个抽象类叫做AbstractRoutePredicateFactory,您可以对其进行扩展。
MyRoutePredicateFactory.java
public class MyRoutePredicateFactory extends AbstractRoutePredicateFactory<HeaderRoutePredicateFactory.Config> { public MyRoutePredicateFactory() { super(Config.class); } @Override public Predicate<ServerWebExchange> apply(Config config) { // grab configuration from Config object return exchange -> { //grab the request ServerHttpRequest request = exchange.getRequest(); //take information from the request to see if it //matches configuration. return matches(config, request); }; } public static class Config { //Put the configuration properties for your filter here } }
2、编写自定义网关过滤器工厂
要编写GatewayFilter,您必须实现GatewayFilterFactory。您可以扩展一个名为AbstractGatewayFilterFactory的抽象类。以下示例显示了如何执行此操作:
例 76。PreGatewayFilterFactory.java
public class PreGatewayFilterFactory extends AbstractGatewayFilterFactory<PreGatewayFilterFactory.Config> { public PreGatewayFilterFactory() { super(Config.class); } @Override public GatewayFilter apply(Config config) { // grab configuration from Config object return (exchange, chain) -> { //If you want to build a "pre" filter you need to manipulate the //request before calling chain.filter ServerHttpRequest.Builder builder = exchange.getRequest().mutate(); //use builder to manipulate the request return chain.filter(exchange.mutate().request(builder.build()).build()); }; } public static class Config { //Put the configuration properties for your filter here } }
PostGatewayFilterFactory.java
public class PostGatewayFilterFactory extends AbstractGatewayFilterFactory<PostGatewayFilterFactory.Config> { public PostGatewayFilterFactory() { super(Config.class); } @Override public GatewayFilter apply(Config config) { // grab configuration from Config object return (exchange, chain) -> { return chain.filter(exchange).then(Mono.fromRunnable(() -> { ServerHttpResponse response = exchange.getResponse(); //Manipulate the response in some way })); }; } public static class Config { //Put the configuration properties for your filter here } }
DemogatewayApplication
package com.example.demogateway; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.gateway.filter.ratelimit.RedisRateLimiter; import org.springframework.cloud.gateway.route.RouteLocator; import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder; import org.springframework.context.annotation.Bean; import org.springframework.security.config.web.server.ServerHttpSecurity; import org.springframework.security.core.userdetails.MapReactiveUserDetailsService; import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.web.server.SecurityWebFilterChain; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @SpringBootApplication public class DemogatewayApplication { @RequestMapping("/circuitbreakerfallback") public String circuitbreakerfallback() { return "This is a fallback"; } @Bean public RouteLocator customRouteLocator(RouteLocatorBuilder builder) { //@formatter:off return builder.routes() .route("path_route", r -> r.path("/get") .uri("http://httpbin.org")) .route("host_route", r -> r.host("*.myhost.org") .uri("http://httpbin.org")) .route("rewrite_route", r -> r.host("*.rewrite.org") .filters(f -> f.rewritePath("/foo/(?<segment>.*)", "/${segment}")) .uri("http://httpbin.org")) .route("circuitbreaker_route", r -> r.host("*.circuitbreaker.org") .filters(f -> f.circuitBreaker(c -> c.setName("slowcmd"))) .uri("http://httpbin.org")) .route("circuitbreaker_fallback_route", r -> r.host("*.circuitbreakerfallback.org") .filters(f -> f.circuitBreaker(c -> c.setName("slowcmd").setFallbackUri("forward:/circuitbreakerfallback"))) .uri("http://httpbin.org")) .route("limit_route", r -> r .host("*.limited.org").and().path("/anything/**") .filters(f -> f.requestRateLimiter(c -> c.setRateLimiter(redisRateLimiter()))) .uri("http://httpbin.org")) .route("websocket_route", r -> r.path("/echo") .uri("ws://localhost:9000")) .build(); //@formatter:on } @Bean RedisRateLimiter redisRateLimiter() { return new RedisRateLimiter(1, 2); } @Bean SecurityWebFilterChain springWebFilterChain(ServerHttpSecurity http) throws Exception { return http.httpBasic().and() .csrf().disable() .authorizeExchange() .pathMatchers("/anything/**").authenticated() .anyExchange().permitAll() .and() .build(); } @Bean public MapReactiveUserDetailsService reactiveUserDetailsService() { UserDetails user = User.withDefaultPasswordEncoder().username("user").password("password").roles("USER").build(); return new MapReactiveUserDetailsService(user); } public static void main(String[] args) { SpringApplication.run(DemogatewayApplication.class, args); } }
2.1、在配置中命名自定义过滤器和引用
自定义筛选器类名应以GatewayFilterFactory结尾。
例如,要在配置文件中引用名为Something的筛选器,该筛选器必须位于名为SomethingGatewayFilterFactory的类中。
可以创建不带后缀的网关筛选器,例如 。此筛选器可能是 如在配置文件中引用。这不是受支持的命名 约定和此语法可能会在将来的版本中删除。请更新过滤器 要合规的名称。GatewayFilterFactoryclass AnotherThingAnotherThing
3、编写自定义全局过滤器
若要编写自定义全局筛选器,必须实现GlobalFilter接口。这将筛选器应用于所有请求。
以下示例分别显示了如何设置全局前置过滤器和后置过滤器:
@Bean public GlobalFilter customGlobalFilter() { return (exchange, chain) -> exchange.getPrincipal() .map(Principal::getName) .defaultIfEmpty("Default User") .map(userName -> { //adds header to proxied request exchange.getRequest().mutate().header("CUSTOM-REQUEST-HEADER", userName).build(); return exchange; }) .flatMap(chain::filter); } @Bean public GlobalFilter customGlobalPostFilter() { return (exchange, chain) -> chain.filter(exchange) .then(Mono.just(exchange)) .map(serverWebExchange -> { //adds header to response serverWebExchange.getResponse().getHeaders().set("CUSTOM-RESPONSE-HEADER", HttpStatus.OK.equals(serverWebExchange.getResponse().getStatusCode()) ? "It worked": "It did not work"); return serverWebExchange; }) .then(); }
六、故障排除
1、日志级别
以下记录器可能包有价值的故障排除信息:当日志设置为DEBUG和 TRACE
- org.springframework.cloud.gateway
- org.springframework.http.server.reactive
- org.springframework.web.reactive
- org.springframework.boot.autoconfigure.web
- reactor.netty
- redisratelimiter
2、监听
在 HttpClient and HttpServer模式下可以启用监听。当与将日志级别设置为 或 结合使用时,它可以记录信息,例如通过网络发送和接收的标头和正文。
要启用监听,请分别设置 :spring.cloud.gateway.httpserver.wiretap=true or spring.cloud.gateway.httpclient.wiretap=true 。
文章下方有交流学习区!一起学习进步!也可以前往官网,加入官方微信交流群你的支持和鼓励是我创作的动力❗❗❗
官网:Doker 多克; 官方旗舰店:首页-Doker 多克 多克创新科技企业店-淘宝网 全品优惠