快速搭建微服务-熔断器

熔断器的主要功能是在进行服务间调用时提供一种容错保护,当服务提供方因网络或自身原因出现调用故障或延迟时,会导致服务调用方对外服务也出现延迟,如果此时服务调用方的请求不断增加,则会出现调用方的自身服务的故障甚至蔓延导致整个系统的瘫痪。

服务调用方配置熔断

  • Maven依赖
1
2
3
4
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
  • 开启熔断器

在启动类上加入@EnableCircuitBreaker注解开启熔断器。

  • 服务降级

通过 @HystrixCommand 注解实现服务降级。

1
2
3
4
5
6
7
8
9
@GetMapping("")
@HystrixCommand(fallbackMethod = "listWxMpAccountFallback")
public Result listWxMpAccount(@PageableDefault Pageable pageable) {
return wxMpAccountService.listWxMpAccount(pageable);
}

private Result listWxMpAccountFallback(Pageable pageable) {
return Result.fail("获取公众号列表失败,请稍后再试");
}

网关配置服务降级

当我们在使用zuul进行路由分发,如果后端服务没有启动或者调用超时的时候,就可以使用zuul提供的降级功能。

在网关服务中新建继承自 FallbackProviderServiceFallbackProvider 类,并使用 @Component 注解进行修饰。FallbackProvider 会根据是否存在 Throwable 来选择降级方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
@Component
public class ServiceFallbackProvider implements FallbackProvider {

@Override
public ClientHttpResponse fallbackResponse(Throwable throwable) {
StringBuilder reasonBuilder = new StringBuilder("服务故障,请稍后重试!");
if (throwable != null && throwable.getCause() != null) {
reasonBuilder.append(" 故障原因: ").append(throwable.getCause().getMessage());
}
return new ClientHttpResponse() {
@Override
public HttpStatus getStatusCode() throws IOException {
return HttpStatus.SERVICE_UNAVAILABLE;
}

@Override
public int getRawStatusCode() throws IOException {
return HttpStatus.SERVICE_UNAVAILABLE.value();
}

@Override
public String getStatusText() throws IOException {
return HttpStatus.SERVICE_UNAVAILABLE.getReasonPhrase();
}

@Override
public void close() {

}

@Override
public InputStream getBody() throws IOException {
return new ByteArrayInputStream(reasonBuilder.toString().getBytes(Charset.forName("UTF-8")));
}

@Override
public HttpHeaders getHeaders() {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.valueOf(AppConsts.WebConsts.TEXT_PLAIN_UTF8_VALUE));
return headers;
}
};
}

@Override
public String getRoute() {
return "*";
}

@Override
public ClientHttpResponse fallbackResponse() {
return new ClientHttpResponse() {
@Override
public HttpStatus getStatusCode() throws IOException {
return HttpStatus.SERVICE_UNAVAILABLE;
}

@Override
public int getRawStatusCode() throws IOException {
return HttpStatus.SERVICE_UNAVAILABLE.value();
}

@Override
public String getStatusText() throws IOException {
return HttpStatus.SERVICE_UNAVAILABLE.getReasonPhrase();
}

@Override
public void close() {

}

@Override
public InputStream getBody() throws IOException {
return new ByteArrayInputStream("服务故障,请稍后重试!".getBytes(Charset.forName("UTF-8")));
}

@Override
public HttpHeaders getHeaders() {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.valueOf(AppConsts.WebConsts.TEXT_PLAIN_UTF8_VALUE));
return headers;
}
};
}
}