文章目錄
一、前言
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基本使用
-
創建新模塊 EurekaZuul 作爲zuul網關。選中引入Zuul依賴和Eureka客戶端依賴。Zuul依賴自不必說,引入Eureka客戶端的依賴是爲了從Eureka註冊中心拉取註冊已註冊的服務。
-
在啓動類上加上註解 @EnableZuulProxy 開啓zuul網關代理,@EnableDiscoveryClient 註冊爲Eureka客戶端
@SpringBootApplication @EnableZuulProxy // 開啓網關代理功能 @EnableDiscoveryClient // 註冊人Eureka客戶端 public class SpringcloudApplication { public static void main(String[] args) { SpringApplication.run(SpringcloudApplication.class, args); } }
-
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默認格式是 ----> 服務名: /服務名/**
-
啓動服務,訪問服務,如下:
三、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熔斷機制。其使用方式和配置和單獨使用並無差別。故此不再敘述。
以上:內容部分參考網絡
如有侵擾,聯繫刪除。 內容僅用於自我記錄學習使用。如有錯誤,歡迎指正