Zuul是Netflix開發的一款提供動態路由、監控、彈性、安全的網關服務,他能夠和Eureka,Ribbon,Hystrix等組件配合使用。還能夠經過建立過濾器對校驗過濾提供支持,使微服務應用更專一於業務邏輯的開發。java
使用Zuul網關服務帶來的好處是統一貫外系統提供REST API,並額外提供了權限控制、負載均衡等功能,而且這些功能是從原先的服務中抽離出來並單獨存在的。git
Zuul提供了不一樣類型的filter用於處理請求,這些filter可讓咱們實現如下功能github
ZuulFilter是一個基礎的抽象類,定義了一些抽象方法spring
filterOrder方法:優先級,級別越高,越快被執行(數值越小表示級別越高)apache
shouldFilter方法:開關,若是是true,run方法會執行,不然不會執行安全
run方法:filter執行的邏輯操做app
建立 zuul-eureka-server 項目,引入eureka-server依賴,項目完整源碼能夠查看:Spring Cloud Zuul 示例源碼負載均衡
如下貼幾段關鍵代碼ide
pom添加依賴spring-boot
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency>
啓動類增長 @EnableEurekaServer 註解
@EnableEurekaServer @SpringBootApplication public class ZuulEurekaServerApplication { public static void main(String[] args) { SpringApplication.run(ZuulEurekaServerApplication.class, args); } }
yml配置
server: port: 8761 spring: application: name: zuul-eureka-server eureka: instance: hostname: localhost # eureka 實例名稱 client: register-with-eureka: false # 不向註冊中心註冊本身 fetch-registry: false # 是否檢索服務 service-url: defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ # 註冊中心訪問地址
建立 zuul-server-provider 項目,引入eureka-client依賴,項目完整源碼能夠查看:Spring Cloud Zuul 示例源碼
如下貼幾段關鍵代碼
pom添加依賴
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency>
編寫HelloController服務
@RestController @Slf4j public class HelloController { @RequestMapping("/hello") public String index(@RequestParam String name) { log.info("request one name is " + name); return "hello " + name + ",this is first messge"; } }
啓動類增長 @EnableDiscoveryClient 註解
@SpringBootApplication @EnableDiscoveryClient public class ZuulServerProviderApplication { public static void main(String[] args) { SpringApplication.run(ZuulServerProviderApplication.class, args); } }
yml配置
spring: application: name: zuul-server-provider server: port: 9000 eureka: client: service-url: defaultZone: http://localhost:8761/eureka
建立 zuul-server-provider2 項目,引入eureka-client依賴,其它同服務提供者1項目,項目完整源碼能夠查看:Spring Cloud Zuul 示例源碼
如下貼出差別部分代碼
編寫服務,這裏爲了作服務降級測試,爲當前線程設置了一個超長休眠時間
@RestController @Slf4j public class HelloController { @RequestMapping("/hello") public String index(@RequestParam String name) { log.info("request two name is " + name); try{ //爲作服務降級測試,設置一個超長休眠時間,故意致使該服務訪問超時 Thread.sleep(1000000); }catch ( Exception e){ log.error(" hello two error",e); } return "hello " + name + ",this is two messge"; } }
建立 zuul-server-gateway 項目,引入netflix-zuul及eureka-client依賴,項目完整源碼能夠查看:Spring Cloud Zuul 示例源碼
如下貼幾段關鍵代碼
pom.xml配置
<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>
建立過濾器TokenFilter.java
package com.easy.zuulServerGateway.filter; import com.netflix.zuul.ZuulFilter; import com.netflix.zuul.context.RequestContext; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang.StringUtils; import javax.servlet.http.HttpServletRequest; @Slf4j public class TokenFilter extends ZuulFilter { @Override public String filterType() { //能夠在請求被路由以前調用 return "pre"; } @Override public int filterOrder() { //filter執行順序,經過數字指定 ,優先級爲0,數字越大,優先級越低 return 0; } @Override public boolean shouldFilter() { //是否執行該過濾器,此處爲true,說明須要過濾 return true; } @Override public Object run() { RequestContext ctx = RequestContext.getCurrentContext(); HttpServletRequest request = ctx.getRequest(); log.info("--->>> TokenFilter {},{}", request.getMethod(), request.getRequestURL().toString()); //獲取請求的參數 String token = request.getParameter("token"); if (StringUtils.isNotBlank(token)) { //對請求進行路由 ctx.setSendZuulResponse(true); ctx.setResponseStatusCode(200); ctx.set("isSuccess", true); return null; } else { //不對其進行路由 ctx.setSendZuulResponse(false); ctx.setResponseStatusCode(400); ctx.setResponseBody("token is empty"); ctx.set("isSuccess", false); return null; } } }
建立 zuul-server-provider 服務對應的熔斷器(這裏針對整個服務熔斷,也能夠對單個服務接口作熔斷處理),ProviderFallback.java
package com.easy.zuulServerGateway.fallback; import lombok.extern.slf4j.Slf4j; 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.InputStream; @Slf4j @Component public class ProviderFallback implements FallbackProvider { @Override public String getRoute() { return "zuul-server-provider"; } @Override public ClientHttpResponse fallbackResponse(String route, Throwable cause) { if (cause != null) { String reason =cause.getMessage(); log.info("Excption {}", reason); } return fallbackResponse(); } public ClientHttpResponse fallbackResponse() { return new ClientHttpResponse() { @Override public HttpStatus getStatusCode() { return HttpStatus.OK; } @Override public int getRawStatusCode() { return 200; } @Override public String getStatusText(){ return "OK"; } @Override public void close() { } @Override public InputStream getBody() { return new ByteArrayInputStream("The service is unavailable.".getBytes()); } @Override public HttpHeaders getHeaders() { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); return headers; } }; } }
yml配置
spring: application: name: zuul-service-gateway server: port: 8888 eureka: client: service-url: defaultZone: http://localhost:8761/eureka #是否開啓重試功能 zuul: retryable: true #對當前服務的重試次數 ribbon: MaxAutoRetries: 2 #切換相同Server的次數 MaxAutoRetriesNextServer: 0
啓動類增長 @EnableZuulProxy 註解,來啓動服務網關
ZuulServerGatewayApplication.java
package com.easy.zuulServerGateway; import com.easy.zuulServerGateway.filter.TokenFilter; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.zuul.EnableZuulProxy; import org.springframework.context.annotation.Bean; @SpringBootApplication @EnableZuulProxy public class ZuulServerGatewayApplication { public static void main(String[] args) { SpringApplication.run(ZuulServerGatewayApplication.class, args); } @Bean public TokenFilter tokenFilter() { return new TokenFilter(); } }
至上,示例的四個服務建立完畢,接下來運行示例查看效果
zuul-eureka-server:服務註冊中心,服務名:zuul-eureka-server,端口:8761
zuul-server-provider:服務提供者1,服務名:zuul-server-provider,端口:9000
zuul-server-provider2:服務提供者,服務名:zuul-server-provider,端口:9001
zuul-server-gateway:服務網關,服務名:zuul-server-gateway,端口:8888
分別啓動zuul-eureka-server、zuul-server-gateway、zuul-server-provider三個服務
啓動zuul-server-provider2
hello yuntian,this is first messge The service is unavailable ...
從返回結果能夠看出:zuul-server-provider2項目已經啓用了熔斷,返回:The service is unavailable.