3-网关路由Hystrix
回退(学习笔记2020.3.16)
前言:
Hystrix
是个熔断器,主要解决了服务调用不通,而一直阻塞从而导致服务连续崩溃问题,feign
内部就有集成了熔断器实现起来非常简单,而Zuul
网关依赖里面也包括了Hystrix
依赖, 那么就可以来进行实现当网关转发请求的时候,一直连接不通,或者长时间获取不到响应的时候,触发熔断快速响应错误信息,避免阻塞!
根据官网的文档,实现起来非常简单,为路线提供
Hystrix
回退,当Zuul
中给定路由的电路跳闸时,您可以通过创建类型为FallbackProvider
的bean来提供回退响应。在这个bean中,您需要指定回退的路由ID,并提供返回的ClientHttpResponse
作为后备。这是一个非常简单的FallbackProvider
实现。
FallbackProvider
是个zuul
提供的回退规范接口,我们要实现回退,就进行实现这个接口并注册到框架中!
一: 实现FallbackProvider
package com.chenzhihao;
import cn.hutool.json.JSONUtil;
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.nio.charset.Charset;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* @Author: zhihao
* @Date: 2020/3/16 14:12
* @Description: zuul回退
* @Versions 1.0
**/
@Component
public class MyZuulFallbackProvider implements FallbackProvider {
/**
* 需要回退的路由
*
* @return
*/
@Override
public String getRoute() {
// return "eureka-client"; 单独配置一个服务的熔断
return "*"; //返回 '*' 是所有
}
/**
* 返回客户端响应
*
* @param route 路由
* @param cause 原因
* @return org.springframework.http.client.ClientHttpResponse
* @author: zhihao
* @date: 2020/3/16
*/
@Override
public ClientHttpResponse fallbackResponse(String route, Throwable cause) {
//根据异常信息判断是否是网关超时
if (cause instanceof HystrixTimeoutException) {
return response(route, HttpStatus.GATEWAY_TIMEOUT);
} else {
//其他一类返回内部错误
return response(route, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
private ClientHttpResponse response(String route, HttpStatus status) {
return new ClientHttpResponse() {
@Override
public HttpStatus getStatusCode() throws IOException {
return status;
}
@Override
public int getRawStatusCode() throws IOException {
return status.value();
}
@Override
public String getStatusText() throws IOException {
return status.getReasonPhrase();
}
@Override
public void close() {
}
@Override
public InputStream getBody() throws IOException {
Map<String, String> errorMap = new LinkedHashMap();
//服务id
errorMap.put("serviceID", route);
errorMap.put("message", status.getReasonPhrase());
//转成json字符串
String jsonStr = JSONUtil.toJsonStr(errorMap);
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(jsonStr.getBytes(Charset.forName("UTF-8")));
return byteArrayInputStream;
}
@Override
public HttpHeaders getHeaders() {
//创建响应头 返回json格式
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
return headers;
}
};
}
}
到此,
zuul
的熔断器回退就实现了!