14.服務閘道器Zuul和Gateway
阿新 • • 發佈:2022-05-29
zuul分為兩個版本,zuul1已經提更,zuul2還沒開發好!
重點學習gateway!
cloud全家桶中有個很重要的元件就是網管,在1.x版本中採用的時Zuul閘道器
但在2.x版本中,zuul的升級一致跳票,SpringCloud最後自己研發了一個閘道器代替Zuul
這就是Spring Cloud Gateway,一句話:gateway時原zuul1.x版的替代!
gateway是基於非同步非阻塞模型上進行開發的,效能方面不需要擔心!
zuul1是基於Servlet2.5使用阻塞架構上開發的,它不支援任何長連線(如WebSocket)
發現上述有問題: 1.服務提供端一般都是以叢集形式部署,在配置檔案中寫死ip和埠不好 2.如何在網管處實現負載均衡呢?GateWay的三大核心概念: 1.Route(路由):路由是構建閘道器的基本模組,它是由ID,目標URI,一系列的斷言和過濾器組成,如果斷言為true則匹配該路由 2.Predicate(斷言):開發人員可以匹配HTTP請求中的所有內容(例如請求頭或者請求引數),如果請求和斷言相匹配則進行路由 3.Filter(過濾):指的是spring框架中GatewayFiletr例項,使用過濾器,可以在請求被路由前或者後對請求進行修改! Gateway的核心邏輯就是:路由轉發和執行過濾器鏈 程式碼構建: gateway是一個單獨的專案,去給其他cloud專案訪問加上一層閘道器 1.pom檔案中的內容: <dependencies> 重點:gateway的jar包 <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> <!--一般基礎通用配置--> <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> <dependency> <groupId>cn.com.springcloud</groupId> <artifactId>common</artifactId> <version>${project.version}</version> </dependency> </dependencies> 2.springboot啟動類: @SpringBootApplication @EnableEurekaClient public class SpringBootGateway9527 { public static void main(String[] args) { SpringApplication.run(SpringBootGateway9527.class,args); } } 3.springboot的配置檔案寫法: server: port: 9527 eureka: client: #表示是否將自己註冊進EurekaServer預設為true。 register-with-eureka: true #是否從EurekaServer抓取已有的註冊資訊,預設為true。單節點無所謂,叢集必須設定為true才能配合ribbon使用負載均衡 fetchRegistry: true service-url: #單機版 #defaultZone: http://localhost:7001/eureka # 叢集版 defaultZone: http://eureka7001:7001/eureka,http://eureka7002:7002/eureka instance: instance-id: cloud-gateway-service9527 prefer-ip-address: true spring: application: name: cloud-gateway-service #重點 cloud: gateway: routes: - id: producer_queryUserById #路由的id,沒有固定規則但要求唯一,建議符合服務名稱 uri: http://localhost:8001 #匹配後提供服務的路由地址 predicates: - Path=/producer/queryUserById/** #斷言,服務端路徑匹配的進行路由 - id: producer_getCurrentThread uri: http://localhost:8001 predicates: - Path=/producer/getCurrentThread/** 上述配置的意思是: 當訪問的是gateway:http://localhost:9527/producer/queryUserById/7時, 滿足上述的斷言,此時會路由到http://localhost:8001//producer/queryUserById/7(路徑拼接) 如果嫌需要給服務專案的每個請求方法都加上閘道器,可以這麼寫: spring: application: name: cloud-gateway-service cloud: gateway: routes: - id: producer_queryUserById #路由的id,沒有固定規則但要求唯一,建議符合服務名稱 uri: http://localhost:8001 #匹配後提供服務的路由地址 predicates: 重點:服務專案的每個請求前都設定一個公共的路徑/producer,然後根據此進行配置,這樣就不需要單獨每個方法都配置了! - Path=/producer/** #斷言,服務端路徑匹配的進行路由
在application.yam中配置如下: server: port: 9527 eureka: client: #表示是否將自己註冊進EurekaServer預設為true。 register-with-eureka: true #是否從EurekaServer抓取已有的註冊資訊,預設為true。單節點無所謂,叢集必須設定為true才能配合ribbon使用負載均衡 fetchRegistry: true service-url: #單機版 #defaultZone: http://localhost:7001/eureka # 叢集版 defaultZone: http://eureka7001:7001/eureka,http://eureka7002:7002/eureka instance: instance-id: cloud-gateway-service9527 prefer-ip-address: true spring: application: name: cloud-gateway-service cloud: gateway: discovery: locator: #重點:加上該配置 enabled: true #開啟從註冊中心動態建立路由的功能,利用微服務名稱進行路由 routes: - id: producer_queryUserById #路由的id,沒有固定規則但要求唯一,建議符合服務名稱 #重點2:這裡本身寫服務提供端的地址,此時可以寫服務註冊在eureka註冊中心的名稱,lb:loadbalance(輪訓的負載均衡) uri: lb://CLOUD-PROVIDER #匹配後提供服務的路由地址 predicates: - Path=/getPerson/** #斷言,服務端路徑匹配的進行路由 - id: producer_getCurrentThread uri: lb://CLOUD-PROVIDER predicates: - Path=/producer/timesleep/** 測試: 此時若通過http://localhost:9527/getPerson/10007去訪問時,發現是輪訓的去訪問服務叢集!
predicates講解
參考地址:https://blog.csdn.net/u012367513/article/details/86356708 predicates(斷言):可以加很多種規則,目的就是讓請求過來找到合適的Route進行處理 1. After Route Predicate Factory:使用的是時間作為匹配規則,只要當前時間大於設定時間,路由才會匹配請求。 spring: cloud: gateway: routes: - id: after_route uri: http://www.google.com predicates: - After=2018-12-25T14:33:47.789+08:00 這個路由規則會在東8區的2018-12-25 14:33:47後,將請求都轉跳到google。 2.Before Route Predicate Factory:使用時間作為匹配規則,只要當前時間小於設定時間,路由才會匹配請求。 spring: cloud: gateway: routes: - id: before_route uri: http://www.google.com predicates: - Before=2018-12-25T14:33:47.789+08:00 這個路由規則會在東8區的2018-12-25 14:33:47前,將請求都轉跳到google。 3.Between Route Predicate Factory:使用兩個時間作為匹配規則,只要當前時間大於第一個設定時間,並小於第二個設定時間,路由才會匹配請求。 spring: cloud: gateway: routes: - id: between_route uri: http://www.google.com predicates: - Between=2018-12-25T14:33:47.789+08:00, 2018-12-26T14:33:47.789+08:00 這個路由規則會在東8區的2018-12-25 14:33:47到2018-12-26 14:33:47之間,將請求都轉跳到google。 4. Cookie Route Predicate Factory:使用的是cookie名字和正則表示式的value作為兩個輸入引數,請求的cookie需要匹配cookie名和符合其中value的正則。 spring: cloud: gateway: routes: - id: cookie_route uri: http://www.google.com predicates: - Cookie=cookiename, cookievalue 路由匹配請求存在cookie名為cookiename,cookie內容匹配cookievalue的,將請求轉發到google。 5.Header Route Predicate Factory:與Cookie Route Predicate Factory類似,也是兩個引數,一個header的name,一個是正則匹配的value。 spring: cloud: gateway: routes: - id: header_route uri: http://www.google.com predicates: - Header=X-Request-Id, \d+ 路由匹配存在名為X-Request-Id,內容為數字的header的請求,將請求轉發到google。 6. Host Route Predicate Factory:使用的是host的列表作為引數,host使用Ant style匹配。 spring: cloud: gateway: routes: - id: host_route uri: http://www.google.com predicates: - Host=**.somehost.org,**.anotherhost.org 路由會匹配Host諸如:www.somehost.org 或 beta.somehost.org或www.anotherhost.org等請求。 7. Method Route Predicate Factory:是通過HTTP的method來匹配路由。 spring: cloud: gateway: routes: - id: method_route uri: http://www.google.com predicates: - Method=GET 路由會匹配到所有GET方法的請求。 8.Path Route Predicate Factory:使用的是path列表作為引數,使用Spring的PathMatcher匹配path,可以設定可選變數。 spring: cloud: gateway: routes: - id: host_route uri: http://www.google.com predicates: - Path=/foo/{segment},/bar/{segment} 上面路由可以匹配諸如:/foo/1 或 /foo/bar 或 /bar/baz等 其中的segment變數可以通過下面方式獲取: PathMatchInfo variables = exchange.getAttribute(URI_TEMPLATE_VARIABLES_ATTRIBUTE); Map<String, String> uriVariables = variables.getUriVariables(); String segment = uriVariables.get("segment"); 在後續的GatewayFilter Factories就可以做對應的操作了。 9.Query Route Predicate Factory:可以通過一個或兩個引數來匹配路由,一個是查詢的name,一個是查詢的正則value。 spring: cloud: gateway: routes: - id: query_route uri: http://www.google.com predicates: - Query=baz 路由會匹配所有包含baz查詢引數的請求。 spring: cloud: gateway: routes: - id: query_route uri: http://www.google.com predicates: - Query=foo, ba. 路由會匹配所有包含baz,並且baz的內容為諸如:bar或baz等符合ba.正則規則的請求。 10.RemoteAddr Route Predicate Factory:通過無類別域間路由(IPv4 or IPv6)列表匹配路由。 spring: cloud: gateway: routes: - id: remoteaddr_route uri: http://www.google.com predicates: - RemoteAddr=192.168.1.1/24 上面路由就會匹配RemoteAddr諸如192.168.1.10等請求。 11.Modifying the way remote addresses are resolved
Filter:過濾器
分類:
1.GatewayFilter
2.GlobalFilter
3.上述兩種的配置種太多,不如自己去實現程式碼來的方便
自定義的過濾器:
1.兩個主要的介面:
2.能幹嘛;
2.1全域性日誌記錄
2.2統一通關鑑權
樣例:建立自己的過濾器,加上@Component註解將其載入到容器中
@Component
@Slf4j
重點1:實現兩個介面:GlobalFilter和Ordered(用來控制該過濾器的執行順序,數值越小,越先執行!)
public class MyLogGateWayFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
重點2:hutool工具包的使用
log.info("*****gateWay的自定義過濾器:時間:"+ DateUtil.formatDateTime(new Date()));
重點3:獲取請求中的uname屬性值
String uanme=exchange.getRequest().getQueryParams().getFirst("uname");
if(uanme == null){
log.info("********使用者名稱為null,非法使用者,/(ㄒoㄒ)/~~");
重點4:設定返回的狀態碼:406
exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);
重點5:表示訊息處理完畢,可以進行結束
return exchange.getResponse().setComplete();
}
重點6:該該條過濾的ServerWebExchange 物件傳入到過濾鏈中的下一個過濾環節!
return chain.filter(exchange);
}
重點7:過濾的執行順序,數字越小,越先執行!
@Override
public int getOrder() {
return 0;
}
}