內容
單體應用中各個模塊拆分成獨立的系統,逐步演變出微服務架構。為了屏蔽微服務內部的復雜調用,引入了Zuul作為微服務調用的統一入口。本文介紹了Zuul的常用配置和使用,並通過簡單的演示進行了測試。
版本
IDE:IDEA 2017.2.2 x64
JDK:1.8.0_171
manve:3.3.3
SpringBoot:1.5.9.RELEASE
SpringCloud:Dalston.SR1
適合人群
Java開發人員
說明
轉載請說明出處:SpringCloud從入門到進階(五)——路由接入Zuul及其單點部署
參考
SpringCloud從入門到進階(二)——注冊中心Eureka的偽分布式部署
Zuul介紹
路由器的概念想必大家都接觸過——家庭上網必備無線路由器。它將手機、電腦等設備的聯網請求轉發到電信運行商的網關,實現設備的網絡通信。Zuul是微服務架構中扮演路由角色的組件,它是基於JVM的路由器,同時是服務端的負載均衡器。所有的外部微服務請求都會經過Zuul,由Zuul根據URL的信息將請求轉發給對應的微服務進行處理。
Zuul內置了Ribbon和hystrix,從eureka中獲取微服務實例的信息,由Ribbon確定接收請求的微服務實例。所有的請求都通過hystrix處理,因而可以通過Hystrix的監控工具觀察請求熔斷的情況。一旦接口熔斷環路開啟,Zuul將不會再將請求轉發給該服務。
項目路徑
pom.xml
配置maven的依賴文件pom.xml,引入SpringBoot,SpringCloud,Eureka Client和Zuul的依賴,以及Spring Boot打包的Maven插件。
<?xml version="1.0" encoding="UTF-8"?> <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.leo</groupId> <artifactId>zuul</artifactId> <version>1.0-SNAPSHOT</version> <!-- 通過繼承的方式引入spring boot --> <!--parent標簽用於指定父pom--> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.9.RELEASE</version> </parent> <!--properties標簽用於聲明一些常量,例如源碼編碼為UTF-8,輸出代碼也為UTF-8,Java版本為1.8--> <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.SR1</spring-cloud.version> </properties> <dependencies> <!--eureka client--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency> <!--zuul組件實現網關的路由轉發和負載均衡--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zuul</artifactId> </dependency> </dependencies> <!--子Module不會繼承該依賴,除非顯示聲明--> <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> <!-- Spring Boot的Maven插件,使用Maven插件的方式來啟動Spring Boot工程 如果不添加該插件在使用mvn命令打包的jar有問題,執行時會報錯:xxx.jar中沒有主清單屬性--> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <executions> <execution> <goals> <goal>repackage</goal> </goals> </execution> </executions> </plugin> </plugins> </build> </project>
yaml
本示例以單點的方式部署Zuul,將所有profiles的公共配置提取到yaml文件的頂部,以便后期進行高可用版本的部署。此外進行了Eureka Client、Zuul路由,logback日志等相關內容的配置。
eureka.instance.instance-id,配置了實例的id。
eureka.client.service-url.defaultZone,配置了Eureka Server集群的地址。
Zuul路由的配置
zuul.prefix屬性,為所有請求添加統一的前綴,默認為空串,即不添加前綴。可以通過該屬性實現API接口的版本號控制,比如此處設置為"/v1"表示API接口為v1版本,注意前綴要以"/"開頭。
zuul.routes屬性,用於配置路由器的路由信息。其中的zuul.routes.path屬性表示url的匹配規則,zuul.routes.serviceId表示處理該路由的微服務的application name。
本示例配置了兩條路由,名稱為routeA和routeB,分別將"/routea"和"/routeb"開頭的url請求轉發給微服務application-serviceA和application-serviceB進行處理。初次接觸SpringCloud的童鞋要注意,這里的application-serviceA和application-serviceB都是微服務的應用名,即spring.application.name屬性;不是eureka client的實例名稱,eureka.instance.instance-id屬性。
logging.file屬性,配置了日志文件的位置和名稱。日志的配置默認讀取classpath下的logback-spring.xml。
spring: application: name: application-gatewayservice profiles: active: peer1 #Zuul的配置 zuul: #通過zuul.prefix屬性配置前綴,為所有請求添加統一的前綴,默認為空串,即不添加前綴。 #可以通過該屬性實現API接口的版本號控制,注意前綴要以"/"開頭,此處設置為"/v1"表示API接口為v1版本。 prefix: /v1 #如果某服務存在多個實例,Zuul結合Ribbon會做負載均衡,將請求均分的部分路由到不同的服務實例 #zuul.routes屬性配置路由器的路由信息。 routes: #路由的名稱是用戶自定義的,需要指定它的path和serviceld,二者規定了將指定規則的請求Url路由到指定的Serviceld #符合/routea/** 規則的請求轉發給微服務springcloud-serviceA routeA: path: /routea/** serviceId: application-serviceA #此處是spring的applicationname,即Eureka的服務名,而非instance-id 實例名。 #符合/routeb/** 規則的請求轉發給微服務springcloud-serviceB routeB: path: /routeb/** serviceId: application-serviceB #指明日志存放位置 logging: file: logs/application-gatewayservice-${server.port}.logs #配置了Eureka Server集群的地址 eureka: client: service-url: defaultZone: http://172.26.125.114:7001/eureka,http://172.26.125.115:7001/eureka,http://172.26.125.118:7001/eureka --- spring: profiles: peer1 server: port: 7081 #Eureka實例名的配置 eureka: instance: instance-id: springcloud-gatewayservice-A7-7081 #actuator的配置 management: port: 7181 security: enabled: false --- spring: profiles: peer2 server: port: 7082 #Eureka實例名的配置 eureka: instance: instance-id: springcloud-gatewayservice-A7-7082 #actuator的配置 management: port: 7182 security: enabled: false
本實例的日志按照日期、文件大小、日志級別進行分割,並將不同的級別或日期將記錄到不同的日志文件中,並且日志的大小超過限定值后會自動切割,詳細請參考SpringBoot從入門到進階——學會Logback日志的配置和搭建,具體參數此處略去。
SpringApplication
主程序類中,增加@EnableZuulProxy開啟Zuul路由功能。增加@EnableEurekaClient開啟Eureka Client的功能。
@EnableZuulProxy //開啟Zuul的功能 @EnableEurekaClient//開啟Eureka Client的功能。 @SpringBootApplication public class GatewayServiceApplicaton { public static void main(String[] args) { SpringApplication.run(GatewayServiceApplicaton.class,args); } }
Zuul斷路器
MyFallbackProvider實現了ZuulFallbackProvider接口,通過實現其中的方法對斷路器進行配置:
getRoute()方法用於配置該斷路器匹配的請求的url規則,此處為"*",表示MyFallbackProvider會處理所有的路由請求。fallbackResponse()方法通過返回ClientHttpResponse接口的對象,ClientHttpResponse接口規定了回調響應的具體邏輯,表示返回到客戶端的HTTP響應,包括HTTP狀態碼、響應頭、響應體等信息。
@Component public class MyFallbackProvider implements ZuulFallbackProvider { /** * getRoute()方法,用於指定熔斷功能應用於哪些路由的服務。 * 如果需要所有的路由服務都加熔斷功能,只需要在getRoute()方法上返回"*"的匹配符, */ @Override public String getRoute() { return "*"; //所有路由服務都增加熔斷。 } /** * fallbackResponse()為進入熔斷功能時執行的邏輯 */ @Override public ClientHttpResponse fallbackResponse() { return new ClientHttpResponse() { //設置響應的HTTP狀態碼(HttpStatus中的enum值) @Override public HttpStatus getStatusCode() throws IOException { return HttpStatus.SERVICE_UNAVAILABLE; } //設置響應的HTTP狀態碼(數字,可以是非標准的狀態碼) @Override public int getRawStatusCode() throws IOException { return 503; } //設置響應的HTTP狀態文本信息 @Override public String getStatusText() throws IOException { return "Service_Fallbcak"; } //關閉響應,用於釋放資源 @Override public void close() { } //以輸入流的形式返回響應體的信息 @Override public InputStream getBody() throws IOException { return new ByteArrayInputStream("您好,服務出現故障,請重試。".getBytes("utf-8")); } //返回響應頭的信息 @Override public HttpHeaders getHeaders() { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON_UTF8); return headers; } }; } }
項目的打包、部署過程之前文檔已經寫明,可參考:SpringCloud從入門到進階(二)——注冊中心Eureka的偽分布式部署。
#啟動jar包。 [user@Serverjars]$ java -Dspring.profiles.active=peer1 -jar zuul-1.0-SNAPSHOT.jar
訪問eureka服務器,可以看到zuul微服務處於up狀態,項目成功啟動。
如果請求url不能匹配到zuul上的路由規則,則會報404錯誤。