路由是微服務架構中必須的一部分,好比,「/」 可能映射到你的WEB程序上,」/api/users
「可能映射到你的用戶服務上,「/api/shop」可能映射到你的商品服務商。(註解:我理解這裏的這幾個映射就是說經過Zuul這個網關把服務映射到不一樣的服務商去處理,從而變成了微服務!)java
這裏只列舉zuul一些配置,headers,client等等不作考慮。web
經過Zuul咱們能夠完成如下功能:正則表達式
在Idea裏,新建項目,選擇Spring initializer.spring
下面的pomapi
<dependencies>
<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>
</dependencies>
配置properties文件參數;瀏覽器
server.port=8887 spring.application.name=zuul-proxy eureka.client.service-url.defaultZone=http://localhost:8882/eureka
啓動類以下:安全
@EnableZuulProxy // 啓動Zuul的路由服務 @SpringBootApplication public class SpringCloundZuulDemoApplication { public static void main(String[] args) { SpringApplication.run(SpringCloundZuulDemoApplication.class, args); } }
代碼基本編寫完成,下面咱們來啓動項目;Eureka,service-hello(兩個 + 一個實例),最後啓動zuul-proxy;架構
瀏覽器輸入:(可見,zuul也實現了負載均衡)app
可見,zuul-proxy已經幫咱們路由到相應的微服務。負載均衡
zuul.routes.service-hello = /hello/** zuul.routes.service-hello-2 = /hello2/**
所要配置的路徑能夠指定一個正則表達式來匹配路徑,所以,/
hello/*
只能匹配一級路徑,可是經過/hello/**
能夠匹配全部以/hello/
開頭的路徑。
配置格式爲: zuul.ignored-services=微服務Id1,微服務Id2...,多個微服務之間使用逗號分隔。
zuul.ignored-services = service-hello-2
可見,自定義路由依舊能夠訪問。
還有其餘形式的路由配置,不在此一一列舉。
spring-cloud-starter-zuul
自己已經集成了hystrix和ribbon,因此Zuul天生就擁有線程隔離和斷路器的自我保護能力,以及對服務調用的客戶端負載均衡功能。可是,咱們須要注意,當使用path與url的映射關係來配置路由規則時,對於路由轉發的請求則不會採用HystrixCommand
來包裝,因此這類路由請求就沒有線程隔離和斷路器保護功能,而且也不會有負載均衡的能力。所以,咱們在使用Zuul的時候儘可能使用path和serviceId的組合進行配置,這樣不只能夠保證API網關的健壯和穩定,也能用到Ribbon的客戶端負載均衡功能。
咱們來看看zuul是否集成hystrix,在以前feign已經集成了hystrix,這裏很少作說明。
請注意,Zuul的Hystrix監控的粒度是微服務,而不是某個API,也就是全部通過Zuul的請求都會被Hystrix保護起來。假如,咱們如今把service-hello-2服務關閉,再來訪問會出現什麼結果呢?結果可能不是咱們所想那樣,以下:
那麼如何爲Zuul實現容錯與回退呢?
Zuul提供了一個ZuulFallbackProvider(新版:
FallbackProvider)
接口,經過實現該接口就能夠爲Zuul實現回退功能。那麼讓咱們改造以前的Zuul-proxy
。
package com.example.zuul.fallback; import org.springframework.cloud.netflix.zuul.filters.route.FallbackProvider; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.client.ClientHttpResponse; import org.springframework.stereotype.Component; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; /** * @author sky.javaweb@qq.com * @version 1.0 * @date 2018-12-28 */ @Component public class ServiceFallbackProvider implements FallbackProvider { @Override public String getRoute() { // 代表是爲哪一個微服務提供回退,*表示爲全部微服務提供回退 return "*"; } @Override public ClientHttpResponse fallbackResponse(String route, Throwable cause) { return new ClientHttpResponse() { @Override public HttpStatus getStatusCode() throws IOException { return HttpStatus.OK; } @Override public int getRawStatusCode() throws IOException { return 200; } @Override public String getStatusText() throws IOException { return "OK"; } @Override public void close() { } @Override public InputStream getBody() throws IOException { return new ByteArrayInputStream((route + "服務暫不可用,請稍後重試!" + cause.getMessage()).getBytes()); } @Override public HttpHeaders getHeaders() { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON_UTF8); return headers; } }; } }
再打開service-hello-2服務接口