代码信息
本篇文章涉及代码版本
组件 | 版本 |
---|---|
Spring Boot | 2.0.8.RELEASE |
Spring Cloud | Finchley.SR1 |
本篇文章涉及应用
应用 | 说明 |
---|---|
base-eureka | 服务发现 |
base-zuul-fallback | Zuul服务降级 |
base-producer | 提供服务的最基础的应用 |
base-producer-upload | 提供文件上传的应用 |
查看Zuul内部的依赖关系可以看到下面内容
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
可以看到Zuul内部其实已经添加了hystrix。这样zuul也可以实现服务降级。
创建一个支持服务降级的zuul应用
构建maven依赖
其实hystrix依赖不是必须的,就像上面看到了,zuul默认依赖已经引入了hystrix。
<dependencies>
<!--zuul-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
</dependencies>
参数配置application.yml
因为这次我们要实现不同项目使用不同的降级策略,所以我们使用了两个项目
base-producer
、base-producer-upload
,其中base-producer
是我们最基础的服务端项目。base-producer-upload
是我们刚创建的支持上传的服务端项目
spring:
application:
name: base-zuul-fallback
server:
port: 8302
eureka:
client:
service-url:
defaultZone: http://localhost:8000/eureka/
logging:
file: ${spring.application.name}.log
zuul:
routes:
consumer:
path: /client/**
serviceId: base-producer
consumerV2:
path: /client-update/**
serviceId: base-producer-upload
consumer:
ribbon:
listOfServers: http://localhost:8100/
consumerV2:
ribbon:
listOfServers: http://localhost:8105/
代码编写
主类
主类很简单就是打开相关功能的注解。
@EnableZuulProxy
@SpringBootApplication
@EnableCircuitBreaker
public class ZuulApplication {
public static void main(String[] args) {
SpringApplication.run(ZuulApplication.class, args);
}
}
服务降级代码
要实现服务降级只需要在容器中创建实现
FallbackProvider
(之前版本是ZuulFallbackProvider
)接口的对象。
@Component
public class ClientFallbackProvider implements FallbackProvider {
@Override
public String getRoute() {
// 表明是为哪个微服务提供回退,*表示为所有微服务提供回退
return "base-producer";
}
/**
* 回退逻辑
* @param route
* @param cause
* @return
*/
@Override
public ClientHttpResponse fallbackResponse(String route, Throwable cause) {
return new ClientHttpResponse() {
@Override
public HttpStatus getStatusCode() throws IOException {
return HttpStatus.BAD_GATEWAY;
}
@Override
public int getRawStatusCode() throws IOException {
return HttpStatus.BAD_REQUEST.value();
}
@Override
public String getStatusText() throws IOException {
return HttpStatus.BAD_REQUEST.getReasonPhrase();
}
@Override
public void close() {
}
@Override
public InputStream getBody() throws IOException {
return new ByteArrayInputStream(("fallback-base-producer:" + ClientFallbackProvider.this.getRoute()).getBytes());
}
@Override
public HttpHeaders getHeaders() {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
return headers;
}
};
}
}
@Component
public class ClientV2FallbackProvider implements FallbackProvider {
@Override
public String getRoute() {
// 表明是为哪个微服务提供回退,*表示为所有微服务提供回退
return "base-producer-upload";
}
/**
* 回退逻辑
* @param route
* @param cause
* @return
*/
@Override
public ClientHttpResponse fallbackResponse(String route, Throwable cause) {
return new ClientHttpResponse() {
@Override
public HttpStatus getStatusCode() throws IOException {
return HttpStatus.BAD_GATEWAY;
}
@Override
public int getRawStatusCode() throws IOException {
return HttpStatus.BAD_REQUEST.value();
}
@Override
public String getStatusText() throws IOException {
return HttpStatus.BAD_REQUEST.getReasonPhrase();
}
@Override
public void close() {
}
@Override
public InputStream getBody() throws IOException {
return new ByteArrayInputStream(("fallback-base-producer-upload:" + ClientV2FallbackProvider.this.getRoute()).getBytes());
}
@Override
public HttpHeaders getHeaders() {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
return headers;
}
};
}
}
接口中getRoute
指的是此处理工具处理那个微服务。假如返回null或者*表示处理所有的微服务。所以上面代码中我们让ClientFallbackProvider
处理base-producer
服务。让ClientV2FallbackProvider
处理base-producer-upload
服
测试
现在我们依次启动base-eureka
、base-producer
、base-producer-upload
、base-zuul-fallback
项目。
首先我们测试两个接口是否可以调用
首先两个接口已经可以正常发起请求,然后现在我们关闭掉base-producer
、base-producer-upload
项目。
可以看到输出的内容已经有所不同,两个微服务成功应用了不同的处理策略。
本篇文章并未贴出所有代码,涉及的源码下载地址:https://gitee.com/daifylearn/cloud-learn
ps.上述的所有项目都是可以成功运行的。但是在后期为了实现每个应用端口尽量不冲突会有些许调整,而后续某次作死调整结构和名称可能会导致部分项目无法运行o(╯□╰)o,如果发现请留言我进行修改。