1. 程式人生 > >11 微服務集群網關Zuul介紹

11 微服務集群網關Zuul介紹

yun 環境 對象 tco 超出 port router 負載 直接

  在實際環境中,我們的應用程序會有多個服務調用者,如何將其組織起來統一對外提供服務呢?我們可以使用Netflix的Zuul框架構建微服務集群網關來解決這個問題。

1. Zuul框架介紹

  1.1 關於Zuul

  Spring Cloud提供了多個組件用於集群內部的通信,例如服務管理組件Eureka,負載均衡組件Ribbon,REST客戶端組件Feign等等。如果集群提供可一個API或者Web服務,需要與外部進行通信,最好的方式就是添加一個網關,將集群的服務都隱藏到網關後面,這種做法對於外部客戶端來說,無需關心集群的內部結構,只需關心網關的配置信息;對於Spring Cloud集群來說,不必過多的暴露服務,提高了集群的安全性。

  代理層作為應用集群的大門,在技術選擇上尤為重要,很多傳統的解決方案,在軟件選擇上使用了Nginx、Apache等服務器。Netflix提供了自己的解決方案:Zuul。Zuul是Netflix的一個子項目,Spring Cloud對其進行了進一步的封裝與實現,將其整合到了spring-netflix項目中,為微服務集群提供代理、過濾和路由等功能。

  1.2 Zuul的功能

  Zuul將外部的請求劃分為不同階段,每個階段都提供了一系列的過濾器,這些過濾器可以幫我們實現以下的功能:

  》 身份驗證和安全性:對需要身份驗證的資源進行過濾,拒絕處理不服個身份認證的請求;

  》觀察和監控:跟蹤重要的數據,為我們展示準確的請求狀況;

  》動態路由:將請求動態路由到不同的服務器;

  》負載分配:設置每種請求的處理能力,刪除那些超出限制的請求;

  》靜態相應處理:提供一些靜態的過濾器,直接響應一些請求,而不將他們轉發到集群內部;

  》路由的多樣化:除了可以將請求路由到Spring Cloud集群外,還可以將請求路由到其他服務。

2. 在Web項目中使用Zuul

  下面將開發一個簡單的程序,初步展示Zuul的功能。,程序架構如下

  技術分享圖片

  2.1 Web項目整合Zuul

  新建一個maven的測試項目,測試項目的目錄結構及架構圖如下

  技術分享圖片

  其中網關項目firstrouter在8080端口啟動,而服務項目bookserver在8090端口啟動。在firstrouter項目中引入相關的依賴,代碼清單如下

  pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.triheart</groupId>
    <artifactId>firstrouter</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Dalston.SR1</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zuul</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.5.3</version>
        </dependency>
    </dependencies>
</project>

  我們需要為項目加入spring-cloud-stater-zuul依賴,由於Zuul底層使用了HttpClient,因此需要加入相應的依賴。為了能讓Web項目開啟對Zuul項目的支持,我們需要在啟動類中加入@EnableZuulProxy註解,代碼清單如下

  RouterApp.java

package com.triheart.firstrouter;

import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;

/**
 * @author 阿遠
 * Date: 2018/9/2
 * Time: 14:33
 */
@SpringBootApplication
@EnableZuulProxy
public class RouterApp {

    public static void main(String[] args){
        new SpringApplicationBuilder(RouterApp.class).properties("server.port=8080").run(args);
    }
}

  我們項目的啟動端口設置為8080,現在我們已經完成了一個擁有Zuul功能的Web項目,接下來,我們測試其路由功能。

  2.2測試路由功能

  新建名為bookserver的maven項目,該項目是一個普通的Spring Boot項目,依賴如下

  pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.triheart</groupId>
    <artifactId>bookserver</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>1.5.4.RELEASE</version>
        </dependency>
    </dependencies>
    
</project>

  再為bookserver添加一個/hello服務,為了簡單起見我們將項目的啟動器和控制器寫在一起,代碼清單如下

  ServerApp.java

package com.triheart.bookserver;

import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author 阿遠
 * Date: 2018/9/2
 * Time: 14:37
 */
@SpringBootApplication
@RestController
public class ServerApp {

    @RequestMapping(value = "/hello/{name}", method = RequestMethod.GET)
    public String hello(@PathVariable("name") String name) {
        return "hello  " + name;
    }

    public static void main(String[] args){
        new SpringApplicationBuilder(ServerApp.class).properties("server.port=8090").run(args);
    }
}

  我們將項目的端口設置為8090,在控制器中,建立了一個/hello/{name}的服務,服務成功調用後,會返回相應的字符串。接下來,我們修改firstrouter項目的配置文件,讓其進行轉發工作。

  為firstrouter項目添加application.yml文件,代碼清單如下

  application.yml

zuul:
  routes:
    books:
      url: http://localhost:8090

  加入以上的配置後,發送給http://localhost:8080/books的所有請求會被轉發到8090端口,也就是訪問firstrouter項目,實際上會調用bookserver的服務。啟動兩個應用,在瀏覽器中訪問http://localhost:8080/books/hello/ayun,可以看到瀏覽器的輸出如下:

技術分享圖片

  我們可以看到,發送的請求已經被轉發到bookserver進行處理。

3.過濾器運行機制

  在前面的項目中,我們使用了@EnableZuulProxy註解。開啟該註解後,在Spring容器初始化時,會將Zuul的相關配置初始化,其中包含一個Spring Boot的Bean:ServletRegistrationBean,該類主要用於註冊Servlet。Zuul提供了一個ZuulServlet類,在Servlet的Service方法中,執行各種Zuul過濾器(ZuulFilter)。下圖為HTTP請求在ZuulServlet中的生命周期。

  技術分享圖片

  ZuulServlet的Service方法接受到請求後,會執行pre階段的過濾器,再執行routing階段的過濾器,最後執行post階段的過濾器。其中routing階段的過濾器會將請求轉發到“源服務”,源服務可以使第三方的Web服務,也可以是Spring Cloud的集群服務。在執行pre和routing階段的過濾器時,如果出現異常,則會執行error過濾器。整個過程的HTTP請求、HTTP響應、狀態等數據,都會被封裝到一個RequestContext對象中。   

11 微服務集群網關Zuul介紹