構建SpringCloud閘道器服務

2022-12-16 18:00:54

搭建閘道器

匯入maven包:

    <!--閘道器依賴-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-gateway</artifactId>
    </dependency>

    <!--服務發現依賴-->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>

他們的版本由父專案中的管理依賴提供:

    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-dependencies</artifactId>
        <version>Hoxton.SR10</version>
        <type>pom</type>
        <scope>import</scope>
    </dependency>

    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-alibaba-dependencies</artifactId>
        <version>2.2.8.RELEASE</version>
        <type>pom</type>
        <scope>import</scope>
    </dependency>

組態檔:

spring:
  application:
    name: gateway-api
  cloud:
    nacos:
      server-addr: localhost:8848   # 設定nacos
    gateway:
      routes:
        - id: user-service                # 路由的id,需要唯一
#          uri: http://127.0.0.1:8080     # 可直接指定服務地址,不會負載均衡
          uri: lb://userservice           # 使用服務名稱進行負載均衡
          predicates:                     # 斷言,制定路由規則
            - Path=/user/**               # 按照路徑進行匹配,需要以 /user/開頭
server:
  port: 9000

路由斷言工廠 Route Predict Factory

名稱 說明 範例
After 是某個時間點後的請求 - After=2037-01-20T17:42:47.789-07:00[America/Denver]
Before 是某個時間點之前的請求 - Before=2031-04-13T15:14:47.433+08:00[Asia/Shanghai]
Between 是某兩個時間點之前的請求 - Between=2037-01-20T17:42:47.789-07:00[America/Denver], 2037-01-21T17:42:47.789-07:00[America/Denver]
Cookie 請求必須包含某些cookie - Cookie=chocolate, ch.p
Header 請求必須包含某些header - Header=X-Request-Id, \d+
Host 請求必須是存取某個host(域名) - Host=**.somehost.org,**.anotherhost.org
Method 請求方式必須是指定方式 - Method=GET,POST
Path 請求路徑必須符合指定規則 - Path=/red/{segment},/blue/**
Query 請求引數必須包含指定引數 - Query=name, Jack或者- Query=name
RemoteAddr 請求者的ip必須是指定範圍 - RemoteAddr=192.168.1.1/24
Weight 權重處理 ``

路由過濾器 GatewayFilter

有31中不同的路由過濾器工廠(GatewayFilterFactory)。 Spring Cloud 提供了多種閘道器過濾器工廠(GatewayFilterFactory):閘道器過濾器工廠。 常見的過濾器工廠如下:

名稱 說明
AddRequestHeader 給當前請求新增一個請求頭
AddRequestParameter 給當前請求新增一個引數
RemoveRequestHeader 移除請求中的一個請求頭
RemoveRequestParameter 移除請求中的一個引數
AddResponseHeader 給響應結果中新增一個響應頭
RemoveResponseHeader 從響應結果中移除有一個響應頭
RequestRateLimiter 限制請求的流量
spring:
  cloud:
    gateway:
      routes:
      - id: add_request_header_route
        uri: https://example.org
        filters:
        - AddRequestHeader=X-Request-red, blue      # 將在header中新增 X-Request-red=blue

預設過濾器

對所有路由生效,需要寫到 default-filters 中。

spring:
  application:
    name: gateway-api
  cloud:
    nacos:
      server-addr: localhost:8848   # 設定nacos
    gateway:
      routes:
        - id: user-service                # 路由的id,需要唯一
#          uri: http://127.0.0.1:8080     # 可直接指定服務地址,不會負載均衡
          uri: lb://userservice           # 使用服務名稱進行負載均衡
          predicates:                     # 斷言,制定路由規則
            - Path=/user/**               # 按照路徑進行匹配,需要以 /user/開頭
          filters:
            - AddRequestParameter=name, tom     # 只對user-service生效
        - id: order-service
          uri: lb://orderservice
          predicates:
            - Path=/order/**
    
      # 預設設定對上面的所有routes生效
      default-filters:
        - AddRequestParameter=age,20

全域性過濾器

GlobalFilter 的邏輯需要自己寫程式碼實現,需要實現 GlobalFilter 介面。 使用 @Order 或者 Ordered 介面制定過濾器的優先順序。(Order越小,優先順序越高,越先執行)

  • 路由過濾器defaultFilterorderSpring指定,預設是按照宣告順序從1遞增
  • 當過濾器的order值一樣時,會按照 defaultFilter > 路由過濾器 > GlobalFilter 的順序執行
//@Order(-1)
@Component
public class GatewayGlobalFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();
        
        MultiValueMap<String, String> queryParams = request.getQueryParams();
        String username = queryParams.getFirst("username");
        if("admin".equals(username)){
            // 放行
            return chain.filter(exchange);
        }

        // 新增 401 錯誤
        response.setStatusCode(HttpStatus.UNAUTHORIZED);
        return response.setComplete();
    }

    @Override
    public int getOrder() {
        return -1;
    }
}

跨域問題處理

域名不同、埠不同時會發生跨域問題。需要是瀏覽器發起的請求,如果是各個服務之間的互相轉發並不會涉及到跨域問題。

新增以下設定開放針對某些網站的跨域請求:

spring:
  application:
    name: gateway-api
  cloud:
    nacos:
      server-addr: localhost:8848   # 設定nacos
    gateway:
      # 跨域處理
      globalcors:
        add-to-simple-url-handler-mapping: true     # 不攔截options請求
        cors-configurations:
          '[/**]':
            allowed-origins:                        # 允許跨域的網站
              - "http://localhost:8090"
            allowed-methods:
              - "GET"
              - "POST"
              - "DELETE"
              - "PUT"
              - "OPTIONS"
            allowed-headers: "*"                    # 允許請求頭中攜帶的頭資訊
            allow-credentials : true                # 允許攜帶cookie
            maxAge: 360000                          # 本次跨域檢測的有效期