1. 程式人生 > >springCloud(F版)(3)——zuul實現路由轉發、過濾器、負載均衡

springCloud(F版)(3)——zuul實現路由轉發、過濾器、負載均衡

前面博文我們通過rest+Ribbon和Feign的方式實現了對生產者的消費(說白了就是轉手呼叫一下server介面),順帶看了一下負載均衡效果。但是我們發現兩種方式呼叫介面的時候如果想呼叫不同的生產者(application.name或者說serviceID)是需要寫死在程式碼裡的,沒有實現方便的路由轉發功能,另外沒有做過濾器校驗等功能,當然你可以自己DIY進去。今天介紹一個springCloud支援的方便的路由閘道器框架Zuul。

下面主要學習實踐一下Zuul專案的搭建、路由轉發功能、過濾器功能、負載均衡功能。

原始碼百度網盤備份:連結:https://pan.baidu.com/s/16p_4VtqMdw6xF1HN_HzvGg 密碼:m4cg

一、建立一個zuul專案

springboot工程我們已經建立了好幾次了,就不贅述了,直接上截圖。

我又放到testSpringCloud這個根路徑下了,主要是想用這個路徑下的父pom.xml檔案,雖然裡面也沒寫什麼有用的東西,但是養成版本統一控制的習慣還是好的。

修改zuul專案的pom.xml檔案

引入spring-cloud-starter-netflix-eureka-client和spring-cloud-starter-netflix-zuul依賴,spring-boot-starter-web這個依賴基本上我這幾個專案裡都有,如果嫌麻煩的話可以放到父pom.xml裡,更懶的話那就直接複製貼上我的pom檔案吧。父pom.xml檔案到我前面的博文裡找。沒有父pom檔案的,parent標籤會報錯哦。

<?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.testzuul</groupId>
    <artifactId>zuul</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>zuul</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>com.springcloud</groupId>
        <artifactId>testspringcloud</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <relativePath>../pom.xml</relativePath>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
        </dependency>
    </dependencies>

</project>

修改**application.java入口類

新增@EnableZuulProxy、 @EnableEurekaClien和 @EnableDiscoveryClient註解就行了。

@SpringBootApplication
@EnableZuulProxy
@EnableEurekaClient
@EnableDiscoveryClient
public class ZuulApplication {

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

修改application.properties配置檔案

自己的埠port是8751,下面配置了兩個閘道器分配的方案

eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/
server.port: 8751
spring.application.name=service-zuul
zuul.routes.client1.path=/client1/**
zuul.routes.client1.service-id=service-client1

zuul.routes.client2.path=/client2/**
zuul.routes.client2.service-id=service-client2

這樣,zuul的訪問url為 http://IP:port/client*/*** 其中ip是localhost或者遠端釋出的伺服器ip,port就是8751,後面client1就指定到service-client1這個生產者叢集,client2就指定到service-client2這個生產者叢集。zuul是整合Ribbon自動負載均衡的。zuul會按照eureka.client.serviceUrl.defaultZone的配置去找註冊中心將自己註冊進去,後面訪問生產者叢集也是依據自己閘道器配置的service-id去匹配註冊中心的application name的。

二、執行工程測試一下閘道器功能

前面博文我們做好了Eureka server註冊中心,生產者springcloudserver*(我們執行的時候通過指令引數配置成service-client1和service-client2兩個服務叢集),現在又做好了zuul閘道器。那麼我們嘗試著搭建下面這樣一個系統結構出來。

埠號我都寫好了,那麼我們分別跑起來看看吧。Eureka server 和springcloudserver*(就是service-client)的原始碼和可執行jar包我都放在百度網盤裡了,連結:https://pan.baidu.com/s/1SGR6I3VZqrrqJO7Mrqj6Ig 密碼:k2fj

啟動Eureka server,cmd到可執行jar包的目錄(eurekaserver的target裡)執行指令:

java -jar eurekaserver-0.0.1-SNAPSHOT.jar --server.port=8761

啟動service-client1和service-client2,cmd到可執行jar包的目錄(springcloudserver1的target裡)執行指令:

(貼上下面指令的話很可能會帶上莫名其妙的字元,強烈建議參考我下面的截圖手敲)

java -jar **.jar --server.port=8762 --spring.application.name=service-client1

--eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/   

java -jar **.jar --server.port=8763 --spring.application.name=service-client1

--eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/   

java -jar **.jar --server.port=8764 --spring.application.name=service-client2

--eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/   

java -jar **.jar --server.port=8765 --spring.application.name=service-client2

--eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/   

到這,該執行的都執行好了,當然是沒報錯的情況下。瀏覽器輸入Eureka server的視覺化頁面網址看一下注冊情況

http://localhost:8761

這裡可以看到我們的四個生產者都註冊好了,分了兩個服務叢集service-client1和service-client2。

現在我們編譯執行剛剛弄好的zuul,執行前千萬檢查一下配置檔案,Eureka server的配置,自己的埠號。另外回憶一下我們的生產者有一個/hi介面,引數是name(不輸入name引數的話預設是testname)

瀏覽器輸入http://localhost:8751/client1/hi?name=qftest

反覆試幾次可以看到,client1被路由轉發到service-client1(8762和8763)叢集裡,執行時有負載均衡。

瀏覽器輸入http://localhost:8751/client2/hi?name=qftest 再試試client2的路由轉發。

OK,從測試效果看,我們已經實現了通過zuul對client1和client2進行路由轉發,呼叫不同的生產者服務叢集,並且自帶負載均衡。

三、修改工程,學習實踐一下過濾器。

zuul框架其實提供了很多功能,我們剛剛實踐了一下路由轉發,現在嘗試一下過濾器。

新增一個java類 MyFilter 繼承ZuulFilter,原始碼如下

@Component
public class MyFilter extends ZuulFilter {

    private static Logger log = LoggerFactory.getLogger(MyFilter.class);
    @Override
    public String filterType() {
        return "pre";
    }

    @Override
    public int filterOrder() {
        return 0;
    }

    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        log.info(String.format("%s >>> %s", request.getMethod(), request.getRequestURL().toString()));
        Object accessToken = request.getParameter("token");
        if(accessToken == null) {
            log.warn("token is empty");
            ctx.setSendZuulResponse(false);
            ctx.setResponseStatusCode(401);
            try {
                ctx.getResponse().getWriter().write("token is empty");
            }catch (Exception e){}

            return null;
        }else if(checkToken(accessToken)){
            log.info("ok");
            return null;
        }else{
            log.info("error");
            return null;
        }
    }

    private boolean checkToken(Object accessToken) {
        //這裡新增token校驗程式碼
        return true;
    }
}

這裡具體的配置可以百度一下ZuulFilter。我只是寫了一個簡單的token過濾,寫了token無論寫啥都通過,沒寫才報錯。

好了,重新編譯執行看看效果:

瀏覽器輸入 http://localhost:8751/client2/hi?name=qftest  (其實就是試試不寫token)

瀏覽器輸入 http://localhost:8751/client2/hi?name=qftest&token=test

OK。至此我們對Zuul框架實現路由轉發、過濾器、負載均衡的學習實踐完成。