[SpringCloud] 入門-第五篇: zuul服務網關和過濾

1. zuul

在微服務系統中,一個客戶端需要調用各種各樣的服務,就好比在一堆電線插頭中找到自己的充電器,十分複雜,且不利於統一的對這些服務調用進行管理,於是zuul就充當了中間人這麼一個角色

這裏寫圖片描述
這樣客戶端只需要和網關交互,而無需直接調用特定微服務的接口,而且方便監控,易於認證,減少客戶端和各個微服務之間的交互次數

 zuul的主要功能

  • 身份認證和安全: 識別每一個資源的驗證要求,並拒絕那些不符的請求

  • 審查與監控:

  • 動態路由:動態將請求路由到不同後端集羣

  • 壓力測試:逐漸增加指向集羣的流量,以瞭解性能

  • 負載分配:爲每一種負載類型分配對應容量,並棄用超出限定值的請求

  • 靜態響應處理:邊緣位置進行響應,避免轉發到內部集羣

  • 多區域彈性:跨域AWS Region進行請求路由,旨在實現ELB(ElasticLoad Balancing)使用多樣化

2. 創建一個service-zuul工程

當然這個工程也是在之前的項目的基礎上創建,可以直接拷貝service-feign,改吧改吧就好了

依賴:

<?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>
    <packaging>jar</packaging>
    <artifactId>service-zuul</artifactId>

    <name>service-zuul</name>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.2.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Dalston.RC1</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

    <repositories>
        <repository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
    </repositories>


</project>

同樣的,我們需要在啓動類上打上註解開啓zuul功能

package com.zgd.springcloud.eurekaClient;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;


/**
 * eureka client 客戶端
 */
@EnableZuulProxy
@EnableEurekaClient
@SpringBootApplication
public class ZuulApp {

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

}

然後修改配置文件

eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/
spring:
  application:
    name: service-zuul
server:
  port: 8087
#分配兩個服務器的路由
zuul:
  routes:
    api-a:
      path: /ribbon/**
      serviceId: service-ribbon
    api-b:
      path: /feign/**
      serviceId: service-feign

這裏api-a和/ribbon/**都是自己定義的,目的是區分routes下面的多個路由

最終以/api-a/ 開頭的請求都轉發給service-ribbon服務;以/api-b/開頭的請求都轉發給service-feign服務

現在我們依次啓動

  • eurekaServer
  • eureka-client-01
  • service-feign
  • service-ribbon
  • serivce-zuul

然後我們訪問
http://localhost:8087/ribbon/getHi?name=zgd

http://localhost:8087/feign/getHi?name=zgd

這裏寫圖片描述

注意這裏的端口是8087,所以訪問的是service-zuul的服務,並且根據ribbonfeign來分別調用service-ribbon和service-feign

3. zuul過濾器

上面說的zuul的路由功能,zuul還有一個功能就是可以過濾從客戶端到服務端的請求

首先我們需要寫一個類,繼承ZuulFilter

注意要使用@component註解將實例交給spring 管理

package com.zgd.springcloud.eurekaClient.filter;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 通過繼承ZuulFilter來自定義過濾器
 * @author zgd
 * @time 2018年8月1日14:18:06
 */
@Component
public class ZuulDemoFilter extends ZuulFilter {




    /**
     * 過濾類型,可以選"pre,routing,post"
     * @return
     */
    @Override
    public String filterType() {
        return "pre";
    }


    /**
     * 過濾順序
     * @return
     */
    @Override
    public int filterOrder() {
        return 0;
    }

    /**
     * 是否進行過濾
     * @return
     */
    @Override
    public boolean shouldFilter() {
        RequestContext rc = RequestContext.getCurrentContext();
        HttpServletRequest request = rc.getRequest();
        String flag = request.getParameter("flag");
        Boolean f = true;
        if (flag != null){
            f = Boolean.valueOf(flag);
        }
        System.out.println("是否過濾 = " + f);
        return f;
    }

    /**
     * 攔截的具體業務代碼
     * @return
     */
    @Override
    public Object run() {
        RequestContext rc = RequestContext.getCurrentContext();
        HttpServletRequest request = rc.getRequest();
        HttpServletResponse response = rc.getResponse();

        System.out.println("調用了過濾器");
        String money = request.getParameter("money");
        if (money == null){
            try {
                rc.setSendZuulResponse(false);
                response.setContentType("text/html;charset=utf-8");
                response.getWriter().write("沒有錢不給過");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }
}
1.filterType方法

可以返回
pre : 在通過路由之前過濾
routing:路由之時過濾
error:報錯的時候調用
post:如有之後調用

2. filterOrder方法

可以給過濾指定調用的順序

3. shouldFilter方法

是否進行過濾,這裏進行邏輯判斷

4. run

過濾要做的具體的業務邏輯

5. rc.setSendZuulResponse(false);

表示是否通過該請求


然後我們運行service-zuul

首先訪問
http://localhost:8087/ribbon/getHi?name=zgd&flag=true
頁面顯示: 說明攔截成功
這裏寫圖片描述
控制檯打印: 說明先調用shouldFilter方法,判斷是否過濾以後,再調用run方法
這裏寫圖片描述

再訪問http://localhost:8087/ribbon/getHi?name=zgd&flag=false
可以正常訪問

這裏寫圖片描述
這裏寫圖片描述

再訪問http://localhost:8087/ribbon/getHi?name=zgd&flag=true&money=1
可以正常訪問
這裏寫圖片描述
這裏寫圖片描述

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