在微服务系统里,众多的微服务大多部署在不同的服务器上,我们使用Zuul来作为网关提供统一入口同时协调服务。但有时出现一两个服务请求不通或者干脆就是宕机的情况,这也是可以预见的问题,所以需要时时刻刻准备着容错的手段,没有系统可以做到万无一失。
请求经过Zuul,然后调用服务失败了,怎么容错
了解过Hystrix的简单实现,其实可以发现在Spring Cloud里Hystrix是个很重要的组件,它做了容错降级,保证了服务的可用性。而其实经过Zuul的请求默认也会被Hystrix包裹,那么Zuul也具有容错降级的能力。
Zuul的Fallback怎么实现
有两个eureka客户端:api-gateway和eureka-client
重点贴上api-gateway配置文件application.yml:
spring:
application:
name: api-gateway
server:
port: 8766
zuul:
routes:
hello-feign:
path: /hello-feign/**
serviceId: eureka-feign-client
hello-eureka:
path: /hello-eureka/**
serviceId: eureka-client
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
可以看到有两条路由规则:
/hello-feign/**路径的访问到 eureka-feign-client服务(这个服务默认不开)
/hello-eureka/**路径的访问到 eureka-client服务
浏览器访问http://localhost:8766/hello-feign/helloWorld/AA,结果如下:
浏览器访问http://localhost:8766/hello-eureka/helloWorld/AA,结果如下:
现在我把eureka-client也关闭了,再次访问http://localhost:8766/hello-eureka/helloWorld/AA,结果如下:
现在eureka-feign-client和eureka-client两个服务都是属于调不通的状态了,开始做fallback。
- 创建FallbackService类,实现FallbackProvider
@Component
public class FallbackService implements FallbackProvider {
@Override
public String getRoute() {
return "eureka-client";
}
@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 200;
}
@Override
public String getStatusText() throws IOException {
return "{code:0,message:\"服务器异常!\"}";
}
@Override
public void close() {
}
@Override
public InputStream getBody() throws IOException {
return new ByteArrayInputStream(getStatusText().getBytes());
}
@Override
public HttpHeaders getHeaders() {
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
return httpHeaders;
}
};
}
}
getRoute():这个方法决定你要处理错误的服务名,比如上面代码我就只处理eureka-client服务
fallbackResponse():这个方法决定你处理错误的规则
重启服务,再次访问http://localhost:8766/hello-eureka/helloWorld/AA,结果如下:
而再次访问http://localhost:8766/hello-feign/helloWorld/AA:
可以看出来,通过添加了FallbackService类,eureka-client服务是实现了fallback功能,eureka-feign-client依旧是500错误。
修改getRoute()方法返回值:
@Override
public String getRoute() {
return "*";
}
重启后再次访问http://localhost:8766/hello-feign/helloWorld/AA:
可以看到这时eureka-feign-client服务也有了fallback回退。
总结:
Zuul实现Fallback回退功能很简单,创建一个实现FallbackProvider类的子类,返回要处理错误的服务名以及要处理错误的规则,就行了。