微服務看門神-Zuul


 
        

Zuul網關和基本應用場景

構建微服務時,常見的問題是為系統的客戶端應用程序提供唯一的網關。

事實上,您的服務被拆分為小型微服務應用程序,這些應用程序應該對用戶不可見,否則可能會導致大量的開發/維護工作。還有一些情況,整個生態系統網絡流量可能會通過一個可能影響群集性能的點。

為了解決這個問題,Netflix(微服務的一個主要采用者)創建並開源了它的ZuulZuul是Netflix的基於JVM的路由器和服務器端負載均衡器。后來Spring在Pivotal下已經在其Spring Cloud中對其進行了調整,使我們能夠通過簡單的步驟輕松有效地使用zuul。

Zuul是一種邊緣服務,它支持對多個服務請求的代理。它為您的生態系統提供統一的“前門”,允許任何瀏覽器,移動應用程序或其他用戶界面使用來自多個主機的服務。您可以將Zuul與其他Netflix堆棧組件(如Hystrix)集成以實現容錯,使用Eureka進行服務發現,或者使用它來管理整個系統中的路由規則,過濾器和負載平衡。

最重要的是,Spring框架通過Spring boot/cloud很好地適應了所有這些組件。

路由器和過濾器

路由是微服務架構不可或缺的一部分。例如,/可以映射到您的Web應用程序,/api/users映射到用戶服務並/api/shop映射到商店服務。

Netflix使用Zuul進行以下操作:

  • 認證

  • 洞察

  • 壓力測試

  • 金絲雀測試

  • 動態路由

  • 服務遷移

  • 負載脫落

  • 安全

  • 靜態響應處理

  • 主動/主動流量管理

Zuul的規則引擎允許規則和過濾器基本上以任何JVM語言編寫,內置支持Java和Groovy。

 

Zuul組件

Zuul主要有四種類型的過濾器,使我們能夠在任何特定事務的請求處理的不同時間線中攔截流量。我們可以為特定的url模式添加任意數量的過濾器。

  • 前置過濾器 - 在路由請求之前調用。

  • 后置過濾器 - 在路由請求后調用。

  • 路由過濾器 - 用於路由請求。

  • 錯誤過濾器 - 在處理請求時發生錯誤時調用。

使用不同的過濾器在Zuul內部請求處理流程

 

過濾器關鍵概念

關鍵詞 備注
類型Type 定義在路由過程中,過濾器被應用的階段
執行順序Execution Order 在同一個Type中,定義過濾器執行的順序
條件Criteria 過濾器被執行必須滿足的條件
動作Action 如果條件滿足,過濾器中將被執行的動作

 

標准過濾器類型

PRE

在請求被路由到源服務器前要執行的過濾器

適用業務場景

  • 認證

  • 選路由

  • 請求日志

 

ROUTING

處理將請求發送到源服務器的過濾器

 

POST

在響應從源服務器返回時要被執行的過濾器

  • 對響應增加HTTP 頭

  • 收集統計和度量

  • 將響應以流的方式發送回客戶端

 

ERROR

上述階段中出現錯誤要執行的過濾器

 

過濾器樣例

public class PreFilter extends ZuulFilter {

// 過濾器類型
 @Override
 public String filterType() {
   return "pre";
}

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

// 是否加入過濾器流程中
 @Override
 public boolean shouldFilter() {
   return true;
}

// 過濾器運行代碼
 @Override
 public Object run() {
   RequestContext ctx = RequestContext.getCurrentContext();
   HttpServletRequest request = ctx.getRequest();

   System.out.println("Request Method : " + request.getMethod() + " Request URL : " + request.getRequestURL().toString());

   return null;
}

}

 

netflix zuul實例概述

現在讓我們通過使用Zuul創建一個簡單而有意義的生態系統來嘗試一下。我們將創建下面的組件來演示整個事物:

  • 學生微服務 - 基於spring boot啟動的微服務,它只是暴露單個URL以啟用一些搜索功能。為簡單起見,我們將返回硬編碼值,但在現實世界中,我們可以讓此服務連接數據庫以獲取數據。

  • Zuul網關服務

    它基於spring boot啟動,它將基本上攔截學生服務的所有流量並應用一系列請求過濾器然后路由到底層服務,並在響應服務時再次,它將應用一些響應過濾。由於它是一個網關,我們可以使用過濾器有效地采取許多有趣和有用的操作。

    網關服務的一些共同責任是 -

    • 在網關層應用微服務身份驗證和安全性以保護實際服務

    • 我們可以通過使一些日志記錄在邊緣獲取有意義的數據和統計數據來實現微服務洞察和監控進入生態系統的所有流量,從而為我們提供准確的生產視圖。

    • 動態路由可以根據需要將請求路由到不同的后端群集。

    • 我們可以通過逐漸增加到新集群的流量來進行運行時壓力測試,以便在許多情況下衡量性能,例如集群有新的H / W和網絡設置,或者部署了新版本的生產代碼。

    • 我們可以進行動態負載,即為每種類型的請求分配容量,並刪除超出限制的請求。

    • 我們可以應用靜態響應處理,即直接在邊緣構建一些響應,而不是將它們轉發到內部集群進行處理。

技術棧和運行環境

  • Java 1.8和IntelliJIDEA作為開發環境

  • Spring cloud Zuul作為網關代理提供商

  • Spring boot作為應用程序框架

  • Spring Rest用於將微服務暴露為REST

  • Maven作為構建工具

 

創建學生微服務

按照以下步驟開發學生微服務,稍后將通過zuul代理訪問的幾個REST端點。稍后我們將研究zuul部分,現在讓我們先創建學生服務。

創建Spring Boot項目

創建一個Spring boot項目從spring初始化網站,依賴於Web

將項目解壓縮並導入到IDEA中。在此步驟中,使用命令執行maven構建,mvn clean install以便正確下載所有maven依賴項。

添加幾個REST端點

我們現在只需向此服務添加一些REST端點,以便稍后測試網關。為此,我們需要通過添加注釋添加一個REST控制器@RestController。為簡單起見,我們將添加一個模型類Student

完成所有更改后,該類將如下所示。

package com.example.springboostudentservice;

import java.util.Date;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@SpringBootApplication
public class SpringBootStudentServiceApplication
{
   @RequestMapping(value = "/echoStudentName/{name}")
   public String echoStudentName(@PathVariable(name = "name") String name)
  {
       return "hello <strong style=\"color: red;\">" + name + " </strong> Responsed on : " + new Date();
  }

   @RequestMapping(value = "/getStudentDetails/{name}")
   public Student getStudentDetails(@PathVariable(name = "name") String name)
  {
       return new Student(name, "Pune", "MCA");
  }

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

class Student
{
   String name;
   String address;
   String cls;

   public Student(String name, String address, String cls) {
       super();
       this.name = name;
       this.address = address;
       this.cls = cls;
  }

   public String getName() {
       return name;
  }

   public String getAddress() {
       return address;
  }

   public String getCls() {
       return cls;
  }
}

應用程序配置

spring:
application:
  name: student
server:
port: 8090

這里我們按屬性給這個服務命名,spring.application.name=student我們也定義了默認端口server.port=8090。我們需要覆蓋默認端口,因為我們將在localhost中運行不同微服務的多個實例。

驗證學生服務

最后使用命令執行maven構建,mvn clean install並通過運行命令將此項目作為spring boot應用程序啟動java -jar target\spring-boot-zuulgatway-student-service-0.0.1-SNAPSHOT.jar。現在,一旦服務器啟動,轉到瀏覽器並測試端點是否正常工作。

http://localhost:8090/echoStudentName/james

http://localhost:8090/getStudentDetails/james

創建學校微服務

創建過程和學生微服務一樣,但是由於服務之間的功能和差異性,我們需要對接口進行簡單的修改

添加幾個REST斷點

我們現在只需向此服務添加一些REST端點,為此,我們需要通過添加注釋添加一個REST控制器@RestController。為簡單起見,我們將添加一個模型類School

完成所有更改后,該類將如下所示。

@SpringBootApplication
@RestController
public class SpringBootZuulgatewaySchoolServiceApplication {

@RequestMapping(value = "/echoSchoolName/{name}")
public String echoSchoolName(@PathVariable(name = "name") String name)
{
return "hello <strong style=\"color: green;\">" + name + " </strong> Responsed on : " + new Date();
}

@RequestMapping(value = "/getSchoolDetails/{name}")
public School getSchoolDetails(@PathVariable(name = "name") String name)
{
return new School(name, "China", "ZheJiang");
}

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

}

class School
{
String name;
String address;
String cls;

public School(String name, String address, String cls) {
super();
this.name = name;
this.address = address;
this.cls = cls;
}

public String getName() {
return name;
}

public String getAddress() {
return address;
}

public String getCls() {
return cls;
}
}

應用程序配置

現在打開application.properties文件並添加這些條目。

 

spring:
application:
  name: school
server:
port: 8100

這里我們按屬性給這個服務命名,spring.application.name=school我們也定義了默認端口server.port=8100`。我們需要覆蓋默認端口,因為我們將在localhost中運行不同微服務的多個實例。

驗證學校服務

最后使用命令執行maven構建,mvn clean install並通過運行命令將此項目作為spring boot應用程序啟動java -jar target\spring-boot-zuulgatway-school-service-0.0.1-SNAPSHOT.jar。現在,一旦服務器啟動,轉到瀏覽器並測試端點是否正常工作。

http://localhost:8100/echoSchoolName/學軍中學

http://localhost:8100/getSchoolDetails/學軍中學

現在我們將使用Zuul創建實際的網關服務。

創建Zuul網關服務

這將是一個基於Spring boot的微服務,但它有一個特殊的功能。它將使用zuul創建一個代表學生服務的API網關。稍后我們可以添加任意數量的微服務,如學生服務,學校服務並能夠創建一個強大的微服務生態系統。

創建String Boot項目

spring初始化網站創建一個具有Zuul依賴關系的Spring boot項目。

將項目作為現有maven項目解壓縮並導入IDEA。在此步驟中,使用命令執行maven構建,mvn clean install以便正確下載所有maven依賴項。

啟用Zuul服務

現在@EnableZuulProxysrc文件夾中的Spring啟動應用程序類中添加注釋。使用此批注,此工件將像Zuul服務代理一樣運行,並將啟用API網關層的所有功能,如前所述。然后我們將添加一些過濾器和路由配置。

import com.example.zuuldemo.filters.ErrorFilter;
import com.example.zuuldemo.filters.PostFilter;
import com.example.zuuldemo.filters.PreFilter;
import com.example.zuuldemo.filters.RouteFilter;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
@EnableZuulProxy
public class ZuuldemoApplication {

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

   @Bean
   public PreFilter preFilter() {
       return new PreFilter();
  }
   @Bean
   public PostFilter postFilter() {
       return new PostFilter();
  }
   @Bean
   public ErrorFilter errorFilter() {
       return new ErrorFilter();
  }
   @Bean
   public RouteFilter routeFilter() {
       return new RouteFilter();
  }

}

Zuul應用配置

打開application.yml並在下面添加條目

zuul:
routes:
  student:
    url: http://localhost:8090
  school:
    url: http://localhost:8100
server:
port: 8080

這里zuul.routes.student.url將路由所有流量以請求/student到實際的學生服務服務器。zuul.routes.school.url將路由所有流量以請求/school到實際的學校服務服務器 server.port - 需要覆蓋默認端口,因為我們將在localhost中運行不同微服務的多個實例。

 

添加Zuul過濾器

正如我們已經描述了zuul組件,我們將添加一些過濾器,Zuul支持4種類型的過濾器,即prepostrouteerror。在這里,我們將創建每種類型的過濾器。

要編寫過濾器,我們基本上需要執行以下步驟:

  • 需要擴展 com.netflix.zuul.ZuulFilter

  • 需要重寫filterTypefilterOrdershouldFilterrun方法。這里的filterType方法只能返回四個String中的任何一個 - pre/post/route/error。降低此值后,過濾器將像特定過濾器一樣運行。

  • run method是根據我們的要求放置濾波器邏輯的地方。

  • 此外,我們可以根據需要添加任意數量的任何特定過濾器,這種情況filterOrder將用於確定該過濾器執行階段該文件管理器的順序。

前置過濾器代碼 - 我們將添加以下預過濾器。目前,過濾器除了println用於測試目的之外什么都不做。但實際上那些功能足以完成前面提到的許多重要方面。

package com.example.springbootzuulgateway.filters;

import javax.servlet.http.HttpServletRequest;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;

public class PreFilter extends ZuulFilter {

@Override
public String filterType() {
  return "pre";
}

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

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

@Override
public Object run() {
  RequestContext ctx = RequestContext.getCurrentContext();
  HttpServletRequest request = ctx.getRequest();

  System.out.println("Request Method : " + request.getMethod() + " Request URL : " + request.getRequestURL().toString());

  return null;
}

}

后置過濾器

package com.example.springbootzuulgateway.filters;

import com.netflix.zuul.ZuulFilter;

public class PostFilter extends ZuulFilter {

  @Override
  public String filterType() {
    return "post";
  }

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

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

  @Override
  public Object run() {
   System.out.println("Inside Response Filter");

    return null;
  }

}

路由過濾器

package com.example.springbootzuulgateway.filters;

import com.netflix.zuul.ZuulFilter;

public class RouteFilter extends ZuulFilter {

  @Override
  public String filterType() {
    return "route";
  }

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

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

  @Override
  public Object run() {
   System.out.println("Inside Route Filter");

    return null;
  }

}

錯誤過濾器

package com.example.springbootzuulgateway.filters;

import com.netflix.zuul.ZuulFilter;

public class ErrorFilter extends ZuulFilter {

  @Override
  public String filterType() {
    return "error";
  }

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

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

  @Override
  public Object run() {
   System.out.println("Inside Route Filter");

    return null;
  }

}

 

5.5。注冊zuul過濾器

創建要自動注冊和啟用的這些過濾器的bean定義。

@Bean
public PreFilter preFilter() {
return new PreFilter();
}
@Bean
public PostFilter postFilter() {
return new PostFilter();
}
@Bean
public ErrorFilter errorFilter() {
return new ErrorFilter();
}
@Bean
public RouteFilter routeFilter() {
return new RouteFilter();
}

 

Netflix zuul示例演示

所以我們啟用了Zuul,添加了所需的配置並開發了過濾器。所以我們可以做基本的測試來理解整個事情。

使用命令執行maven構建,mvn clean install並通過運行命令將此項目作為spring boot應用程序啟動java -jar target\spring-boot-zuulgateway-0.0.1-SNAPSHOT.jar

現在,一旦服務器啟動,轉到瀏覽器並通過訪問學生服務名稱和學校服務來測試端點是否正常工作,即/student/school

http://localhost:8080/student/echoStudentName/james

http://localhost:8080/school/echoSchoolName/學軍學校

總結

這就是netflix zuul過濾器示例。我建議你自己做,通過代理添加一些更多的底層服務和路由請求,應用不同類型的過濾器並在過濾器中添加真正的邏輯。

鏈接: https://pan.baidu.com/s/1zpUBTCDNVHO4s8TAIOxKVA 提取碼: 8v7w

請在評論部分將您的問題提交給我。

快樂學習!!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM