Spring Cloud Gateway is an intelligent and programmable router based on Project Reactor.html
在雲架構中運行着衆多客戶端和服務端,API網關的存在提供了保護和路由消息,隱藏服務,限制負載等等功能。git
Spring Cloud Gateway
提供了一個在Spring生態系統之上構建的API網關,包括:Spring 5,Spring Boot 2和Project Reactor。 Spring Cloud Gateway旨在提供一種簡單而有效的方法來對API進行路由,提供精準控制。web
爲了提高網關的性能,Spring Cloud Gateway是基於WebFlux框架實現的,而WebFlux框架底層則使用了高性能的Reactor模式通訊框架Netty。正則表達式
SpringCloud Gateway的目標是:提供統一的路由方式且基於FilterChain的方式提供網關基本的功能,例如:安全,監控/指標,彈性,限流等等。spring
路由:路由是構建網關的基本模塊,它由ID,目標URI,一系列的斷言Predicates和過濾器Filters組成,若是斷言爲true,則匹配該路由。shell
斷言:參考Java8的java.util.function.Predicate,開發人員能夠匹配HTTP請求中的全部內容,例如請求頭或請求參數,若是請求與斷言相匹配則進行路由。安全
過濾:Spring框架中GatewayFilter的實例,使用過濾器,能夠載請求被路由前或者後對請求進行修改。cookie
一個web請求,經過一些匹配條件,定位到真正的服務節點,在這個轉發的過程當中,進行一些精細化的控制。架構
- predicate就是匹配條件
- filter就是攔截器
- predicate + filter + 目標uri實現路由route
下圖整體上描述了Spring Cloud Gateway的工做流程:
客戶端向Spring Cloud Gateway發出請求。
若是Gateway Handler Mapping肯定請求與路由匹配,則將其發送到Gateway Web Handler。
Handler經過指定的過濾器鏈將請求發送到咱們實際的服務執行業務邏輯,而後返回。
過濾器由虛線分隔的緣由是,過濾器能夠在發送代理請求以前或以後執行邏輯。
核心:路由轉發+過濾器鏈
引入spring-cloud-starter-gateway
核心組件,其次,這個服務自己也許要註冊進Eureka,所以引入spring-cloud-starter-netflix-eureka-client
。
<!--gateway--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <!--eureka-client--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency>
注意:不能引入spring-boot-starter-web依賴
server: port: 9527 spring: application: name: cloud-gateway cloud: gateway: discovery: locator: enabled: true #開啓從註冊中心動態建立路由的功能,利用微服務名進行路由 routes: - id: payment_routh #payment_route #路由的ID,沒有固定規則但要求惟一,建議配合服務名 uri: http://localhost:8001 #匹配後提供服務的路由地址 predicates: - Path=/payment/** # 斷言,路徑相匹配的進行路由 - id: payment_routh2 #payment_route #路由的ID,沒有固定規則但要求惟一,建議配合服務名 uri: http://localhost:8001 #匹配後提供服務的路由地址 predicates: - Path=/payment/lb/** # 斷言,路徑相匹配的進行路由 #- After=2020-02-21T15:51:37.485+08:00[Asia/Shanghai] #- Cookie=username,zzyy #- Header=X-Request-Id, \d+ # 請求頭要有X-Request-Id屬性而且值爲整數的正則表達式 eureka: instance: hostname: cloud-gateway-service instance-id: gateway9527 prefer-ip-address: true client: #服務提供者provider註冊進eureka服務列表內 service-url: register-with-eureka: true fetch-registry: true defaultZone: http://eureka7001.com:7001/eureka
這段yml配置內容比較多:
@SpringBootApplication @EnableEurekaClient public class GatewayMain9527 { public static void main(String[] args) { SpringApplication.run(GatewayMain9527.class, args); } }
依次啓動7001註冊中心,8001服務和9527網關服務,訪問localhost:7001/
因爲網關的存在,咱們能夠訪問:http://localhost:9527/payment/1
,可以成功訪問到8001服務的接口。
咱們以前已經配置過了:
spring: application: name: cloud-gateway cloud: gateway: discovery: locator: enabled: true #開啓從註冊中心動態建立路由的功能,利用微服務名進行路由 routes: - id: payment_routh #payment_route #路由的ID,沒有固定規則但要求惟一,建議配合服務名 uri: http://localhost:8001 #匹配後提供服務的路由地址 predicates: - Path=/payment/** # 斷言,路徑相匹配的進行路由
@Configuration public class GatewayConfig { @Bean public RouteLocator customRouteLocator(RouteLocatorBuilder routeLocatorBuilder) { RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes(); routes.route("path_route", r -> r.path("/guonei") .uri("http://news.baidu.com/guonei")).build(); return routes.build(); } }
原理:默認狀況下Gateway會根據註冊中心註冊的服務列表,以註冊中心上微服務名爲路徑建立動態動態路由進行轉發,從而實現動態路由的功能。
server: port: 9527 spring: application: name: cloud-gateway cloud: gateway: discovery: locator: enabled: true #開啓從註冊中心動態建立路由的功能,利用微服務名進行路由 routes: - id: payment_routh #payment_route #路由的ID,沒有固定規則但要求惟一,建議配合服務名 uri: lb://cloud-payment-service #匹配後提供服務的路由地址 predicates: - Path=/payment/** # 斷言,路徑相匹配的進行路由 - id: payment_routh2 #payment_route #路由的ID,沒有固定規則但要求惟一,建議配合服務名 uri: lb://cloud-payment-service #匹配後提供服務的路由地址 predicates: - Path=/payment/lb/** # 斷言,路徑相匹配的進行路由 #- After=2020-02-21T15:51:37.485+08:00[Asia/Shanghai] #- Cookie=username,zzyy #- Header=X-Request-Id, \d+ # 請求頭要有X-Request-Id屬性而且值爲整數的正則表達式
訪問localhost:9527/payment/lb
,根據獲取到的服務的路由地址,動態切換路由。
Spring Cloud Gateway matches routes as part of the Spring WebFlux
HandlerMapping
infrastructure. Spring Cloud Gateway includes many built-in route predicate factories. All of these predicates match on different attributes of the HTTP request. You can combine multiple route predicate factories with logicaland
statements.
SpringCloud Gateway將路由匹配做爲Spring WebFlux HandlerMapping基礎架構的一部分。
Spring Cloud Gateway包括許多內置的Route Predicate工廠,全部這些Predicate都與HTTP請求的不一樣屬性匹配,多個RoutePredicate工廠能夠進行組合。
SpringCloud Gateway建立Route對象時,使用RoutePredicateFactory建立Predicate對象,Predicate對象能夠賦值給Route。
你能夠經過and邏輯組合多種route predicate factories。舉幾個例子:
spring: application: name: cloud-gateway cloud: gateway: discovery: locator: enabled: true #開啓從註冊中心動態建立路由的功能,利用微服務名進行路由 routes: - id: payment_routh #payment_route #路由的ID,沒有固定規則但要求惟一,建議配合服務名 #uri: http://localhost:8001 #匹配後提供服務的路由地址 uri: lb://cloud-payment-service #匹配後提供服務的路由地址 predicates: - Path=/payment/** # 斷言,路徑相匹配的進行路由 - Before=2020-11-26T21:27:26.256+08:00[Asia/Shanghai] - id: payment_routh2 #payment_route #路由的ID,沒有固定規則但要求惟一,建議配合服務名 #uri: http://localhost:8001 #匹配後提供服務的路由地址 uri: lb://cloud-payment-service #匹配後提供服務的路由地址 predicates: - Path=/payment/lb/** # 斷言,路徑相匹配的進行路由 - After=2020-11-25T22:42:23.608+08:00[Asia/Shanghai] - Cookie=username,hyh
cookie能夠經過curl命令測試:
$ curl http://localhost:9527/payment/lb --cookie "username=hyh"
header測試:
$ http://localhost:9527/payment/lb --H "X-Request-Id:123"
predicates: - Before=2017-01-20T17:42:47.789-07:00[America/Denver] # 在..以前能夠匹配 - After=2017-01-20T17:42:47.789-07:00[America/Denver] # 在..以後能夠匹配 - Between=xxx,xxx # 在..之間能夠匹配 - Cookie=chocolate, ch.p # 帶cookie - Header=X-Request-Id, \d+ # 規定header - Host=**.somehost.org,**.anotherhost.org # 規定host - Method=GET,POST # 規定請求方法 - Path=/red/{segment},/blue/{segment} # 規定請求路徑 - Query=green # 規定請求參數 - RemoteAddr=192.168.1.1/24 # 規定remoteAddr # 將80%的流量轉到weighthigh.org,20%轉到weightlow.org - id: weight_high uri: https://weighthigh.org predicates: - Weight=group1, 8 - id: weight_low uri: https://weightlow.org predicates: - Weight=group1, 2
Route filters allow the modification of the incoming HTTP request or outgoing HTTP response in some manner. Route filters are scoped to a particular route. Spring Cloud Gateway includes many built-in GatewayFilter Factories.
路由過濾器容許以某種方式修改傳入的HTTP請求或傳出的HTTP響應。
路由過濾器適用於特定路由。
Spring Cloud Gateway包括許多內置的GatewayFilter工廠,感興趣能夠查看官網。
@Slf4j @Component public class MyGlobalFilter implements GlobalFilter, Ordered { @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { log.info("================come in myGlobalFilter" + new Date() + "=================="); String name = exchange.getRequest().getQueryParams().getFirst("name"); if (name == null || name.length() == 0) { log.info("=======================非法用戶,name爲null=============================="); exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE); return exchange.getResponse().setComplete(); } log.info("=======welcome! name = " + name + "======================="); return chain.filter(exchange); } @Override public int getOrder() { return -1; } }
本系列文章爲《尚硅谷SpringCloud教程》的學習筆記【版本稍微有些不一樣,後續遇到bug再作相關說明】,主要作一個長期的記錄,爲之後學習的同窗提供示例,代碼同步更新到Gitee:https://gitee.com/tqbx/spring-cloud-learning,而且以標籤的形式詳細區分每一個步驟,這個系列文章也會同步更新。