Spring Cloud GateWay是Spring Cloud的⼀個全新項⽬,⽬標是取代Netflflix Zuul,它基於Spring5.0+SpringBoot2.0+WebFlux(基於⾼性能的Reactor模式響應式通信框架Netty,異步⾮阻塞模型)等技術開發,性能⾼於Zuul,官⽅測試,GateWay是Zuul的1.6倍,旨在為微服務架構提供⼀種簡單有效的統⼀的API路由管理⽅式。Spring Cloud GateWay不僅提供統⼀的路由⽅式(反向代理)並且基於 Filter(定義過濾器對請求過濾,完成⼀些功能) 鏈的⽅式提供了⽹關基本的功能,例如:鑒權、流量控制、熔斷、路徑重寫、⽇志監控等。
⽹關在架構中的位置

二、 GateWay核⼼概念
Zuul1.x 阻塞式IO 2.x 基於Netty
Spring Cloud GateWay天⽣就是異步⾮阻塞的,基於Reactor模型
⼀個請求—>⽹關根據⼀定的條件匹配—匹配成功之后可以將請求轉發到指定的服務地址;⽽在這個過程中,我們可以進⾏⼀些⽐較具體的控制(限流、⽇志、⿊⽩名單)
- 路由(route): ⽹關最基礎的部分,也是⽹關⽐較基礎的⼯作單元。路由由⼀個ID、⼀個⽬標URL(最終路由到的地址)、⼀系列的斷⾔(匹配條件判斷)和Filter過濾器(精細化控制)組成。如果斷⾔為true,則匹配該路由。
- 斷⾔(predicates):參考了Java8中的斷⾔java.util.function.Predicate,開發⼈員可以匹配Http請求中的所有內容(包括請求頭、請求參數等)(類似於nginx中的location匹配⼀樣),如果斷⾔與請求相匹配則路由。
- 過濾器(fifilter):⼀個標准的Spring webFilter,使⽤過濾器,可以在請求之前或者之后執⾏業務邏輯。
三、GateWay⼯作過程
客戶端向Spring Cloud GateWay發出請求,然后在GateWay Handler Mapping中找到與請求相匹配的路由,將其發送到GateWay Web Handler;Handler再通過指定的過濾器鏈來將請求發送到我們實際的服務執⾏業務邏輯,然后返回。過濾器之間⽤虛線分開是因為過濾器可能會在發送代理請求之前(pre)或者之后(post)執⾏業務邏輯。
Filter在“pre”類型過濾器中可以做參數校驗、權限校驗、流量監控、⽇志輸出、協議轉換等,在“post”類型的過濾器中可以做響應內容、響應頭的修改、⽇志的輸出、流量監控等。
GateWay核⼼邏輯:路由轉發+執⾏過濾器鏈
四、應用
第一步、引入pom,注意使用的不是spring-mvc,只需要引入webflux即可
<!--GateWay ⽹關--> <dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <!--引⼊webflux--> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId> </dependency>
第二步、配置配置文件
1、時間點前匹配

spring:
cloud:
gateway:
routes:
- id: after_route
uri: http://ityouknow.com
predicates:
- Before=2018-01-20T06:06:06+08:00[Asia/Shanghai]
2、時間點后匹配

spring:
cloud:
gateway:
routes:
- id: time_route
uri: http://ityouknow.com
predicates:
- After=2018-01-20T06:06:06+08:00[Asia/Shanghai]
3、時間區間匹配

spring:
cloud:
gateway:
routes:
- id: after_route
uri: http://ityouknow.com
predicates:
- Between=2018-01-20T06:06:06+08:00[Asia/Shanghai], 2019-01-20T06:06:06+08:00[Asia/Shanghai]
4、指定Cookie正則匹配指定值

spring:
cloud:
gateway:
routes:
- id: cookie_route
uri: http://ityouknow.com
predicates:
- Cookie=ityouknow, kee.e
5、指定Header正則匹配指定值

spring:
cloud:
gateway:
routes:
- id: header_route
uri: http://ityouknow.com
predicates:
- Header=X-Request-Id, \d+
6、請求Host匹配指定值

spring:
cloud:
gateway:
routes:
- id: host_route
uri: http://ityouknow.com
predicates:
- Host=**.ityouknow.com
7、請求Method匹配指定請求⽅式

spring:
cloud:
gateway:
routes:
- id: method_route
uri: http://ityouknow.com
predicates:
- Method=GET
8、請求路徑正則匹配

spring:
cloud:
gateway:
routes:
- id: host_route
uri: http://ityouknow.com
predicates:
- Path=/foo/{segment}
9、請求包含某參數

spring:
cloud:
gateway:
routes:
- id: query_route
uri: http://ityouknow.com
predicates:
- Query=smile
10、請求包含某參數並且參數值匹配正則表達式

spring:
cloud:
gateway:
routes:
- id: query_route
uri: http://ityouknow.com
predicates:
- Query=keep, pu.
11、遠程地址IP匹配

spring:
cloud:
gateway:
routes:
- id: remoteaddr_route
uri: http://ityouknow.com
predicates:
- RemoteAddr=192.168.1.1/24
注意:如果是注冊中心配置,那需要uri更換為: lb://服務名,同時需要引入客戶端pom,和配置客戶端注冊中心配置。
五、過濾器
從過濾器⽣命周期(影響時機點)的⻆度來說,主要有兩個pre和post:
- pre:這種過濾器在請求被路由之前調⽤。我們可利⽤這種過濾器實現身份驗證、在集群中選擇 請求的微服務、記錄調試信息等。
- post:這種過濾器在路由到微服務以后執⾏。這種過濾器可⽤來為響應添加標准的 HTTPHeader、收集統計信息和指標、將響應從微服務發送給客戶端等。
從過濾器類型的⻆度,Spring Cloud GateWay的過濾器分為GateWayFilter和GlobalFilter兩種
- GateWayFilter 應⽤到單個路由路由上
- GlobalFilter全局過濾器、應⽤到所有的路由上。實現的時候只需要實現GlobalFilter接口即可,有時候添加Ordered接口,設置攔截器的優先級,數值越⼩,優先級越⾼
如Gateway Filter可以去掉url中的占位后轉發路由,⽐如
spring:
cloud:
gateway:
routes:
- id: service-user8080
uri: lb://service-user8080
predicates:
- Path=/api/user
filters:
- StripPrefix=1 #去掉path第一個路徑參數在進行轉發
1、GateWayFilter單個路由上
實現GateWayFilter 接口
package city.albert.filter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.cloud.gateway.filter.GatewayFilter; import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.core.Ordered; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.http.server.reactive.ServerHttpResponse; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; /** * @author niunafei * @function * @email niunafei0315@163.com * @date 2020/9/23 1:26 AM */ public class IpFilter implements GatewayFilter, Ordered { Logger logger = LoggerFactory.getLogger(IpFilter.class); @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { HttpHeaders httpHeaders = exchange.getResponse().getHeaders(); //返回數據格式 httpHeaders.setContentType(MediaType.APPLICATION_JSON); ServerHttpRequest request = exchange.getRequest(); ServerHttpResponse response = exchange.getResponse(); // 從request對象中獲取客戶端ip logger.info("攔截處理業務"); return chain.filter(exchange); } @Override public int getOrder() { return 0; } }
配置生效
package city.albert.config; import city.albert.filter.IpFilter; import org.springframework.cloud.gateway.route.RouteLocator; import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * @author niunafei * @function * @email niunafei0315@163.com * @date 2020/9/23 2:03 AM */ @Configuration public class GateWayConfig { @Bean public RouteLocator customerRouteLocator(RouteLocatorBuilder builder) { RouteLocator build = builder.routes() //設置攔截接口 .route(r -> r.path("/api/user/register/**") //去除路徑上第一個參數/api .filters(f -> f.stripPrefix(1) //自定義的filetr .filter(new IpFilter()) .addResponseHeader("X-Response-Default-Foo", "Default-Bar")) .uri("lb://lagou-service-user8080") .order(0) .id("lagou-service-user80801") ) .build(); return build; } }
2、全局生效
package city.albert.filter; import org.springframework.cloud.gateway.filter.GlobalFilter; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.annotation.Order; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.http.server.reactive.ServerHttpResponse; /** * @author niunafei * @function * @email niunafei0315@163.com * @date 2020/9/24 1:46 AM */ @Configuration public class AutoFilter {
@Bean @Order(10) public GlobalFilter b() { return (exchange, chain) -> { HttpHeaders httpHeaders = exchange.getResponse().getHeaders(); //返回數據格式 httpHeaders.setContentType(MediaType.APPLICATION_JSON); ServerHttpRequest request = exchange.getRequest(); ServerHttpResponse response = exchange.getResponse(); //業務邏輯 return chain.filter(exchange); }; } }
路由配置:https://blog.csdn.net/rain_web/article/details/102469745
過濾器:https://blog.csdn.net/lizhiqiang1217/article/details/90576228