框架 | 版本 |
---|---|
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随笔便可