Spring Cloud Zuul:API網關服務

SpringBoot實戰電商項目mall(20k+star)地址:github.com/macrozheng/…java

摘要

Spring Cloud Zuul 是Spring Cloud Netflix 子項目的核心組件之一,能夠做爲微服務架構中的API網關使用,支持動態路由與過濾功能,本文將對其用法進行詳細介紹。git

Zuul簡介

API網關爲微服務架構中的服務提供了統一的訪問入口,客戶端經過API網關訪問相關服務。API網關的定義相似於設計模式中的門面模式,它至關於整個微服務架構中的門面,全部客戶端的訪問都經過它來進行路由及過濾。它實現了請求路由、負載均衡、校驗過濾、服務容錯、服務聚合等功能。github

建立一個zuul-proxy模塊

這裏咱們建立一個zuul-proxy模塊來演示zuul的經常使用功能。web

在pom.xml中添加相關依賴

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
複製代碼

在application.yml中進行配置

server:
 port: 8801
spring:
 application:
 name: zuul-proxy
eureka:
 client:
 register-with-eureka: true
 fetch-registry: true
 service-url:
 defaultZone: http://localhost:8001/eureka/
複製代碼

在啓動類上添加@EnableZuulProxy註解來啓用Zuul的API網關功能

@EnableZuulProxy
@EnableDiscoveryClient
@SpringBootApplication
public class ZuulProxyApplication {

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

}
複製代碼

經常使用功能

啓動相關服務

這裏咱們經過啓動eureka-server,兩個user-service,feign-service和zuul-proxy來演示Zuul的經常使用功能,啓動後註冊中心顯示以下。spring

配置路由規則

  • 咱們能夠經過修改application.yml中的配置來配置路由規則,這裏咱們將匹配/userService/**的請求路由到user-service服務上去,匹配/feignService/**的請求路由到feign-service上去。
zuul:
 routes: #給服務配置路由
 user-service:
 path: /userService/**
 feign-service:
 path: /feignService/**
複製代碼

默認路由規則

  • Zuul和Eureka結合使用,能夠實現路由的自動配置,自動配置的路由以服務名稱爲匹配路徑,至關於以下配置:
zuul:
 routes: #給服務配置路由
 user-service:
 path: /user-service/**
 feign-service:
 path: /feign-service/**
複製代碼
zuul:
 ignored-services: user-service,feign-service #關閉默認路由配置
複製代碼

負載均衡功能

屢次調用http://localhost:8801/user-service/user/1進行測試,能夠發現運行在8201和8202的user-service服務交替打印以下信息。

2019-10-05 10:31:58.738  INFO 11520 --- [nio-8202-exec-5] c.macro.cloud.controller.UserController  : 根據id獲取用戶信息,用戶名稱爲:macro
2019-10-05 10:32:00.356  INFO 11520 --- [nio-8202-exec-6] c.macro.cloud.controller.UserController  : 根據id獲取用戶信息,用戶名稱爲:macro
複製代碼

配置訪問前綴

咱們能夠經過如下配置來給網關路徑添加前綴,此處添加了/proxy前綴,這樣咱們須要訪問http://localhost:8801/proxy/user-service/user/1才能訪問到user-service中的接口。

zuul:
 prefix: /proxy #給網關路由添加前綴
複製代碼

Header過濾及重定向添加Host

  • Zuul在請求路由時,默認會過濾掉一些敏感的頭信息,如下配置能夠防止路由時的Cookie及Authorization的丟失:
zuul:
 sensitive-headers: Cookie,Set-Cookie,Authorization #配置過濾敏感的請求頭信息,設置爲空就不會過濾
複製代碼
  • Zuul在請求路由時,不會設置最初的host頭信息,如下配置能夠解決:
zuul:
 add-host-header: true #設置爲true重定向是會添加host請求頭
複製代碼

查看路由信息

咱們能夠經過SpringBoot Actuator來查看Zuul中的路由信息。

  • 在pom.xml中添加相關依賴:
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
複製代碼
  • 修改application.yaml配置文件,開啓查看路由的端點:
management:
 endpoints:
 web:
 exposure:
 include: 'routes'
複製代碼

過濾器

路由與過濾是Zuul的兩大核心功能,路由功能負責將外部請求轉發到具體的服務實例上去,是實現統一訪問入口的基礎,過濾功能負責對請求過程進行額外的處理,是請求校驗過濾及服務聚合的基礎。

過濾器類型

Zuul中有如下幾種典型的過濾器類型。

  • pre:在請求被路由到目標服務前執行,好比權限校驗、打印日誌等功能;
  • routing:在請求被路由到目標服務時執行,這是使用Apache HttpClient或Netflix Ribbon構建和發送原始HTTP請求的地方;
  • post:在請求被路由到目標服務後執行,好比給目標服務的響應添加頭信息,收集統計數據等功能;
  • error:請求在其餘階段發生錯誤時執行。

過濾器的生命週期

下圖描述了一個HTTP請求到達API網關後,如何在各類不一樣類型的過濾器中流轉的過程。

來自Zuul官網

自定義過濾器

接下來咱們自定義一個過濾器來演示下過濾器的做用。

添加PreLogFilter類繼承ZuulFilter

這是一個前置過濾器,用於在請求路由到目標服務前打印請求日誌。

/** * Created by macro on 2019/9/9. */
@Component
public class PreLogFilter extends ZuulFilter {
    private Logger LOGGER = LoggerFactory.getLogger(this.getClass());

    /** * 過濾器類型,有pre、routing、post、error四種。 */
    @Override
    public String filterType() {
        return "pre";
    }

    /** * 過濾器執行順序,數值越小優先級越高。 */
    @Override
    public int filterOrder() {
        return 1;
    }

    /** * 是否進行過濾,返回true會執行過濾。 */
    @Override
    public boolean shouldFilter() {
        return true;
    }

    /** * 自定義的過濾器邏輯,當shouldFilter()返回true時會執行。 */
    @Override
    public Object run() throws ZuulException {
        RequestContext requestContext = RequestContext.getCurrentContext();
        HttpServletRequest request = requestContext.getRequest();
        String host = request.getRemoteHost();
        String method = request.getMethod();
        String uri = request.getRequestURI();
        LOGGER.info("Remote host:{},method:{},uri:{}", host, method, uri);
        return null;
    }
}
複製代碼

過濾器功能演示

添加過濾器後,咱們訪問http://localhost:8801/user-service/user/1測試下,會打印以下日誌。

2019-10-05 15:13:10.232  INFO 11040 --- [nio-8801-exec-7] com.macro.cloud.filter.PreLogFilter      : Remote host:0:0:0:0:0:0:0:1,method:GET,uri:/user-service/user/1
複製代碼

核心過濾器

過濾器名稱 過濾類型 優先級 過濾器的做用
ServletDetectionFilter pre -3 檢測當前請求是經過DispatcherServlet處理運行的仍是ZuulServlet運行處理的。
Servlet30WrapperFilter pre -2 對原始的HttpServletRequest進行包裝。
FormBodyWrapperFilter pre -1 將Content-Type爲application/x-www-form-urlencoded或multipart/form-data的請求包裝成FormBodyRequestWrapper對象。
DebugFilter route 1 根據zuul.debug.request的配置來決定是否打印debug日誌。
PreDecorationFilter route 5 對當前請求進行預處理以便執行後續操做。
RibbonRoutingFilter route 10 經過Ribbon和Hystrix來向服務實例發起請求,並將請求結果進行返回。
SimpleHostRoutingFilter route 100 只對請求上下文中有routeHost參數的進行處理,直接使用HttpClient向routeHost對應的物理地址進行轉發。
SendForwardFilter route 500 只對請求上下文中有forward.to參數的進行處理,進行本地跳轉。
SendErrorFilter post 0 當其餘過濾器內部發生異常時的會由它來進行處理,產生錯誤響應。
SendResponseFilter post 1000 利用請求上下文的響應信息來組織請求成功的響應內容。

禁用過濾器

  • 咱們能夠對過濾器進行禁用的配置,配置格式以下:
zuul:
 filterClassName:
 filter:
 disable: true 
複製代碼
  • 如下是禁用PreLogFilter的示例配置:
zuul:
 PreLogFilter:
 pre:
 disable: true 
複製代碼

Ribbon和Hystrix的支持

因爲Zuul自動集成了Ribbon和Hystrix,因此Zuul天生就有負載均衡和服務容錯能力,咱們能夠經過Ribbon和Hystrix的配置來配置Zuul中的相應功能。

  • 可使用Hystrix的配置來設置路由轉發時HystrixCommand的執行超時時間:
hystrix:
 command: #用於控制HystrixCommand的行爲
 default:
 execution:
 isolation:
 thread:
 timeoutInMilliseconds: 1000 #配置HystrixCommand執行的超時時間,執行超過該時間會進行服務降級處理
複製代碼
  • 可使用Ribbon的配置來設置路由轉發時請求鏈接及處理的超時時間:
ribbon: #全局配置
 ConnectTimeout: 1000 #服務請求鏈接超時時間(毫秒)
 ReadTimeout: 3000 #服務請求處理超時時間(毫秒)
複製代碼

經常使用配置

zuul:
 routes: #給服務配置路由
 user-service:
 path: /userService/**
 feign-service:
 path: /feignService/**
 ignored-services: user-service,feign-service #關閉默認路由配置
 prefix: /proxy #給網關路由添加前綴
 sensitive-headers: Cookie,Set-Cookie,Authorization #配置過濾敏感的請求頭信息,設置爲空就不會過濾
 add-host-header: true #設置爲true重定向是會添加host請求頭
 retryable: true # 關閉重試機制
 PreLogFilter:
 pre:
 disable: false #控制是否啓用過濾器
複製代碼

使用到的模塊

springcloud-learning
├── eureka-server -- eureka註冊中心
├── user-service -- 提供User對象CRUD接口的服務
├── feign-service -- feign服務調用測試服務
└── zuul-proxy -- zuul做爲網關的測試服務
複製代碼

項目源碼地址

github.com/macrozheng/…

公衆號

mall項目全套學習教程連載中,關注公衆號第一時間獲取。

公衆號圖片
相關文章
相關標籤/搜索