簡介
SpringCloud Gateway是SpringCloud的一個全新項目,基於Spring5+springboot2+project Reactor等技術開發的網關,它旨在為微服務架構提供一中簡單有效的統一的Api路由管理方式,且基於Filter鏈的方式提供了網關基本的功能,如安全,監控,指標,限流。
Spring Cloud Gateway使用的webflux中的reactor-netty響應式編程組件,底層使用了Netty通訊框架。
GateWay具有如下特性:
- 基於Spring5+springboot2+project Reactor等技術構建。
- 可以對路由指定Predicate(斷言)和filter(過濾器)。
- 集成Hystrix的斷路器功能。
- 集成SpringCloud服務發現功能。
- 易於編寫的Predicate(斷言)和filter(過濾器);
- 請求限流功能。
- 支持路徑重寫。
三大核心概念
路由(Route)是構建網關的基本模塊,它由ID,目標URI,一系列斷言和過濾器組成,如果斷言為true則匹配該路由。
斷言(Predicate),開發人員可以匹配HTTP請求中的所有內容,例如請求頭或請求參數,如果請求與斷言相匹配則進行路由
過濾(Filter),指的是Spring框架中的GatewayFilter的實例,使用過濾器,可以在請求被路由前或者后對請求進行修改
官網截圖:
核心邏輯:路由轉發+執行過濾器鏈
Gateway環境搭建
yml配置方式
pom依賴:需要移除springboot的web場景啟動器,否則會報錯,無法啟動
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
配置文件yml,在配置文件中配置了網關
server:
port: 9527
spring:
application:
name: cloud-gateway
cloud:
gateway:
routes:
- id: payment_routh
uri: http://localhost:8001
predicates:
- Path=/payment/get/**
- id: payment_routh2
uri: http://localhost:8001
predicates:
- Path=/payment/create
eureka:
client:
#是否將自己注冊到Eureka Server 默認為true
register-with-eureka: true
#是否從EurekaServer抓取已有的注冊信息,默認為true,單節點無所謂,集群必須設置true才能配合ribbon做負載均衡
fetch-registry: true
service-url:
#設置eureka server交互的地址查詢服務和注冊服務都需要依賴這個地址
defaultZone: http://localhost:7001/eureka
instance:
hostname: cloud-gateway-service
然后我們通過9527端口就可以訪問服務了:
編碼方式配置
新寫一個Gateway配置類:
@Configuration
public class GatewayConfig {
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder routeLocatorBuilder){
RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes();
routes.route("path_route_wj",r->{
//意思是訪問localhost:9527/guonei,將會轉發到http://news.baidu.com/guonei
return r.path("/guonei").uri("http://news.baidu.com/guonei");
}).build();
return routes.build();
}
}
我們在瀏覽器輸入localhost:9527/guonei並訪問,觀察效果:
Gateway實現動態路由
yml配置
需要注意的是:uri的協議為lb,表示啟用Gateway的負載均衡功能.
lb://serverName是Spring cloud Gateway在微服務中自動為我們創建的負載均衡uri
spring:
application:
name: cloud-gateway
cloud:
gateway:
routes:
- id: payment_routh
#uri: http://localhost:8001
uri: lb://CLOUD-PAYMENT-SERVICE
predicates:
- Path=/payment/get/**
- id: payment_routh2
#uri: http://localhost:8001
uri: lb://CLOUD-PAYMENT-SERVICE
predicates:
- Path=/payment/create
discovery:
locator:
#開啟從注冊中心動態創建路由的功能,利用微服務名進行路由
enabled: true
常用的斷言
當我們啟動Gateway服務時,發現控制台打印了一串Predicate
官方文檔有詳細說明:https://docs.spring.io/spring-cloud-gateway/docs/2.2.5.RELEASE/reference/html/#gateway-request-predicates-factories
這里不做過多介紹。
filter
filter分為兩種,一個是GatewayFilter,一種是GlobalFilter。
GatewayFilter
沒啥好說的,官網寫的很清楚。https://docs.spring.io/spring-cloud-gateway/docs/2.2.5.RELEASE/reference/html/#gatewayfilter-factories
舉例:
spring:
application:
name: cloud-gateway
cloud:
gateway:
routes:
- id: payment_routh
#uri: http://localhost:8001
uri: lb://CLOUD-PAYMENT-SERVICE
predicates:
- Path=/payment/get/**
#- After=2020-09-06T21:57:48.289+08:00[Asia/Shanghai]
filters:
#過濾器工廠會在匹配的請求頭上加上一對請求頭,名稱為X-Request-red值是blue
- AddRequestHeader=X-Request-red, blue
自定義全局GlobalFilter:
需要實現兩個接口,GlobalFilter和Ordered。
@Slf4j
@Component
public class MyGlobalFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String name = exchange.getRequest().getQueryParams().getFirst("name");
if(StringUtils.isBlank(name)){
log.info("非法用戶");
exchange.getResponse().setStatusCode(HttpStatus.BAD_REQUEST);
return exchange.getResponse().setComplete();
}
return chain.filter(exchange);
}
@Override
public int getOrder() {
return 0;
}
}
運行效果: