1. 程式人生 > >小白學SpringCloud(五):路由閘道器(Zuul)

小白學SpringCloud(五):路由閘道器(Zuul)

zuul_logo

在微服務的架構下,各個服務一般會有各自的網路地址,在這樣的情況下外部客戶端的呼叫可能會形成雜亂無章的局面。這時候我們就可以使用微服務閘道器Zuul這個元件,我們讓所有的客戶端請求全部請求Zuul,再由Zuul統一的去請求各個服務。

一、Zuul簡介

Zuul是Netflix開源的微服務閘道器,他可以和Eureka,Ribbon,Hystrix等元件配合使用。Zuul元件的核心是一系列的過濾器,這些過濾器可以完成以下功能:

  • 身份認證和安全: 識別每一個資源的驗證要求,並拒絕那些不符的請求
  • 審查與監控:
  • 動態路由:動態將請求路由到不同後端叢集
  • 壓力測試:逐漸增加指向叢集的流量,以瞭解效能
  • 負載分配:為每一種負載型別分配對應容量,並棄用超出限定值的請求
  • 靜態響應處理:邊緣位置進行響應,避免轉發到內部叢集
  • 多區域彈性:跨域AWS Region進行請求路由,旨在實現ELB(ElasticLoad Balancing)使用多樣化

Spring Cloud對Zuul進行了整合和增強。目前,Zuul使用的預設是Apache的HTTP Client,也可以使用Rest Client,可以設定ribbon.restclient.enabled=true.。

二、建立一個api-gateway工程

這裡我們使用IntelliJ IDEA進行展示。
1.首先建立一個Zuul專案
使用IDEA建立一個專案
eureka_2
中間有一步我們選擇Zuul選項和SpringBoot版本,如圖
eureka_2


然後下一步就可以建立好了
2.新增@EnableZuulProxy註解
這個註解只需要在springboot工程的啟動application類上就好了

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

然後在配置檔案中新增config的配置,具體可以見

小白學SpringCloud(三):統一配置中心(config)。然後就可以使用Zuul工程的路由了,依次執行Eureka、Config、Client客戶端、Zuul。
我們先來隨便訪問一下client端的env介面
zuul_2
然後我們通過zuul服務的埠+專案名/介面名這種方式來訪問一下這個介面
zuul_3
可以看到,同樣訪問到了結果。
另外,我們也可以在配置檔案中更加細粒度控制路由路徑:

# 表示只要HTTP請求是 /client1開始的,就會轉發到服務id為client1的服務上面
zuul:
  routes:
    client1:
      path:/client1/**  // 路由路徑
      serviceId: client1 // 服務id
    client2:
      path:/client2/**  // 路由路徑
      serviceId: client2 // 服務id

需要注意的是,使用Zuul預設不會將Cookie的資訊帶入服務端,所以我們需要在配置檔案中進行配置,將敏感頭設定為空即可:

zuul:
  sensitiveHeaders:  

二、服務過濾

zuul不僅只是路由,並且還能過濾,做一些安全驗證。我們來新建一個Filter並且繼承ZuulFilter

import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_DECORATION_FILTER_ORDER;
import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_TYPE;

/**
 * @Author: lllx
 * @Description:
 * @Date: Created on 17:54 2018/7/10
 * @Modefied by:
 */
public class MyFilter extends ZuulFilter {
    
    /*返回一個字串代表過濾器的型別
    pre:路由之前
    routing:路由之時
    post: 路由之後
    error:傳送錯誤呼叫
    我們可以通過匯入FilterConstants這個常量類中的屬性來返回
    */
    @Override
    public String filterType() {
        return PRE_TYPE;
    }

    //過濾的順序,Zuul中也自定義了很多過濾器,呼叫的順序即通過這個方法返回的大小,越小越靠前。我們可以通過FilterConstants這個常量類中定義好的過濾器-1來返回
    @Override
    public int filterOrder() {
        return PRE_DECORATION_FILTER_ORDER -1;
    }

    //這裡可以寫邏輯判斷,是否要過濾,本文true,永遠過濾。
    @Override
    public boolean shouldFilter() {
        return true;
    }

    //過濾器的具體邏輯。可用很複雜,包括查sql,nosql去判斷該請求到底有沒有許可權訪問。
    @Override
    public Object run() throws ZuulException {
        RequestContext requestContext = RequestContext.getCurrentContext();
        HttpServletRequest request = requestContext.getRequest();

        //從url引數獲取如果沒有token這個引數就不允許請求
        String token = request.getParameter("token");
        if(StringUtils.isEmpty(token)){
            requestContext.setSendZuulResponse(false);
            requestContext.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());
        }
        return null;
    }
}

我們可以通過這樣的方式去自定義一個個的過濾器。