Spring Cloud 学习笔记六:搭建微服务工程之使用 Zuul 实现容错回退功能、高可用

目录

使用 Zuul 实现容错回退功能、高可用

容错机制

回退机制

Zuul 高可用


使用 Zuul 实现容错回退功能、高可用

Zuul 主要功能就是转发,在转发过程中我们无法保证被转发的服务是可用的,这个时候就需要容错机制及回退机制。

 

容错机制

容错,简单来说就是当某个服务不可用时,能够切换到其他可用的服务上去,也就是需要有重试机制。在 Zuul 中开启重试机制需要依赖 spring-retry。

首先在 pom.xml 中添加 spring-retry 的依赖,代码如下所示:

        <!-- spring-retry -->
        <dependency>
            <groupId>org.springframework.retry</groupId>
            <artifactId>spring-retry</artifactId>
        </dependency>

在属性文件中开启重试机制以及配置重试次数:

zuul:
  # 开启重试
  retryable: true
ribbon:
  # 请求连接的超时时间(ms)
  connectTimeout: 5000
  # 请求处理的超时时间(ms)
  readTimeout: 10000
  # 对当前实例的重试次数
  maxAutoRetries: 1
  # 切换实例的最大重试次数
  maxAutoRetriesNextServer: 3
  # 对所有操作请求都进行重试
  okToRetryOnAllOperations: true
  # 对指定的 Http 响应码进行重试
  retryableStatusCodes: 500,404,502

可以启动两个 blog-user-web 服务,默认 Ribbon 的转发规则是轮询,然后我们停掉一个 blog-user-web 服务。没加重试机制之前,当你请求接口的时候肯定有一次是会被转发到停掉的服务上去的,返回的是异常信息。

当我们加入了重试机制后,你可以循环请求接口,这个时候不会返回异常信息,因为 Ribbon 会根据重试配置进行重试,当请求失败后会将请求重新转发到可用的服务上去。

 

回退机制

在 Spring Cloud 中,Zuul 默认整合了 Hystrix,当后端服务异常时可以为 Zuul 添加回退功能,返回默认的数据给客户端。

实现回退机制需要实现 FallbackProvider 接口,代码如下所示:

@Component
public class ZuulFallbackProvider 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 this.getStatusCode().value();
            }
            @Override
            public String getStatusText() throws IOException {
                return this.getStatusCode().getReasonPhrase();
            }
            @Override
            public void close() {
            }
            @Override
            public InputStream getBody() throws IOException {
                if (cause != null) {
                    System.err.println(cause.getCause());
                }
                RequestContext ctx = RequestContext.getCurrentContext();
                ObjectMapper mapper = new ObjectMapper();
                Map<String, Object> data = new HashMap<>(16);
                data.put("msg", "系统内部错误");
                data.put("code", 999999);
                String json = mapper.writeValueAsString(data);
                return new ByteArrayInputStream(json.getBytes(StandardCharsets.UTF_8));
            }
            @Override
            public HttpHeaders getHeaders() {
                HttpHeaders headers = new HttpHeaders();
                MediaType mt = new MediaType("application", "json", StandardCharsets.UTF_8);
                headers.setContentType(mt);
                return headers;
            }
        };
    }
}

getRoute 方法中返回*表示对所有服务进行回退操作,如果只想对某个服务进行回退,那么就返回需要回退的服务名称,这个名称一定要是注册到 Eureka 中的名称。

通过 ClientHttpResponse 构造回退的内容。通过 getStatusCode 返回响应的状态码。通过 getStatusText 返回响应状态码对应的文本。通过 getBody 返回回退的内容。通过 getHeaders 返回响应的请求头信息。

通过 API 网关来访问 blog-user-web 服务,将 blog-user-web 服务停掉,然后再次访问,就可以看到回退的内容了:

访问结果

 

Zuul 高可用

Zuul客户端也注册到了Eureka Server上

这种情况下,Zuul 的高可用非常简单,只需将多个 Zuul 节点注册到 Eureka Server 上,就可实现 Zuul 的高可用。此时,Zuul 的高可用与其他微服务的高可用没什么区别。

 

多个 Zuul 节点注册到 Eureka Server

 

如上图,当 Zuul 客户端也注册到 Eureka Server 上时,只需部署多个 Zuul 节点即可实现其高可用。Zuul 客户端会自动从 Eureka Server 中查询 Zuul Server 的列表,并使用 Ribbon 负载均衡地请求 Zuul 集群。这种场景一般用于Sidecar

Zuul客户端未注册到Eureka Server上

现实使用中,API 网关这层往往是给 APP、Webapp、客户来调用接口的,如果我们将 Zuul 也注册到 Eureka 中是达不到高可用的,因为你不可能让你的客户也去操作你的注册中心。

这时最好的办法就是用额外的负载均衡器来实现 Zuul 的高可用,比如我们最常用的 Nginx,或者 HAProxy、F5 等。

负载均衡器来实现 Zuul 的高可用

 

这种方式也是单体项目最常用的负载方式,当用户请求一个地址的时候,通过 Nginx 去做转发,当一个服务挂掉的时候,Nginx 会把它排除掉。

如果想要 API 网关也能随时水平扩展,那么我们可以用脚本来动态修改 Nginx 的配置,通过脚本操作 Eureka,发现有新加入的网关服务或者下线的网关服务,直接修改 Nginx 的 upstream,然后通过重载(reload)配置来达到网关的动态扩容。

如果不用脚本结合注册中心去做的话,就只能提前规划好 N 个节点,然后手动配置上去。

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

stary1993

你的鼓励是我创作的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值