前言:前面說過,由於微服務過多,可能某一個小業務就需要調各種微服務的接口,不可避免的就會需要負載均衡和反向代理了,以確保ui不直接與所有的微服務接口接觸,所以我們需要使用一個組件來做分發,跨域等各種請求。
一、微服務網關ZUUL
ZUUL是Netflix開源的微服務網關,它可以和Eureka、Ribbon、Hystrix等組件配合使用,它主要用作反向代理、Filter擴展、動態加載、動態路由、壓力測試、彈性擴展、審查監控、安全檢查等。

二、ZUUL與SpringCloud各組件的整合使用
1、創建一個Maven工程,gateway-zuul,添加依賴:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.13.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zuul</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Edgware.SR3</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<!-- 添加spring-boot的maven插件 -->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
2、在啟動類上添加注解@EnableZuulProxy,聲明ZUUL代理,通過觀察Zuul的類庫發現,zuul的依賴庫中除了有它本身的核心包外還有actuator、hystrix的整合包,默認實現了監控和熔斷機制,所有經過zuul的請求都會在hystrix命令中執行:
@SpringBootApplication @EnableZuulProxy public class ZuulApplication { public static void main(String[] args) { SpringApplication.run(ZuulApplication.class, args); } }
3、編寫配置文件application.properties:
server.port=8000 spring.application.name=zuul-8000 eureka.client.service-url.defaultZone=http://localhost:8761/eureka/ #由於zuul中的actuator默認的安全權限為ture,需改為false,若不修改則會導致無法訪問路由管理(localhost:8000/routes) management.security.enabled=false
(注:下面的測試,是基於之前做的幾個關於Ribbon、Hystrix的demo來做的,若感興趣可以看一下我之前的文章:SpringCloud-客戶端的負載均衡Ribbon(三)、SpringCloud-容錯處理Hystrix熔斷器(五))
4、測試路由網關是否啟動:
分別啟動 eureka-ribbon-server、 eureka-ribbon-client、 eureka-ribbon-client2 和 gateway-zuul,打開服務配置中心,並訪問http://localhost:8000/client-8762/getUser:


通過網關訪問成功!
5、測試負載均衡是否可用:
分別啟動 eureka-ribbon-server、eureka-feign-hystrix-client、修改 eureka-ribbon-client2 端口為8763、修改 eureka-ribbon-client2 端口為8764 和 gateway-zuul,打開服務配置中心,並多次訪問http://localhost:8000/client-8762/loadInstance,觀察返回結果:



根據觀察結果知,通過網關實現負載均衡!
6、測試熔斷與路由端點是否可用:
熔斷:
分別啟動 eureka-ribbon-server、 eureka-feign-hystrix-client、 eureka-ribbon-client2 和 gateway-zuul,打開服務配置中心,並多次訪問http://localhost:8000/client-8762/loadInstance,觀察返回結果:


將CLIENT-87實例關閉,再次調用:

注:由於client-87的實例關閉后要等eureka將實例移除后,然后eureka通知zuul,zuul再將client-87從網關列表中移除,最后訪問,才可以看到熔斷,走回調函數了!
啟動項目與上面 測試5相同,注意網關中的application.properties一定要將安全權限打開或者以其他方式,才可訪問localhost:8000/routes/
#由於zuul中的actuator默認的安全權限為ture,需改為false,若不修改則會導致無法訪問路由管理(localhost:8000/routes) management.security.enabled=false

三、ZUUL過濾器的實踐

Zuul提供一個框架,可以對Groovy寫的過濾器進行動態的加載、編譯、運行。過濾器之間沒有直接的相互通信,通過一個RequestContext的靜態類中ThreadLocal變量來進行數據傳遞,過濾器類型:
PRE:這種過濾器在請求到達Origin Server之前調用。比如身份驗證,在集群中選擇請求的Origin Server,記log等;
ROUTING:在這種過濾器中把用戶請求發送給Origin Server。發送給Origin Server的用戶請求在這類過濾器中build。並使用Apache HttpClient或者NetfilxRibbon發送給Origin Server;
POST:這種過濾器在用戶請求從Origin Server返回以后執行。比如在返回的response上面加response header,做各種統計等。並在該過濾器中把response返回給客戶;
ERROR:在其他階段發生錯誤時執行該過濾器;
客戶定制:比如我們可以定制一種STATIC類型的過濾器,用來模擬生成返回給客戶的response;
1、創建過濾器類,繼承ZuulFilter抽象類,實現該方法:
/** * @program: springcloud-example * @description: * @author: * @create: 2018-06-20 16:53 **/ public class RequestLogFilter extends ZuulFilter { private Logger logger = LoggerFactory.getLogger(RequestLogFilter.class); /** * @Description: 返回過濾器類型,就是上面介紹的那幾種類型 * @Param: * @return: * @Author: * @Date: 2018/6/20 */ @Override public String filterType() { return "pre"; } /** * @Description:指定過濾器執行的順序 * @Param: * @return: * @Author: * @Date: 2018/6/20 */ @Override public int filterOrder() { return 1; } /** * @Description:指定該過濾器是否執行 * @Param: * @return: * @Author: * @Date: 2018/6/20 */ @Override public boolean shouldFilter() { return true; } /** * @Description: 過濾器的具體方法邏輯 * @Param: * @return: * @Author: * @Date: 2018/6/20 */ @Override public Object run() { RequestContext currentContext = RequestContext.getCurrentContext(); HttpServletRequest request = currentContext.getRequest(); String url = request.getRequestURL().toString(); logger.info("請求URL:"+url); return null; } }
2、在啟動類,將該過濾器注入到Spring容器中:
@Bean public RequestLogFilter getRequestLogFilter() { return new RequestLogFilter(); }
3、分別啟動 eureka-ribbon-server、 eureka-ribbon-client、 eureka-ribbon-client2、 gateway-zuul測試:

參考書籍:《SpringCloud與Docker微服務架構實戰》周力著
代碼示例:https://gitee.com/lfalex/springcloud-example( eureka-feign-hystrix-client、 eureka-hystrix-client、 eureka-ribbon-client、 eureka-ribbon-client2、 eureka-ribbon-server、 gateway-zuul)
