框架 | 版本 |
---|---|
Spring Boot | 2.0.0.RELEASE |
Spring Cloud | Finchley.RELEASE |
Zuul | 1.3.1 |
JDK | 1.8.x |
參考上一篇:https://ken.io/note/spring-cloud-zuul-quickstart
基於源碼:https://github.com/ken-io/springcloud-course/tree/master/chapter-07java
啓動Eureka Server: http://localhost:8800
啓動Test Service:http://localhost:8602,http://localhost:8603git
Zuul做爲服務網關爲了保證本身不被服務拖垮,自己已經集成了Hystrix對路由轉發進行隔離。
爲了方便開發人員對服務短路進行自定義處理,
Zuul 提供了 ZuulFallbackProvider 接口,開發人員能夠經過實現該接口來完成自定義Hystrix Fallbackgithub
Spring Cloud Zuul 提供了 FallbackProvider替代了ZuulFallbackProvider接口。所以咱們實現FallbackProvider便可web
基於上一篇中zuul項目的源碼進行修改便可:https://github.com/ken-io/springcloud-course/tree/master/chapter-07/zuulspring
在src\main\java\io\ken\springcloud\zuul建立package:provider
而後建立Filter類:ApiFallbackProvider.java框架
實現FallbackProvider並標記爲@Component
ide
package io.ken.springcloud.zuul.provider; import com.netflix.hystrix.exception.HystrixTimeoutException; 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; import java.util.logging.Logger; @Component public class ApiFallbackProvider implements FallbackProvider { private Logger logger = Logger.getLogger(ApiFallbackProvider.class.toString()); @Override public String getRoute() { return "*"; } @Override public ClientHttpResponse fallbackResponse(String route, Throwable cause) { logger.warning(String.format("route:%s,exceptionType:%s,stackTrace:%s", route, cause.getClass().getName(), cause.getStackTrace())); String message = ""; if (cause instanceof HystrixTimeoutException) { message = "Timeout"; } else { message = "Service exception"; } return fallbackResponse(message); } public ClientHttpResponse fallbackResponse(String message) { 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 { String bodyText = String.format("{\"code\": 999,\"message\": \"Service unavailable:%s\"}", message); return new ByteArrayInputStream(bodyText.getBytes()); } @Override public HttpHeaders getHeaders() { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); return headers; } }; } }
項 | 說明 |
---|---|
getRoute() | 該Provider應用的Route ID,例如:testservice,若是設置爲 * ,那就對全部路由生效 |
fallbackResponse(String route, Throwable cause) | 快速回退失敗/響應,即處理異常並返回對應輸出/響應內容。route:發生異常的RouteID,cause:觸發快速回退/失敗的異常/錯誤 |
ClientHttpResponse | Spring提供的HttpResponse接口。能夠經過實現該接口自定義Http status、body、header |
啓動zuul項目,訪問 http://localhost:8888/testservice?token=123
會獲得正常響應內容:spring-boot
{ "code": 0, "message": "hello", "content": null, "serviceName": "testservice", "host": "localhost:8602" }
關掉testservice啓動的實例。而後再訪問 http://localhost:8888/testservice?token=123 ,就會看到測試
{ "code": 999, "message": "Service unavailable:Timeout" }
上一節我們提到了,Zuul自己就集成了Hystrix,實際上Zuul的路由轉發也是用到了Ribbon+Hystrix,也就意味着咱們能夠經過Hystrix Dashboard監控Zuul的工做狀況ui
新建package:configuration,而後在此package下建立HystrixConfiguration.java
package io.ken.springcloud.zuul.configuration; import com.netflix.hystrix.contrib.metrics.eventstream.HystrixMetricsStreamServlet; import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class HystrixConfiguration { @Bean(name = "hystrixRegistrationBean") public ServletRegistrationBean servletRegistrationBean() { ServletRegistrationBean registration = new ServletRegistrationBean( new HystrixMetricsStreamServlet(), "/hystrix.stream"); registration.setName("hystrixServlet"); registration.setLoadOnStartup(1); return registration; } @Bean(name = "hystrixForTurbineRegistrationBean") public ServletRegistrationBean servletTurbineRegistrationBean() { ServletRegistrationBean registration = new ServletRegistrationBean( new HystrixMetricsStreamServlet(), "/actuator/hystrix.stream"); registration.setName("hystrixForTurbineServlet"); registration.setLoadOnStartup(1); return registration; } }
配置完成後重啓啓動zuul,訪問 http://localhost:8888/hystrix.stream 或者
http://localhost:8888/actuator/hystrix.stream
就能夠看到Hystrix流信息.(之因此配置兩個入口,是爲了知足turbine須要)
//截取片斷 {"type":"HystrixCommand","name":"testservice","group":"RibbonCommand","currentTime":1532412948030,"isCircuitBreakerOpen":false,"errorPercentage":100,"errorCount":1,"requestCount":1}
這時候咱們經過已有看板以連接方式查看Hystrix Dashboard,或者能夠用Turbine來聚合Hystrix數據了。
固然,也能夠在zuul項目中引入Hystrix Dashboard 進行監控。
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId> </dependency>
@EnableHystrixDashboard
註解package io.ken.springcloud.zuul; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard; import org.springframework.cloud.netflix.zuul.EnableZuulProxy; @EnableHystrixDashboard @EnableZuulProxy @EnableEurekaClient @SpringBootApplication public class App { public static void main(String[] args) { SpringApplication.run(App.class, args); } }
配置完成後重啓啓動zuul,訪問 http://localhost:8888/hystrix ,就能夠看到門戶頁
具體操做,再也不贅述,參考本系列前面幾篇Hystrix隨筆便可