Spring Cloud構(gòu)建微服務(wù)架構(gòu):服務(wù)網(wǎng)關(guān)(基礎(chǔ))
通過之前幾篇Spring Cloud中幾個(gè)核心組件的介紹,我們已經(jīng)可以構(gòu)建一個(gè)簡略的(不夠完善)微服務(wù)架構(gòu)了。比如下圖所示:
我們使用Spring Cloud Netflix中的Eureka實(shí)現(xiàn)了服務(wù)注冊(cè)中心以及服務(wù)注冊(cè)與發(fā)現(xiàn);而服務(wù)間通過Ribbon或Feign實(shí)現(xiàn)服務(wù)的消費(fèi)以及均衡負(fù)載;通過Spring Cloud Config實(shí)現(xiàn)了應(yīng)用多環(huán)境的外部化配置以及版本管理。為了使得服務(wù)集群更為健壯,使用Hystrix的融斷機(jī)制來避免在微服務(wù)架構(gòu)中個(gè)別服務(wù)出現(xiàn)異常時(shí)引起的故障蔓延。
在該架構(gòu)中,我們的服務(wù)集群包含:內(nèi)部服務(wù)Service A和Service B,他們都會(huì)注冊(cè)與訂閱服務(wù)至Eureka Server,而Open Service是一個(gè)對(duì)外的服務(wù),通過均衡負(fù)載公開至服務(wù)調(diào)用方。本文我們把焦點(diǎn)聚集在對(duì)外服務(wù)這塊,這樣的實(shí)現(xiàn)是否合理,或者是否有更好的實(shí)現(xiàn)方式呢?
先來說說這樣架構(gòu)需要做的一些事兒以及存在的不足:
- 首先,破壞了服務(wù)無狀態(tài)特點(diǎn)。為了保證對(duì)外服務(wù)的安全性,我們需要實(shí)現(xiàn)對(duì)服務(wù)訪問的權(quán)限控制,而開放服務(wù)的權(quán)限控制機(jī)制將會(huì)貫穿并污染整個(gè)開放服務(wù)的業(yè)務(wù)邏輯,這會(huì)帶來的最直接問題是,破壞了服務(wù)集群中REST API無狀態(tài)的特點(diǎn)。從具體開發(fā)和測試的角度來說,在工作中除了要考慮實(shí)際的業(yè)務(wù)邏輯之外,還需要額外可續(xù)對(duì)接口訪問的控制處理。
- 其次,無法直接復(fù)用既有接口。當(dāng)我們需要對(duì)一個(gè)即有的集群內(nèi)訪問接口,實(shí)現(xiàn)外部服務(wù)訪問時(shí),我們不得不通過在原有接口上增加校驗(yàn)邏輯,或增加一個(gè)代理調(diào)用來實(shí)現(xiàn)權(quán)限控制,無法直接復(fù)用原有的接口。
面對(duì)類似上面的問題,我們要如何解決呢?下面進(jìn)入本文的正題:服務(wù)網(wǎng)關(guān)!
為了解決上面這些問題,我們需要將權(quán)限控制這樣的東西從我們的服務(wù)單元中抽離出去,而最適合這些邏輯的地方就是處于對(duì)外訪問最前端的地方,我們需要一個(gè)更強(qiáng)大一些的均衡負(fù)載器,它就是本文將來介紹的:服務(wù)網(wǎng)關(guān)。
服務(wù)網(wǎng)關(guān)是微服務(wù)架構(gòu)中一個(gè)不可或缺的部分。通過服務(wù)網(wǎng)關(guān)統(tǒng)一向外系統(tǒng)提供REST API的過程中,除了具備服務(wù)路由、均衡負(fù)載功能之外,它還具備了權(quán)限控制等功能。Spring Cloud Netflix中的Zuul就擔(dān)任了這樣的一個(gè)角色,為微服務(wù)架構(gòu)提供了前門保護(hù)的作用,同時(shí)將權(quán)限控制這些較重的非業(yè)務(wù)邏輯內(nèi)容遷移到服務(wù)路由層面,使得服務(wù)集群主體能夠具備更高的可復(fù)用性和可測試性。
下面我們通過實(shí)例例子來使用一下Zuul來作為服務(wù)的路有功能。
準(zhǔn)備工作
在構(gòu)建服務(wù)網(wǎng)關(guān)之前,我們先準(zhǔn)備一下網(wǎng)關(guān)內(nèi)部的微服務(wù),可以直接使用前幾篇編寫的內(nèi)容,比如:
- eureka-client
- eureka-consumer
由于我們用了基于eureka的服務(wù),所以我們可以使用我的公益注冊(cè)中心:http://eureka.didispace.com/
這些服務(wù)可從我的倉庫中直接獲取:
Github:https://github.com/dyc87112/SpringCloud-Learning
碼云:https://gitee.com/didispace/SpringCloud-Learning
在啟動(dòng)了eureka-client和eureka-consumer的實(shí)例之后,所有的準(zhǔn)備工作就以就緒,下面我們來試試使用Spring Cloud Zuul來實(shí)現(xiàn)服務(wù)網(wǎng)關(guān)的功能。
構(gòu)建服務(wù)網(wǎng)關(guān)
使用Spring Cloud Zuul來構(gòu)建服務(wù)網(wǎng)關(guān)的基礎(chǔ)步驟非常簡單,只需要下面幾步:
- 創(chuàng)建一個(gè)基礎(chǔ)的Spring Boot項(xiàng)目,命名為:api-gateway。并在pom.xml中引入依賴:
- <parent>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-parent</artifactId>
- <version>1.5.4.RELEASE</version>
- <relativePath/>
- </parent>
- <dependencies>
- <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>Dalston.SR1</version>
- <type>pom</type>
- <scope>import</scope>
- </dependency>
- </dependencies>
- </dependencyManagement>
- 創(chuàng)建應(yīng)用主類,并使用@EnableZuulProxy注解開啟Zuul的功能。
- @EnableZuulProxy
- @SpringCloudApplication
- public class Application {
- public static void main(String[] args) {
- new SpringApplicationBuilder(Application.class).web(true).run(args);
- }
- }
創(chuàng)建配置文件application.yaml,并加入服務(wù)名、端口號(hào)、eureka注冊(cè)中心的地址:
- spring:
- application:
- name: api-gateway
- server:
- port: 1101
- eureka:
- client:
- serviceUrl:
- defaultZone: http://eureka.didispace.com/eureka/
到這里,一個(gè)基于Spring Cloud Zuul服務(wù)網(wǎng)關(guān)就已經(jīng)構(gòu)建完畢。啟動(dòng)該應(yīng)用,一個(gè)默認(rèn)的服務(wù)網(wǎng)關(guān)就構(gòu)建完畢了。由于Spring Cloud Zuul在整合了Eureka之后,具備默認(rèn)的服務(wù)路由功能,即:當(dāng)我們這里構(gòu)建的api-gateway應(yīng)用啟動(dòng)并注冊(cè)到eureka之后,服務(wù)網(wǎng)關(guān)會(huì)發(fā)現(xiàn)上面我們啟動(dòng)的兩個(gè)服務(wù)eureka-client和eureka-consumer,這時(shí)候Zuul就會(huì)創(chuàng)建兩個(gè)路由規(guī)則。每個(gè)路由規(guī)則都包含兩部分,一部分是外部請(qǐng)求的匹配規(guī)則,另一部分是路由的服務(wù)ID。針對(duì)當(dāng)前示例的情況,Zuul會(huì)創(chuàng)建下面的兩個(gè)路由規(guī)則:
- 轉(zhuǎn)發(fā)到eureka-client服務(wù)的請(qǐng)求規(guī)則為:/eureka-client/**
- 轉(zhuǎn)發(fā)到eureka-consumer服務(wù)的請(qǐng)求規(guī)則為:/eureka-consumer/**
最后,我們可以通過訪問1101端口的服務(wù)網(wǎng)關(guān)來驗(yàn)證上述路由的正確性:
- 比如訪問:http://localhost:1101/eureka-client/dc ,該請(qǐng)求將最終被路由到eureka-client的/dc接口上。
本篇小結(jié)
本篇,我們介紹了構(gòu)建服務(wù)網(wǎng)關(guān)的基礎(chǔ)。通過上面的構(gòu)建內(nèi)容,我們已經(jīng)為所有內(nèi)部服務(wù)提供了一個(gè)統(tǒng)一的對(duì)外入口,同時(shí)對(duì)于服務(wù)的路由都是自動(dòng)創(chuàng)建了,減少了傳統(tǒng)方式大量的運(yùn)維配置工作。
【本文為51CTO專欄作者“翟永超”的原創(chuàng)稿件,轉(zhuǎn)載請(qǐng)通過51CTO聯(lián)系作者獲取授權(quán)】