从零搭建一个SpringCloud项目之Zuul(四)
整合Zuul
为什么要使用Zuul?
- 易于监控
- 易于认证
- 减少客户端与各个微服务之间的交互次数
- 引入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
- 配置文件
可不配置,具体配置参数见下文 - 开启注解
启动类上加@EnableZuulProxy
备注:不配置任何配置文件时,启动zuul服务,zuul可以通过服务名去访问到其他服务。
例:http://localhost:8000/study-trade/trade/testTrade/2
二、配置详解
- 路径映射
#关闭通过微服务名称访问
zuul.ignored-services=*
#指定微服务名称和路径的映射
#zuul.routes.study-trade=/strade/**
#指定微服务名称和路径的映射,是否剥离前缀
zuul.routes.study-trade.service-id=study-trade
zuul.routes.study-trade.path=/orderservice/**
zuul.routes.study-trade.strip-prefix=true
#指定ip映射,而不用负载均衡
#zuul.routes.study-trade.url=http://localhost:8005/
#zuul.routes.study-trade.path=/st/**
#为我们目标下游服务器设置统一的请求前缀
# 本来是http://localhost:8000/strade/trade/testTrade/2 的配置了就需要http://localhost:8000/study-springcloud/strade/trade/testTrade/2才能访问
#zuul.prefix=/study-springcloud
#是否剥离请求前缀
#zuul.strip-prefix=true
#屏蔽敏感的路径
zuul.ignored-patterns=/**/admin/**
#过滤敏感头信息,不加这行,cookie,setcookie,authrotion三个同步信息不能传递的,等号后不用写值
zuul.routes.study-trade.sensitive-headers=
#禁用Zuul的过滤器 simpleClassname代表类名
#zuul.simpleClassname.pre|router|post|error=true
- 降级回退
- 宕机回退
- 超时回退(ribbon.ConnectionTimeout=4000
ribbon.ReadTimeout=4000)
代码实现:
/**
* @description: Zull的降级回退
* @author: mmc
* @create: 2020-04-12 22:39
**/
@Component
public class ZuulFallBack implements FallbackProvider {
@Override
public String getRoute() {
//可以填微服务实例名称或*
return "*";
}
@Override
public ClientHttpResponse fallbackResponse(String route, Throwable cause) {
return new ClientHttpResponse() {
@Override
public HttpStatus getStatusCode() throws IOException {
return HttpStatus.OK;
}
@Override
public int getRawStatusCode() throws IOException {
return HttpStatus.OK.value();
}
@Override
public String getStatusText() throws IOException {
return HttpStatus.OK.getReasonPhrase();
}
@Override
public void close() {
}
@Override
public InputStream getBody() throws IOException {
return new ByteArrayInputStream("后端服务异常".getBytes());
}
@Override
public HttpHeaders getHeaders() {
HttpHeaders httpHeaders=new HttpHeaders();
httpHeaders.setContentType(MediaType.APPLICATION_JSON_UTF8);
return httpHeaders;
}
};
}
}
- 过滤器
@Component
public class ThrowExeceptionFilter extends ZuulFilter {
@Override
public String filterType() {
return "pre";
}
@Override
public int filterOrder() {
return 0;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() throws ZuulException {
return null;
}
}
- 统一异常处理
-
4.1 禁用系统异常
zuul.SendErrorFilter.error.disable=true
-
4.2 自定义异常处理类
@Component
public class ErrorFilter extends SendErrorFilter {
@Override
public Object run() {
try{
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
HttpServletResponse response = ctx.getResponse();
ExceptionHolder exception = findZuulException(ctx.getThrowable());
response.setContentType("application/json;charset=utf-8");
response.setCharacterEncoding("UTF-8");
Map<String,Object> errorMap=new HashMap<>();
errorMap.put("code","-1");
errorMap.put("errMsg",exception.getThrowable().getCause().getMessage());
response.getWriter().write(JSON.toJSONString(errorMap));
}catch (Exception e){
try {
ReflectionUtils.rethrowException(e);
} catch (Exception e1) {
e1.printStackTrace();
}
}
return null;
}
}
书山有路勤为径,学海无涯苦作舟