新 Spring Cloud (五) 之 Zuul 網關

一、前言

0. 之前寫過兩篇Spring Cloud,但是感覺不夠具體,所以重新寫了一份。

新 Spring Cloud (一) 之 Eureka 服務註冊中心
新 SpringCloud (二) 之 Ribbon 負載均衡
新 Spring Cloud (三) 之 Hystrix熔斷保護
新 Spring Cloud (四) 之 Fegin遠程調用
新 Spring Cloud (五) 之 Zuul 網關

1. 正文

Zuul是Netflix開源的微服務網關,它可以和Eureka、Ribbon、 Hystrix 等組件配合使用。
Zuul的核心是–系列的過濾器,這些過濾器可以完成以下功能。

  • 身份認證與安全:識別每個資源的驗證要求,並拒絕那些與要求不符的請求。
  • 審查與監控:在邊緣位置追蹤有意義的數據和統計結果,從而帶來精確的生產視圖。
  • 動態路由:動態地將請求路由到不同的後端集羣。
  • 壓力測試:逐漸增加指向集羣的流量,以瞭解性能。
  • 負載分配:爲每- -種負載類型分配對應容量,並棄用超出限定值的請求。
  • 靜態響應處理:在邊緣位置直接建立部分響應,從而避免其轉發到內部集羣。
  • 多區域彈性:跨越AWS Region進行請求路由,旨在實現ELB ( Elastic Load Balancing )
    使用的多樣化,以及讓系統的邊緣更貼近系統的使用者。

Spring Cloud對Zuul進行了整合與增強。目前, Zuul使用的默認HTTP客戶端是Apache
HTTP Client,也可以使用RestClient或者okhttp3.0kHttpClient。如果想要使用RestClient,
可以設置ribbon.restclient ,enabled=true ;想要使用okhttp3.0kHttpClient ,可以設置rib-
bon. okhttp . enabled=true。

Zuul網關的架構圖:
在這裏插入圖片描述

二、Zuul基本使用

  1. 創建新模塊 EurekaZuul 作爲zuul網關。選中引入Zuul依賴和Eureka客戶端依賴。Zuul依賴自不必說,引入Eureka客戶端的依賴是爲了從Eureka註冊中心拉取註冊已註冊的服務。
    在這裏插入圖片描述


  2. 在啓動類上加上註解 @EnableZuulProxy 開啓zuul網關代理,@EnableDiscoveryClient 註冊爲Eureka客戶端

    @SpringBootApplication
    @EnableZuulProxy            // 開啓網關代理功能
    @EnableDiscoveryClient      // 註冊人Eureka客戶端
    public class SpringcloudApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(SpringcloudApplication.class, args);
        }
    
    }
    

  3. yml進行如下配置

    spring:
      application:
        name: zuul-gateway  #  指定服務名
    server:
      port: 9999  #端口號
    zuul:
      routes:
        eureka-server-provider: /provider/**  #  /provider/** 路徑的請求都映射到的 eureka-server-provider 服務上
        eureka-server-consumer: /consumer/**  #  /provider/** 路徑的請求都映射到的 eureka-server-provider 服務上
      prefix: /api    # 添加路由前綴。用來分辨哪個接口通過了Zuul網關。
    eureka:
      client:
        service-url: # EurekaServer的地址
          defaultZone: http://127.0.0.1:10086/eureka,http://127.0.0.1:10087/eureka
    

    注: Zuul 網關的常用的路由方式有以下三種
    1. 使用 path 指定映射路徑,serviceId指定服務名

    zuul:
      routes:
        eureka-server-provider:         # 路由id,可以隨意寫
          path: /provider/** 			# 服務將要映射的路徑
          serviceId: eureka-server-provider   # 指定需要路由的服務名
    

    2. 是第一種的簡化形式,格式是 ----> 服務名:映射路徑

    	zuul:
    	  routes:	# 上面簡化形式: 服務名:映射路徑
    	    eureka-server-provider: /provider/**  #  /provider/** 路徑的請求都映射到的 eureka-server-provider 服務上
    

    3. 不進行配置: 不配置默認將服務名作爲映射路徑。Zuul默認格式是 ----> 服務名: /服務名/**


  4. 啓動服務,訪問服務,如下:
    在這裏插入圖片描述

三、Zuul過濾器

1. 簡介

Zuul作爲網關的其中一個重要功能,就是實現請求的鑑權。而這個動作我們往往是通過Zuul提供的過濾器來實現的。
Zuul提供了一個最頂層的抽象過濾器ZuulFilter。我們通過繼承這個抽象類來實現過濾器功能。

public abstract ZuulFilter implements IZuulFilter{

    abstract public String filterType();

    abstract public int filterOrder();
    
    boolean shouldFilter();// 來自IZuulFilter 

    Object run() throws ZuulException;// IZuulFilter
}
  • shouldFilter:返回一個Boolean值,判斷該過濾器是否需要執行。返回true執行,返回false不執行。
  • run:過濾器的具體業務邏輯。
  • filterType:返回字符串,代表過濾器的類型。包含以下4種:
    • pre:請求在被路由之前執行
    • route:在路由請求時調用
    • post:在route和errror過濾器之後調用
    • error:處理請求時發生錯誤調用
  • filterOrder:通過返回的int值來定義過濾器的執行順序,數字越小優先級越高。

2. 使用場景

  • 請求鑑權:一般放在pre類型,如果發現沒有訪問權限,直接就攔截了
  • 異常處理:一般會在error類型和post類型過濾器中結合來處理。
  • 服務調用時長統計:pre和post結合使用。

3. 過濾器的生命週期

正常流程:

  • 請求到達首先會經過pre類型過濾器,而後到達route類型,進行路由,請求就到達真正的服務提供者,執行請求,返回結果後,會到達post過濾器。而後返回響應。

異常流程:

  • 整個過程中,pre或者route過濾器出現異常,都會直接進入error過濾器,在error處理完畢後,會將請求交給POST過濾器,最後返回給用戶。
  • 如果是error過濾器自己出現異常,最終也會進入POST過濾器,將最終結果返回給請求客戶端。
  • 如果是POST過濾器出現異常,會跳轉到error過濾器,但是與pre和route不同的是,請求不會再到達POST過濾器了。

4. 自定義過濾器實現

創建一個類繼承 ZuulFilter 類,並實現其中的方法,最後將其注入到Spring容器中即可。

package com.kingfish.springcloud.filter;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import io.micrometer.core.instrument.util.StringUtils;
import org.apache.http.HttpStatus;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;

/**
 * @Des: 自定義過濾器
 */
@Component
public class CallFilter extends ZuulFilter {
    /**
     * 過濾類型
     *
     * @return
     */
    @Override
    public String filterType() {
        return "pre";
    }

    /**
     * 過濾器順序,數字越小優先級越高
     *
     * @return
     */
    @Override
    public int filterOrder() {
        return 10;
    }

    /**
     * 是否執行攔截
     *
     * @return
     */
    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() throws ZuulException {
        // 獲取zuul提供的上下文對象
        RequestContext context = RequestContext.getCurrentContext();
        // 從上下文對象中獲取請求對象
        HttpServletRequest request = context.getRequest();
        // 設置編碼格式
        context.getResponse().setContentType("text/html;charset=UTF-8");
        // 獲取token信息
        String msg = request.getParameter("msg");
        // 判斷
        if (StringUtils.isBlank(msg)) {
            // 過濾該請求,不對其進行路由
            context.setSendZuulResponse(false);
            // 設置響應狀態碼,401
            context.setResponseStatusCode(HttpStatus.SC_UNAUTHORIZED);
            // 設置響應信息
            context.setResponseBody("{\"status\":\"401\", \"text\":\"來者何人,報上姓名!\"}");
        } else if ("張三".equals(msg)) {
            // 過濾該請求,不對其進行路由
            context.setSendZuulResponse(false);
            // 設置響應狀態碼,401
            context.setResponseStatusCode(HttpStatus.SC_FORBIDDEN);
            // 設置響應信息
            context.setResponseBody("{\"status\":\"403\", \"text\":\"張三不能打車!\"}");
        }
        // 校驗通過,把登陸信息放入上下文信息,繼續向後執行
        context.set("msg", msg);
        return null;
    }
}

調用如下:
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

四、Ribbon負載均衡和Hystrix熔斷

Zuul中默認就已經集成了Ribbon負載均衡和Hystix熔斷機制。其使用方式和配置和單獨使用並無差別。故此不再敘述。

以上:內容部分參考網絡
如有侵擾,聯繫刪除。 內容僅用於自我記錄學習使用。如有錯誤,歡迎指正

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章