您好,登錄后才能下訂單哦!
這篇文章將為大家詳細講解有關spring cloud如何使用Zuul實現API網關服務問題,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。
通過前面幾次的分享,我們了解了微服務架構的幾個核心設施,通過這些組件我們可以搭建簡單的微服務架構系統。比如通過Spring Cloud Eureka搭建高可用的服務注冊中心并實現服務的注冊和發現;
通過Spring Cloud Ribbon或Feign進行負載均衡;通過Spring Cloud Hystrix進行服務容錯保護以避免故障蔓延。微服務搭建好了之后我們肯定會提供給外部系統一些統一的RESTFul API服務接口進行調用,
但是當外部系統調用我們的RESTful API的時候,怎么確定它需要的功能具體是哪個服務提供的呢?這個就涉及到一個路由規則和服務實例列表的維護問題。
這就引入了我們今天的主角--Spring Cloud Zuul,它是基于Netflix Zuul實現的API網關組件。它可以解決兩個大問題:
就是我們上面提到的路由規則和服務實例的維護問題
對于一些校驗(比如登錄校驗等)冗余問題。 按照我們的習慣的做法,是在每個服務中都需要加入這些校驗,但是這樣會導致代碼冗余并且維護也比較麻煩,有了Spring Cloud Zuul這個網關服務之后,我們可以將這些共通的校驗放到網關里面統一維護。
好,接下來我們就來看下怎么實現這個網關服務。
一、構建網關,配置路由
這里我們還是需要使用到前面的hello-service和feign-consumer服務。我們之前把feign-consumer作為服務消費者,但是別忘了在eureka體系里面,每個服務既是服務提供者又是服務消費者,所以feign-consumer也是一個服務提供者,并且http://localhost:9001/feign-consumer等接口就是它提供的服務。
接下來我們構建一個網關服務,代碼結構如下:
代碼實現步驟:
新建maven工程api-gateway
修改POM文件
<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.sam</groupId> <artifactId>api-gateway</artifactId> <version>0.0.1-SNAPSHOT</version> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.1.RELEASE</version> </parent> <properties> <javaVersion>1.8</javaVersion> </properties> <!-- 使用dependencyManagement進行版本管理 --> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Camden.SR6</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <!-- 引入zuul依賴 , 它依賴了spring-boot-starter-actuator/spring-boot-starter-hystrix/spring-boot-starter-ribbon--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zuul</artifactId> </dependency> </dependencies> </project>
新建啟動類
/** * @EnableZuulProxy 開啟Zuul 的API網關服務功能 * */ @EnableZuulProxy @SpringCloudApplication public class GateWayApp { public static void main(String[] args) { SpringApplication.run(GateWayApp.class, args); } }
新建application.properties
server.port=5555 spring.application.name=api-gateway #增加路由規則的配置 #通過zuul.routes.<route>.path和zuul.routes.<route>.url進行配置,<route>為路由的名字,可以任意指定,但是一組path和url的路由名要相同 #如下面的例子:所有滿足/api-a/** 規則的訪問都會被路由轉發到//localhost:9001的地址 #也就是說,我們訪問http://localhost:5555/api-a/hello的時候,API網關服務就會將該請#求路由到 http://localhost:9001/hello提供的微服務接口上 zuul.routes.api-a.path=/api-a/** zuul.routes.api-a.url=http://localhost:9001 zuul.routes.api-b.path=/api-b/** zuul.routes.api-b.url=http://localhost:9090
測試,啟動eureka、hello-service、feign-consumer以及本次新加的api-gateway服務,然后訪問http://localhost:5555/api-a/feign-consumer
成功訪問到了feign-consumer的服務接口--feign-consonsumer。
以上步驟實現了傳統路由的配置,這種配置有個大的缺點,就是需要手工在application.properties文件中進行路由規則的配置,當服務很多的時候,維護工作量就會很大。為了減小維護成本,還有另外一種路由--面向服務的路由。
二、面向服務的路由
Spring Cloud Zuul和Eureka進行整合,我們可以讓路由的path不是映射具體的url,而是具體的某個服務,而服務的url則交給Eureka服務發現機制自動維護,這類路由就是面向服務的路由。具體代碼配置如下:
修改POM文件,引入Eureka依賴
<!-- 引入eureka依賴 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency>
修改application.properties配置文件
server.port=5555 spring.application.name=api-gateway zuul.routes.api-a.path=/api-a/** #這里用serviceId代替url,用服務名代替ip+端口號 zuul.routes.api-a.serviceId=hello-service eureka.client.service-url.defaultZone=http://localhost:1111/eureka
注意:zuul.routes.api-a.url=hello-service也能實現功能,但是它不能進行正常的負載均衡和容錯保護。
測試,訪問http://localhost:5555/api-a/hello
訪問成功。
三、服務路由的默認規則
在面向服務的路由中,由于<route>名字是隨意起的,那么是不是可以這樣:
zuul.routes.hello-service.path=/hello-service/** zuul.routes.hello-service.serviceId=hello-service
<route>名字就是服務名,其實在實際的應用中,我們往往就是這樣命名的。如果有這樣的規則的話,那Zuul就可以幫我們默認實現這樣的功能,進一步省去了配置的麻煩。
我們來做個實驗,將配置文件改為:
server.port=5555 spring.application.name=api-gateway eureka.client.service-url.defaultZone=http://localhost:1111/eureka
然后頁面訪問驗證
訪問成功。
但是由于默認情況下,Eureka上的服務都會被Zuul創建默認的映射關系來進行路由,使得我們不想對外開放的服務也被外部訪問到,這個時候可以通過配置zuul.ignored-services來進行配置不需要自動創建路由的規則。當zuul.ignored-services=*的時候,所有的服務都不會自動創建路由規則,這個時候需要通過前面的配置進行相關路由配置了。
================華麗的分割線===================
前面說了那么多都是圍繞一個問題展開的:路由規則和服務實例的維護問題,那么怎么解決第二個問題(校驗冗余問題)呢?
四、請求過濾
為了在API網關中實現對客戶端請求的校驗,我們可以通過過濾器來實現對請求的攔截和過濾,實現方法比較簡單,只需要繼承ZuulFilter抽象類并實現其四個方法就行了。
修改api-gateway:
新增過濾器類
/** * 繼承ZuulFilter,并且實現其4個接口 * * 用來進行請求過濾 * */ public class AccessFilter extends ZuulFilter { Logger logger = LoggerFactory.getLogger(AccessFilter.class); /* * shouldFilter 判斷該過濾器是否需要被執行 * * 這里直接返回true,表示該過濾器對所有請求都會生效。 * 實際運用中我們可以利用該函數指定過濾器的有效范圍 */ @Override public boolean shouldFilter() { return true; } /* * 過濾器的具體邏輯 * * 這里我們通過ctx.setSendZuulResponse(false)讓zuul過來請求,不對其進行路由 * 然后通過ctx.setResponseStatusCode(401)設置了返回的錯誤碼 * */ @Override public Object run() { RequestContext context = RequestContext.getCurrentContext(); HttpServletRequest request = context.getRequest(); Object accessToken = request.getParameter("accessToken"); logger.info("send {} request to {}", request.getMethod(),request.getRequestURL().toString()); if(accessToken == null) { context.setSendZuulResponse(false); context.setResponseStatusCode(401); } return null; } /* filterType 返回過濾器類型 * 他決定了過濾器在請求的哪個生命周期中執行。這里定義為pre,代表會在請求被路由前執行。 * * pre:請求執行之前filter * route: 處理請求,進行路由 * post: 請求處理完成后執行的filter * error:出現錯誤時執行的filter */ @Override public String filterType() { return "pre"; } /* * filterOrder 返回過濾器的執行順序 * * 當請求在一個階段有多個過濾器是,需要根據該方法的返回值來一次執行 * */ @Override public int filterOrder() { return 0; } }
修改啟動類
/** * @EnableZuulProxy 開啟Zuul 的API網關服務功能 * */ @EnableZuulProxy @SpringCloudApplication public class GateWayApp { //追加bean的是實現 @Bean public AccessFilter accessFilter() { return new AccessFilter(); } public static void main(String[] args) { SpringApplication.run(GateWayApp.class, args); } }
測試
)訪問http://localhost:5555/hello-service/hello,訪問失敗
)訪問http://localhost:5555/hello-service/hello?accessToken=token,正常訪問
修改后的代碼結構:
五、拓展延伸
其實路由功能在真正運行時,他的路由映射和請求轉發都是由幾個不同的過濾器完成的。
路由映射主要通過pre類型的過濾器完成,他將請求路徑與配置的路由規則進行匹配,找到需要轉發的目標地址。
而請求轉發的部分則是由route類型的過濾器完成的,對pre類型過濾器獲取的路由地址進行轉發。
所以,過濾器可以說是Zuul實現API網關功能最為核心的部件,每一個進入Zuul的HTTP請求都會經過一系列的過濾器處理鏈得到請求響應并返回給客戶端。
關于“spring cloud如何使用Zuul實現API網關服務問題”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,使各位可以學到更多知識,如果覺得文章不錯,請把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。