08.SpringCloud Gateway (新一代閘道器)
阿新 • • 發佈:2021-01-01
1.概述
基本說明
官網上一代閘道器 zuulhttps://github.com/Netflix/zuul/wiki 當前gatewayhttps://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.1.RELEASE/reference/html/是什麼
一句話Spring Cloud Gateway 使用的Webflux中的reactor-netty響應式程式設計元件,底層使用了Netty通訊框架原始碼架構
能幹嘛
- 反向代理
- 鑑權
- 流量控制
- 熔斷
- 日誌監控
微服務架構中閘道器在哪裡有了Zuul了怎麼又出來了gateway
我們為什麼選擇Gatway?
- 1.neflix不太靠譜,zuul2.0一直跳票,遲遲不釋出
- 2.SpringCloud Gateway具有如下特性
- 3.SpringCloud Gateway與Zuul的區別
Zuul1.x模型
GateWay模型
WebFlux是什麼?說明
2.三大核心概念
Route(路由)
路由是構建閘道器的基本模組,它由ID,目標URI,一系列的斷言和過濾器組成,如果斷言為true則匹配該路由Predicate(斷言)
參考的是java8的java.util.function.Predicate開發人員可以匹配HTTP請求中的所有內容(例如請求頭或請求引數),如果請求與斷言相匹配則進行路由Filter(過濾)
指的是Spring框架中GatewayFilter的例項,使用過濾器,可以在請求被路由前或者之後對請求進行修改。總體
3.Gateway工作流程
- 路由轉發+執行過濾器鏈
4.入門配置
新建模組cloud-gateway-gateway9527pomyml<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>springcloud2020</artifactId> <groupId>com.chl.springcloud</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>cloud-gateway-gateway9527</artifactId> <dependencies> <!--新增gateway--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <dependency> <groupId>com.chl.springcloud</groupId> <artifactId>cloud-api-commons</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> </project>
server:
port: 9527
spring:
application:
name: cloud-gateway
cloud:
gateway:
discovery:
locator:
enabled: true #開啟從註冊中心動態建立路由的功能,利用微服務名進行路由
routes:
- id: payment_routh #路由的ID,沒有固定規則但要求唯一,建議配合服務名
uri: http://localhost:8001 #匹配後提供服務的路由地址
predicates:
- Path=/payment/get/** #斷言,路徑相匹配的進行路由
- id: payment_routh2
uri: http://localhost:8001 #匹配後提供服務的路由地址
predicates:
- Path=/payment/lb/** #斷言,路徑相匹配的進行路由
eureka:
instance:
hostname: cloud-gateway-service
client:
service-url:
register-with-eureka: true
fetch-registry: true
defaultZone: http://eureka7001.com:7001/eureka
主啟動類@SpringBootApplication
@EnableEurekaClient
public class GateWayMain9527 {
public static void main(String[] args) {
SpringApplication.run( GateWayMain9527.class,args);
}
}
9527閘道器如何做路由對映那???cloud-provider-payment8001看看controller的訪問地址 get個lb我們目前不想暴露8001埠,希望在8001外面套一層9527yml新增閘道器配置server:
port: 9527
spring:
application:
name: cloud-gateway
cloud:
gateway:
discovery:
locator:
enabled: true #開啟從註冊中心動態建立路由的功能,利用微服務名進行路由
routes:
- id: payment_routh #路由的ID,沒有固定規則但要求唯一,建議配合服務名
uri: http://localhost:8001 #匹配後提供服務的路由地址
predicates:
- Path=/payment/get/** #斷言,路徑相匹配的進行路由
- id: payment_routh2
uri: http://localhost:8001 #匹配後提供服務的路由地址
predicates:
- Path=/payment/lb/** #斷言,路徑相匹配的進行路由
eureka:
instance:
hostname: cloud-gateway-service
client:
service-url:
register-with-eureka: true
fetch-registry: true
defaultZone: http://eureka7001.com:7001/eureka
測試1.啟動70012.啟動8001 cloud-provider-payment80013.啟動9527閘道器4.訪問說明- 新增閘道器前
- 新增閘道器前
yml配置說明
Gateway閘道器路由有兩種配置方式在配置檔案yml中配置
見前面步驟程式碼中注入RouteLocator的Bean
官網案例百度國內新聞網址,需要外網http://news.baidu.com/guoji
自己寫一個測試下 百度新聞業務需求通過9527閘道器訪問到外網的百度新聞網址編碼 cloud-gateway-gateway9527實現業務新增配置bean
@Configuration
public class GateWayConfig {
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder routeLocatorBuilder) {
RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes();
routes.route("path_rote_atguigu", r -> r.path("/guonei").uri("http://news.baidu.com/guonei")).build();
return routes.build();
}
}
5.通過微服務名實現動態路由
預設情況下Gateway會根據註冊中心的服務列表,以註冊中心上微服務名為路徑建立動態路由進行轉發,從而實現動態路由的功能一個eureka7001+兩個服務提供者8001/8002yml配置
需要注意的是uri的協議為lb,表示啟用Gateway的負載均衡功能。lb://serviceName是spring cloud gateway在微服務中自動為我們建立的負載均衡uriserver:
port: 9527
spring:
application:
name: cloud-gateway
cloud:
gateway:
discovery:
locator:
enabled: true #開啟從註冊中心動態建立路由的功能,利用微服務名進行路由
routes:
- id: payment_routh #路由的ID,沒有固定規則但要求唯一,建議配合服務名
#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/lb/** #斷言,路徑相匹配的進行路由
eureka:
instance:
hostname: cloud-gateway-service
client:
service-url:
register-with-eureka: true
fetch-registry: true
defaultZone: http://eureka7001.com:7001/eureka
測試http://localhost:9527/payment/lb 8001/8002兩個埠切換6.Predicate的使用
是什麼
啟動我們的gatewat9527Route Predicate Factories這個是什麼東東?
常用的Route Predicate
1.After Route Predicateyml配置
#這些是常用的斷言,如果不符合,就返回404,找不到
- After=2020-03-08T10:59:34.102+08:00[Asia/Shanghai] 這個時間後面訪問才行
2.Before Route Predicate
- Before=2020-03-08T10:59:34.102+08:00[Asia/Shanghai]
3.Between Route Predicate
- Between=2020-03-08T10:59:34.102+08:00[Asia/Shanghai] , 2020-03-08T10:59:34.102+08:00[Asia/Shanghai]
4. Cookie Route Predicate不帶cookies訪問帶上cookies訪問 加入curl返回中文亂碼 https://blog.csdn.net/leedee/article/details/82685636
- Cookie=username,atguigu #並且Cookie是username=zhangshuai才能訪問
5. Header Route Predicate
6.Host Route Predicate
- Host=**.baidu.com
7.Method Route Predicate
- Method=GET
8.Path Route Predicate
9. Query Route Predicate
- Query=username, \d+ #要有引數名稱並且是正整數才能路由
10.小總結說白了,Predicate就是為了實現一組匹配規則,讓請求過來找到對應的Route進行處理
server:
port: 9527
spring:
application:
name: cloud-gateway
cloud:
gateway:
discovery:
locator:
enabled: true #開啟從註冊中心動態建立路由的功能,利用微服務名進行路由
routes:
- id: payment_routh #路由的ID,沒有固定規則但要求唯一,建議配合服務名
#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/lb/** #斷言,路徑相匹配的進行路由
#這些是常用的斷言,如果不符合,就返回404,找不到
#- After=2020-03-08T10:59:34.102+08:00[Asia/Shanghai] 這個時間後面訪問才行
#- Cookie=username,zhangshuai #並且Cookie是username=zhangshuai才能訪問
#- Header=X-Request-Id, \d+ #請求頭中要有X-Request-Id屬性並且值為整數的正則表示式
#- Host=**.atguigu.com #主機攜帶是這個才行
#- Method=GET #get 方法訪問
#- Query=username, \d+ #要有引數名稱並且是正整數才能
eureka:
instance:
hostname: cloud-gateway-service
client:
service-url:
register-with-eureka: true
fetch-registry: true
defaultZone: http://eureka7001.com:7001/eureka
7.Filter的使用
是什麼
Spring Cloud Gateway的Filter
生命週期 (2個)
- Pre 在業務邏輯之前
- Post 在業務邏輯之後
種類(2個)
- GatewayFilter 單一 gateway定義的,沒啥用
- GlobalFilter 全域性 都是用這個
常用的GatewayFilter (gateway定義作用不大)
AddRequestParameter自定義過濾器(自定義全域性GlobalFilter)
兩個主要介面介紹- GlobalFilter
Ordered
能幹嘛全域性日誌記錄統一閘道器鑑權
案例程式碼
/**
* 自定義全域性的filter Spring Cloud Gateway的Filter 沒啥用,還是自己自定義的好用
*/
@Component
@Slf4j
public class MyLogGateWayFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
log.info("*********come in MyLogGateWayFilter: "+new Date());
String uname = exchange.getRequest().getQueryParams().getFirst("uname");
//不成功,就直接返回去
if(StringUtils.isEmpty(uname)){
log.info("*****使用者名稱為Null 非法使用者,(┬_┬)");
exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);//給人家一個迴應
return exchange.getResponse().setComplete();
}
return chain.filter(exchange);
}
/**
* order是過濾器的執行順序,數字越小,執行順序越前
* @return
*/
@Override
public int getOrder() {
return 0;
}
}
測試啟動
正確http://localhost:9527/payment/lb?uname=z3