天天看點

一文詳解springcloud中的重要元件 “網關” Gateway的前世今生

網關(GateWay)

第一代網關zuul 1.X

Netflix開源的網關,使用Java開發,基于Servlet架構建構,便于二次開發。因為基于Servlet内部延遲嚴重,并發場景不友好,一個線程隻能處理一次連接配接請求。

但由于 zuul 采取的是 servlet 2.5 阻塞IO,性能較低且 zuul2 遲遲未釋出,目前不再推薦使用。

spring 推出的 “GateWay” 網關元件

Spring Cloud Gateway 使用的Webflux中的reactor-netty響應式程式設計元件,底層使用了Netty通訊架構。

Yaml 配置:

路由(Route)是GateWay中最基本的元件之一,表示一個具體的路由資訊載體,主要由下面幾個部分組成:
  1. id:路由唯一辨別,差別于其他的route
  2. url: 路由指向的目的地URL,用戶端請求最終被轉發到的微服務
  3. order: 用于多個Route之間的排序,數值越小越靠前,比對優先級越高
  4. predicate:斷言的作用是進行條件判斷,隻有斷言為true,才執行路由
  5. filter: 過濾器用于修改請求和響應資訊
server:
  port: 9527

spring:
  application:
    name: 微服務名
  cloud:
    gateway:
      routes:
      - id: 類似資料庫主鍵字段,全局唯一即可
        # uri: http://localhost:8001        # 比對後提空服務的路由位址
        uri: lb://cloud-payment-service 	# 注冊中心中的服務名
        predicates: 
          - Path=/payment/get/**    # 斷言,路徑相比對的進行路由跳轉,controller請求位址

注冊中心配置...
           

作用:

  • 反向代理
  • 鑒權
  • 流量控制
  • 熔斷
  • 日志監控

三大核心概念

一. Route(路由)

路由是建構網關的基本子產品,它由 ID ,目标 URI ,一系列的斷言和過濾器組成,如果斷言為 true 則比對該路由。

二. Predicate(斷言)

參考的是 java 8的 java.util.function.Predicate 開發人員可以比對 HTTP 請求中的所有内容(例如請求頭或請求參數),如果請求與斷言相比對則進行路由。在 Yaml 檔案中配置在 Predicates 結點下

1) After:在某時間點之後才可以進行通路

// 擷取格式化時區時間的 Java 方法
public static void main(String[] args) {
	ZonedDateTime zbj = ZonedDateTime.now(); // 根據系統的預設時區擷取
    System.out.print(zbj);  // 2022-10-04T16:49:23.334+08:00[Asia/Shanghai]
}
           
# Yaml 中的配置
 cloud:
    gateway:
      routes:
        predicates: - After=2022-10-04T16:49:23.334+08:00[Asia/Shanghai]
           

2)Between、Before 時間同理

3)Cookie:攜帶 Cookie 才可以通路,以攜帶使用者名和zzyy字段為例

# Yaml 中的配置
 cloud:
    gateway:
      routes:
        predicates: 
          - Cookie=username,zzyy
           

4)Header:請求頭中攜帶指定字段

5)Host:請求需為指定主機(ip)

6)Method:請求需為指定請求類型(GET)

三. Filter(過濾)

指的是 Spring 架構中 GatewayFilter 的執行個體,使用過濾器,可以在請求被路由前或者之後對請求進行修改。

1) 生命周期 Only Two

pre:請求之前

post:請求之後

2) 種類 Only Two

GatewayFilter:單一網關過濾器

GlobalFilter:全局網關過濾器

3)自定義過濾器:

/**
 * 全局網關過濾器配置,以“請求頭”必須攜帶使用者名為例
 * Mono 相當于 MVC 中的 ModelAndView
 *
 * @Author: 魏一yi
 * @Date: 2022/10/4 14:58
 */
@Component
@Slf4j
public class MyLogGateWayFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        log.info("******come in MyLogGateWayFilter" + new Date());
        // exchange.getRequest() 擷取的對象類似于HttpServletRequest
        // 請求必須帶uname
        String uname = exchange.getRequest().getQueryParams().getFirst("uname");
        if(uname == null) {
            log.info("******使用者名為空,非法使用者");
            exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);
            return exchange.getResponse().setComplete();
        }
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        // 數字越小優先級越高
        return 0;
    }
}