到目前爲止,咱們Spring Cloud中的內容已經介紹了不少了,Ribbon、Hystrix、Feign這些知識點你們都耳熟能詳了,咱們在前文也提到過微服務就是把一個大的項目拆分紅不少小的獨立模塊,而後經過服務治理讓這些獨立的模塊配合工做等。那麼你們來想這樣兩個問題:1.若是個人微服務中有不少個獨立服務都要對外提供服務,那麼對於開發人員或者運維人員來講,他要如何去管理這些接口?特別是當項目很是大很是龐雜的狀況下要如何管理?2.權限管理也是一個老生常談的問題,在微服務中,一個獨立的系統被拆分紅不少個獨立的模塊,爲了確保安全,我難道須要在每個模塊上都添加上相同的鑑權代碼來確保系統不被非法訪問?若是是這樣的話,那麼工做量就太大了,並且維護也很是不方便。 html
爲了解決上面提到的問題,咱們引入了API網關的概念,API網關是一個更爲智能的應用服務器,它有點相似於咱們微服務架構系統的門面,全部的外部訪問都要先通過API網關,而後API網關來實現請求路由、負載均衡、權限驗證等功能。Spring Cloud中提供的Spring Cloud Zuul實現了API網關的功能,本文咱們就先來看看Spring Cloud Zuul的一個基本使用。java
本文是Spring Cloud系列的第十九篇文章,瞭解前十八篇文章內容有助於更好的理解本文: spring
1.使用Spring Cloud搭建服務註冊中心
2.使用Spring Cloud搭建高可用服務註冊中心
3.Spring Cloud中服務的發現與消費
4.Eureka中的核心概念
5.什麼是客戶端負載均衡
6.Spring RestTemplate中幾種常見的請求方式
7.RestTemplate的逆襲之路,從發送請求到負載均衡
8.Spring Cloud中負載均衡器概覽
9.Spring Cloud中的負載均衡策略
10.Spring Cloud中的斷路器Hystrix
11.Spring Cloud自定義Hystrix請求命令
12.Spring Cloud中Hystrix的服務降級與異常處理
13.Spring Cloud中Hystrix的請求緩存
14.Spring Cloud中Hystrix的請求合併
15.Spring Cloud中Hystrix儀表盤與Turbine集羣監控
16.Spring Cloud中聲明式服務調用Feign
17.Spring Cloud中Feign的繼承特性
18.Spring Cloud中Feign配置詳解api
網關的構建咱們經過下面三個步驟來實現。緩存
首先咱們建立一個普通的Spring Boot工程名爲api-gateway,而後添加相關依賴,這裏咱們主要添加兩個依賴spring-cloud-starter-zuul和spring-cloud-starter-eureka,spring-cloud-starter-zuul依賴中則包含了ribbon、hystrix、actuator等,以下:安全
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.7.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> <spring-cloud.version>Dalston.SR3</spring-cloud.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zuul</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
而後在入口類上添加@EnableZuulProxy註解表示開啓Zuul的API網關服務功能,以下:服務器
@SpringBootApplication @EnableZuulProxy public class ApiGatewayApplication { public static void main(String[] args) { SpringApplication.run(ApiGatewayApplication.class, args); } }
application.properties文件中的配置能夠分爲兩部分,一部分是Zuul應用的基礎信息,還有一部分則是路由規則,以下:架構
# 基礎信息配置 spring.application.name=api-gateway server.port=2006 # 路由規則配置 zuul.routes.api-a.path=/api-a/** zuul.routes.api-a.serviceId=feign-consumer # API網關也將做爲一個服務註冊到eureka-server上 eureka.client.service-url.defaultZone=http://localhost:1111/eureka/
咱們在這裏配置了路由規則全部符合/api-a/**的請求都將被轉發到feign-consumer服務上,至於feign-consumer服務的地址究竟是什麼則由eureka-server去分析,咱們這裏只須要寫上服務名便可。以上面的配置爲例,若是我請求http://localhost:2006/api-a/h...接口則至關於請求http://localhost:2005/hello1(我這裏feign-consumer的地址爲http://localhost:2005),咱們在路由規則中配置的api-a是路由的名字,能夠任意定義,可是一組path和serviceId映射關係的路由名要相同。 app
OK,作好這些以後,咱們依次啓動咱們的eureka-server、provider和feign-consumer,而後訪問以下地址http://localhost:2006/api-a/h...,訪問結果以下: 負載均衡
看到這個效果說明咱們的API網關服務已經構建成功了,咱們發送的符合路由規則的請求自動被轉發到相應的服務上去處理了。
構建好了網關,接下來咱們就來看看如何利用網關來實現一個簡單的權限驗證。這裏就涉及到了Spring Cloud Zuul中的另一個核心功能:請求過濾。請求過濾有點相似於Java中Filter過濾器,先將全部的請求攔截下來,而後根據現場狀況作出不一樣的處理,這裏咱們就來看看Zuul中的過濾器要如何使用。很簡單,兩個步驟:
首先咱們定義一個過濾器繼承自ZuulFilter,以下:
public class PermisFilter extends ZuulFilter { @Override public String filterType() { return "pre"; } @Override public int filterOrder() { return 0; } @Override public boolean shouldFilter() { return true; } @Override public Object run() { RequestContext ctx = RequestContext.getCurrentContext(); HttpServletRequest request = ctx.getRequest(); String login = request.getParameter("login"); if (login == null) { ctx.setSendZuulResponse(false); ctx.setResponseStatusCode(401); ctx.addZuulResponseHeader("content-type","text/html;charset=utf-8"); ctx.setResponseBody("非法訪問"); } return null; } }
關於這個類我說以下幾點:
1.filterType方法的返回值爲過濾器的類型,過濾器的類型決定了過濾器在哪一個生命週期執行,pre表示在路由以前執行過濾器,其餘可選值還有post、error、route和static,固然也能夠自定義。
2.filterOrder方法表示過濾器的執行順序,當過濾器不少時,這個方法會有意義。
3.shouldFilter方法用來判斷過濾器是否執行,true表示執行,false表示不執行,在實際開發中,咱們能夠根據當前請求地址來決定要不要對該地址進行過濾,這裏我直接返回true。
4.run方法則表示過濾的具體邏輯,假設請求地址中攜帶了login參數的話,則認爲是合法請求,不然就是非法請求,若是是非法請求的話,首先設置ctx.setSendZuulResponse(false);表示不對該請求進行路由,而後設置響應碼和響應值。這個run方法的返回值在當前版本(Dalston.SR3)中暫時沒有任何意義,能夠返回任意值。
而後在入口類中配置相關的Bean便可,以下:
@Bean PermisFilter permisFilter() { return new PermisFilter(); }
此時,若是咱們訪問http://localhost:2006/api-a/h...,結果以下:
若是給請求地址加上login參數,則結果以下:
到這裏小夥伴們應該已經見識到Spring Cloud Zuul的強大之處了吧,API網關做爲系統的的統一入口,將微服務中的內部細節都屏蔽掉了,並且可以自動的維護服務實例,實現負載均衡的路由轉發,同時,它提供的過濾器爲全部的微服務提供統一的權限校驗機制,使得服務自身只須要關注業務邏輯便可。
Zuul的入門知識咱們就先介紹到這裏,小夥伴們有問題歡迎留言討論。
更多JavaEE資料請關注公衆號: