Spring Cloud Zuul:API網(wǎng)關服務

Spring Cloud Zuul:API網(wǎng)關服務

Spring Cloud Zuul 是Spring Cloud Netflix 子項目的核心組件之一,可以作為微服務架構(gòu)中的API網(wǎng)關使用,支持動態(tài)路由與過濾功能,本文將對其用法進行詳細介紹。

Zuul簡介

API網(wǎng)關為微服務架構(gòu)中的服務提供了統(tǒng)一的訪問入口,客戶端通過API網(wǎng)關訪問相關服務。API網(wǎng)關的定義類似于設計模式中的門面模式,它相當于整個微服務架構(gòu)中的門面,所有客戶端的訪問都通過它來進行路由及過濾。它實現(xiàn)了請求路由、負載均衡、校驗過濾、服務容錯、服務聚合等功能。

創(chuàng)建一個zuul-proxy模塊

這里我們創(chuàng)建一個zuul-proxy模塊來演示zuul的常用功能。

在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>Copy to clipboardErrorCopied

在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/Copy to clipboardErrorCopied

在啟動類上添加@EnableZuulProxy注解來啟用Zuul的API網(wǎng)關功能

@EnableZuulProxy@EnableDiscoveryClient@SpringBootApplicationpublicclassZuulProxyApplication{publicstaticvoidmain(String[]args){SpringApplication.run(ZuulProxyApplication.class,args);}}Copy to clipboardErrorCopied

常用功能

啟動相關服務

這里我們通過啟動eureka-server,兩個user-service,feign-service和zuul-proxy來演示Zuul的常用功能,啟動后注冊中心顯示如下。

配置路由規(guī)則

我們可以通過修改application.yml中的配置來配置路由規(guī)則,這里我們將匹配/userService/**的請求路由到user-service服務上去,匹配/feignService/**的請求路由到feign-service上去。

zuul:

? routes: #給服務配置路由

? ? user-service:

? ? ? path: /userService/**

? ? feign-service:

? ? ? path: /feignService/**Copy to clipboardErrorCopied

訪問http://localhost:8801/userService/user/1可以發(fā)現(xiàn)請求路由到了user-service上了;

訪問http://localhost:8801/feignService/user/1可以發(fā)現(xiàn)請求路由到了feign-service上了。

默認路由規(guī)則

Zuul和Eureka結(jié)合使用,可以實現(xiàn)路由的自動配置,自動配置的路由以服務名稱為匹配路徑,相當于如下配置:

zuul:

? routes: #給服務配置路由

? ? user-service:

? ? ? path: /user-service/**

? ? feign-service:

? ? ? path: /feign-service/**Copy to clipboardErrorCopied

訪問http://localhost:8801/user-service/user/1同樣可以路由到了user-service上了;

訪問http://localhost:8801/feign-service/user/1同樣可以路由到了feign-service上了。

如果不想使用默認的路由規(guī)則,可以添加以下配置來忽略默認路由配置:

zuul:

? ignored-services: user-service,feign-service #關閉默認路由配置Copy to clipboardErrorCopied

負載均衡功能

多次調(diào)用http://localhost:8801/user-service/user/1進行測試,可以發(fā)現(xiàn)運行在8201和8202的user-service服務交替打印如下信息。

2019-10-0510:31:58.738? INFO11520---[nio-8202-exec-5]c.macro.cloud.controller.UserController:根據(jù)id獲取用戶信息,用戶名稱為:macro2019-10-0510:32:00.356? INFO11520---[nio-8202-exec-6]c.macro.cloud.controller.UserController:根據(jù)id獲取用戶信息,用戶名稱為:macroCopy to clipboardErrorCopied

配置訪問前綴

我們可以通過以下配置來給網(wǎng)關路徑添加前綴,此處添加了/proxy前綴,這樣我們需要訪問http://localhost:8801/proxy/user-service/user/1才能訪問到user-service中的接口。

zuul:

? prefix: /proxy #給網(wǎng)關路由添加前綴Copy to clipboardErrorCopied

Header過濾及重定向添加Host

Zuul在請求路由時,默認會過濾掉一些敏感的頭信息,以下配置可以防止路由時的Cookie及Authorization的丟失:

zuul:

? sensitive-headers: Cookie,Set-Cookie,Authorization #配置過濾敏感的請求頭信息,設置為空就不會過濾Copy to clipboardErrorCopied

Zuul在請求路由時,不會設置最初的host頭信息,以下配置可以解決:

zuul:

? add-host-header: true #設置為true重定向是會添加host請求頭Copy to clipboardErrorCopied

查看路由信息

我們可以通過SpringBoot Actuator來查看Zuul中的路由信息。

在pom.xml中添加相關依賴:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency>Copy to clipboardErrorCopied

修改application.yaml配置文件,開啟查看路由的端點:

management:

? endpoints:

? ? web:

? ? ? exposure:

? ? ? ? include: 'routes'Copy to clipboardErrorCopied

通過訪問http://localhost:8801/actuator/routes查看簡單路由信息:

通過訪問http://localhost:8801/actuator/routes/details查看詳細路由信息:

過濾器

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

過濾器類型

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

pre:在請求被路由到目標服務前執(zhí)行,比如權限校驗、打印日志等功能;

routing:在請求被路由到目標服務時執(zhí)行,這是使用Apache HttpClient或Netflix Ribbon構(gòu)建和發(fā)送原始HTTP請求的地方;

post:在請求被路由到目標服務后執(zhí)行,比如給目標服務的響應添加頭信息,收集統(tǒng)計數(shù)據(jù)等功能;

error:請求在其他階段發(fā)生錯誤時執(zhí)行。

過濾器的生命周期

下圖描述了一個HTTP請求到達API網(wǎng)關后,如何在各種不同類型的過濾器中流轉(zhuǎn)的過程。

自定義過濾器

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

添加PreLogFilter類繼承ZuulFilter

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

/**

* Created by macro on 2019/9/9.

*/@ComponentpublicclassPreLogFilterextendsZuulFilter{privateLoggerLOGGER=LoggerFactory.getLogger(this.getClass());/**

? ? * 過濾器類型,有pre、routing、post、error四種。

? ? */@OverridepublicStringfilterType(){return"pre";}/**

? ? * 過濾器執(zhí)行順序,數(shù)值越小優(yōu)先級越高。

? ? */@OverridepublicintfilterOrder(){return1;}/**

? ? * 是否進行過濾,返回true會執(zhí)行過濾。

? ? */@OverridepublicbooleanshouldFilter(){returntrue;}/**

? ? * 自定義的過濾器邏輯,當shouldFilter()返回true時會執(zhí)行。

? ? */@OverridepublicObjectrun()throwsZuulException{RequestContextrequestContext=RequestContext.getCurrentContext();HttpServletRequestrequest=requestContext.getRequest();Stringhost=request.getRemoteHost();Stringmethod=request.getMethod();Stringuri=request.getRequestURI();LOGGER.info("Remote host:{},method:{},uri:{}",host,method,uri);returnnull;}}Copy to clipboardErrorCopied

過濾器功能演示

添加過濾器后,我們訪問http://localhost:8801/user-service/user/1測試下,會打印如下日志。

2019-10-0515:13:10.232? INFO11040---[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/1Copy to clipboardErrorCopied

核心過濾器

過濾器名稱過濾類型優(yōu)先級過濾器的作用

ServletDetectionFilterpre-3檢測當前請求是通過DispatcherServlet處理運行的還是ZuulServlet運行處理的。

Servlet30WrapperFilterpre-2對原始的HttpServletRequest進行包裝。

FormBodyWrapperFilterpre-1將Content-Type為application/x-www-form-urlencoded或multipart/form-data的請求包裝成FormBodyRequestWrapper對象。

DebugFilterroute1根據(jù)zuul.debug.request的配置來決定是否打印debug日志。

PreDecorationFilterroute5對當前請求進行預處理以便執(zhí)行后續(xù)操作。

RibbonRoutingFilterroute10通過Ribbon和Hystrix來向服務實例發(fā)起請求,并將請求結(jié)果進行返回。

SimpleHostRoutingFilterroute100只對請求上下文中有routeHost參數(shù)的進行處理,直接使用HttpClient向routeHost對應的物理地址進行轉(zhuǎn)發(fā)。

SendForwardFilterroute500只對請求上下文中有forward.to參數(shù)的進行處理,進行本地跳轉(zhuǎn)。

SendErrorFilterpost0當其他過濾器內(nèi)部發(fā)生異常時的會由它來進行處理,產(chǎn)生錯誤響應。

SendResponseFilterpost1000利用請求上下文的響應信息來組織請求成功的響應內(nèi)容。

禁用過濾器

我們可以對過濾器進行禁用的配置,配置格式如下:

zuul:

? filterClassName:

? ? filter:

? ? ? disable: true Copy to clipboardErrorCopied

以下是禁用PreLogFilter的示例配置:

zuul:

? PreLogFilter:

? ? pre:

? ? ? disable: true Copy to clipboardErrorCopied

Ribbon和Hystrix的支持

由于Zuul自動集成了Ribbon和Hystrix,所以Zuul天生就有負載均衡和服務容錯能力,我們可以通過Ribbon和Hystrix的配置來配置Zuul中的相應功能。

可以使用Hystrix的配置來設置路由轉(zhuǎn)發(fā)時HystrixCommand的執(zhí)行超時時間:

hystrix:

? command: #用于控制HystrixCommand的行為

? ? default:

? ? ? execution:

? ? ? ? isolation:

? ? ? ? ? thread:

? ? ? ? ? ? timeoutInMilliseconds: 1000 #配置HystrixCommand執(zhí)行的超時時間,執(zhí)行超過該時間會進行服務降級處理Copy to clipboardErrorCopied

可以使用Ribbon的配置來設置路由轉(zhuǎn)發(fā)時請求連接及處理的超時時間:

ribbon: #全局配置

? ConnectTimeout: 1000 #服務請求連接超時時間(毫秒)

? ReadTimeout: 3000 #服務請求處理超時時間(毫秒)Copy to clipboardErrorCopied

常用配置

zuul:

? routes: #給服務配置路由

? ? user-service:

? ? ? path: /userService/**

? ? feign-service:

? ? ? path: /feignService/**

? ignored-services: user-service,feign-service #關閉默認路由配置

? prefix: /proxy #給網(wǎng)關路由添加前綴

? sensitive-headers: Cookie,Set-Cookie,Authorization #配置過濾敏感的請求頭信息,設置為空就不會過濾

? add-host-header: true #設置為true重定向是會添加host請求頭

? retryable: true # 關閉重試機制

? PreLogFilter:

? ? pre:

? ? ? disable: false #控制是否啟用過濾器Copy to clipboardErrorCopied

使用到的模塊

springcloud-learning

├── eureka-server -- eureka注冊中心

├── user-service -- 提供User對象CRUD接口的服務

├── feign-service -- feign服務調(diào)用測試服務

└── zuul-proxy -- zuul作為網(wǎng)關的測試服務

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內(nèi)容