当前位置:网站首页>微服務入門:Gateway網關

微服務入門:Gateway網關

2022-07-04 08:37:00 mm天天寫bug

微服務入門:Gateway網關

一、為什麼需要網關

Gateway相當於微服務中的守門員,它可以幫助我們完成:

  • 身份驗證和權限校驗
  • 服務路由和負載均衡
  • 請求限流

在這裏插入圖片描述

在SpringCloud中網關的實現有兩種方式:

  • gateway
  • zuul

主要使用gateway,因為Zuul是基於Servlet實現的,屬於阻塞式編程。

而SpringCloudGateway則是基於Spring5中提供的WebFlux,屬於響應式編程的實現,具備更好的性能


二、搭建網關服務

搭建網關服務,首先我們需要創建一個Maven模塊,建議選擇一個空模塊,不要用SpringBoot模板創建,不然會出現未知的錯誤(因為我第一次就是用SpringBoot模板創建的,然後出現了依賴導入不了的Bug)

創建完一個空的Maven項目之後,在pom.xml導入以下依賴

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

<!--引入gateway 網關-->
<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>

導入依賴後,手動添加GatewayApplication以及yml文件

在這裏插入圖片描述

@SpringBootApplication
public class GatewayApplication {
    public static void main(String[] args) {
        SpringApplication.run(GatewayApplication.class,args);
    }
}

然後在yml配置網關和路由

路由配置包括:

1.路由id:路由的唯一標示

2.路由目標(uri):路由的目標地址,http代錶固定地址,lb代錶根據服務名負載均衡

3.路由斷言(predicates):判斷路由的規則,

4.路由過濾器(filters):對請求或響應做處理

server:
  port: 10010
spring:
  application:
    name: gateway #服務名稱
  cloud:
    nacos:
      server-addr: localhost:8848 #nacos地址
    gateway:
      routes:
        - id: user-service # 路由id,自定義,只要唯一即可
          uri: lb://userservice # 路由的目標地址 lb就是負載均衡,後面跟服務名稱
          predicates: # 路由斷言,也就是判斷請求是否符合路由規則的條件
            - Path=/user/** # 這個是按照路徑匹配,只要以/user/開頭就符合要求
        - id: order-service
          uri: lb://orderservice
          predicates:
            - Path=/order/**

如果我們向添加多個服務,那麼則多寫幾個id即可

這樣就完成了網關的搭建

在這裏插入圖片描述

搭建完成的網關就會起到了守門員的作用,當我們請求/user/**這個url的時候,就會根據理由規則判斷是哪一個服務,然後進行負載均衡接著發送請求。

比如我們訪問網關http://localhost:10010/user/1,然後符合/user/**規則,請求轉發到uri:http://userservice/user/1,得到了結果:

在這裏插入圖片描述


三、路由斷言工廠

在上述的yml配置中,可以看到有一個predicates

這個predicates就是路由斷言,判斷請求是否符合規則,符合規則則轉發到路由目的地

在配置文件中寫的斷言規則只是字符串,這些字符串會被Predicate Factory讀取並處理,轉變為路由判斷的條件

例如:Path=/user/**是按照路徑匹配,這個規則是由org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory類來處理的

像這樣的斷言工廠在SpringCloudGateway還有十幾個

名稱說明示例
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是網關中提供的一種過濾器,可以對進入網關請求和微服務返回的響應做處理

在這裏插入圖片描述

Spring提供了31中不同的路由過濾工廠,這裏提供幾種展示

名稱說明
AddRequestHeader給當前請求添加一個請求頭
RemoveRequestHeader移除請求中的一個請求頭
AddResponseHeader給響應結果中添加一個響應頭
RemoveResponseHeader從響應結果中移除有一個響應頭
RequestRateLimiter限制請求的流量

4.1 添加過濾器GatewayFilter

在Gateway模塊的yml添加過濾器

下面的案例就是添加請求頭

server:
  port: 10010
spring:
  application:
    name: gateway #服務名稱
  cloud:
    nacos:
      server-addr: localhost:8848 #nacos地址
    gateway:
      routes:
        - id: user-service # 路由id,自定義,只要唯一即可
          uri: lb://userservice # 路由的目標地址 lb就是負載均衡,後面跟服務名稱
          predicates: # 路由斷言,也就是判斷請求是否符合路由規則的條件
            - Path=/user/** # 這個是按照路徑匹配,只要以/user/開頭就符合要求
          filters: #過濾器
            - AddRequestHeader=Truth,Itcast is freaking aowsome!
        - id: order-service
          uri: lb://orderservice
          predicates:
            - Path=/order/**
      default-filters: # 默認過濾器,會對所有的路由請求都生效
        - AddRequestHeader=Truth,Itcast is freaking aowsome!

filters是局部過濾器,如上代碼所示,其只在user-service起作用

而default-filters是默認過濾器,在路由中的所有服務都起作用


4.2 全局過濾器GlobalFilter

全局過濾器的作用也是處理一切進入網關的請求和微服務響應,與GatewayFilter的作用一樣。

區別在於GatewayFilter通過配置定義,處理邏輯是固定的。而GlobalFilter的邏輯需要自己寫代碼實現。

定義方式是實現GlobalFilter接口。

首先我們在Gateway模塊添加一個Java類

// @Order(-1)
@Component
public class AuthorizeFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //1.獲取請求參數
        ServerHttpRequest request = exchange.getRequest();
        //2.獲取所有的參數
        MultiValueMap<String, String> queryParams = request.getQueryParams();
        //3.獲取Authorization參數
        String first = queryParams.getFirst("Authorization");
        //4.判斷參數是否是admin
        if ("admin".equals(first)){
            //5.是則放行
            return chain.filter(exchange);
        }
        //6.設置狀態碼
        exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
        //7.攔截請求
        return exchange.getResponse().setComplete();
    }

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

這個類的主要是作用是實現了GlobalFilter,對發送來的請求判斷Authorization參數是否為admin,如果是則放行,不是則設置狀態碼為401然後攔截請求

注意的是,這個攔截器需要用@Component注解給Spring托管

並且我們可以設置該攔截器的優先級(數字越小,優先級越大)

例如使用@Order(-1)設置優先級

也可以選擇實現Ordered接口的getOrder方法,返回一個數字,那個數字就是决定攔截器的優先級的


4.3 過濾器的執行順序

請求進入網關會碰到三類過濾器:當前路由的過濾器、DefaultFilter、GlobalFilter

請求路由後,會將當前路由過濾器和DefaultFilter、GlobalFilter,合並到一個過濾器鏈(集合)中,排序後依次執行每個過濾器

在這裏插入圖片描述

  • 每一個過濾器都必須指定一個int類型的order值,order值越小,優先級越高,執行順序越靠前
  • GlobalFilter通過實現Ordered接口,或者添加@Order注解來指定order值,由我們自己指定
  • 路由過濾器和defaultFilter的order由Spring指定,默認是按照聲明順序從1遞增。
  • 當過濾器的order值一樣時,會按照 defaultFilter > 路由過濾器 > GlobalFilter的順序執行。

五、跨域問題解决

什麼是跨域問題呢?

在之前開發SpringBoot+vue的項目的時候,如果沒有進行跨域問題的解决,我用axios發送請求給後端就會報錯

這是因為前端和後端的端口號不一樣,瀏覽器禁止請求的發起者與服務端發生跨域ajax請求

所以跨域問題就是 瀏覽器禁止請求的發起者與服務端發生跨域ajax請求,請求被瀏覽器攔截的問題

除了端口不一樣會產生跨域問題之外,如果域名不一樣,也會導致跨域問題

解决方案:CORS

server:
  port: 10010
spring:
  application:
    name: gateway #服務名稱
  cloud:
    nacos:
      server-addr: localhost:8848 #nacos地址
    gateway:
      globalcors: # 全局的跨域處理
        add-to-simple-url-handler-mapping: true # 解决options請求被攔截問題
        corsConfigurations:
          '[/**]':
            allowedOrigins: # 允許哪些網站的跨域請求
              - "http://127.0.0.1:5500"
              - "http://www.leyou.com"
            allowedMethods: # 允許的跨域ajax的請求方式
              - "GET"
              - "POST"
              - "DELETE"
              - "PUT"
              - "OPTIONS"
            allowedHeaders: "*" # 允許在請求中攜帶的頭信息
            allowCredentials: true # 是否允許攜帶cookie
            maxAge: 360000 # 這次跨域檢測的有效期

在gateway網關模塊中配置以上配置,即可解决跨域問題

原网站

版权声明
本文为[mm天天寫bug]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/185/202207040835458783.html