Netflix Zuul 集成 Hystrix 熔断

在微服务架构中,熔断(Circuit Breaker)是一种用于应对服务故障和高延迟的机制。想象一下电路中的保险丝,当电流过大(类比服务出现故障或高延迟)时,保险丝会熔断以保护电路的其他部分(类比保护系统的其他部分免受故障服务的影响)。

Zuul 作为 API 网关,在将请求转发到后端服务时,需要熔断机制来防止后端服务的故障或高延迟导致整个系统性能下降或出现故障。例如,当一个后端微服务因为数据库连接问题或者高负载而无法正常响应请求时,Zuul 的熔断机制可以及时切断对该服务的请求,避免客户端长时间等待或者收到错误响应。

Spring Cloud 版本信息:

284ea6aef26255905e5b7eaf9b6c7b99_1734081700973-4429bccc-6ee5-4777-8670-30d4260e10fb.png

💥注意:Spring Cloud 在 Edgware 版本之前,Zuul 提供了接口 ZuulFallbackProvider 用于实现 fallback 处理。从 Edgware 版本开始,Zuul 提供了接口 FallbackProvider 来提供 fallback 处理。

Zuul 的 fallback 容错处理逻辑,只针对 timeout 异常处理,当请求被 Zuul 路由后,只要服务有返回 (包括异常),都不会触发 Zuul 的 fallback 容错逻辑。

因为对于 Zuu 网关来说,做请求路由分发的时候,结果由远程服务运算。远程服务反馈了异常信息,Zuu网关不会处理异常,因为无法确定这个错误是否是应用程序真实想要反馈给客户端的。

由于,笔者的版本是 Hoxton.SR8,因此使用 FallbackProvider 接口。

FallbackProvider 接口

FallbackProvider是 Zuul 中用于实现服务降级的一个重要接口。当 Zuul 无法将请求转发到后端服务(例如,后端服务不可用、超时或出现异常)时,该接口允许开发人员提供自定义的回退逻辑,以便为客户端提供一个更友好的响应,而不是直接抛出错误。

FallbackProvider 接口提供了如下两个方法:

getRoute() 方法

@Override
public String getRoute() {
    return "service-order";
}

该方法返回一个字符串,用于指定要为哪个服务提供回退逻辑。可以是服务的具体名称(如 "service-order"),也可以是通配符 "*",表示为所有服务提供回退。

fallbackResponse() 方法

@Override
public ClientHttpResponse fallbackResponse(String route, Throwable cause) {
    return null;
}

这个方法是核心方法,用于提供具体的回退响应。它接收四个参数:route(服务的名称)、cause(导致回退的异常)、status(原始请求的 HTTP 状态码)和 request(原始请求)。

它返回一个 ClientHttpResponse 对象,该对象包含了回退的 HTTP 响应信息,如状态码、响应体、响应头和响应的内容类型等。

简单示例

下面自定义实现了 FallbackProvider 接口的类:

package com.hxstrive.hystrix_demo.fallback;

import org.springframework.cloud.netflix.zuul.filters.route.FallbackProvider;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.stereotype.Component;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;

/**
 * SERVICE-ORDER 服务降级处理类
 * @author hxstrive.com
 */
@Component
public class ServiceOrderFallbackProvider implements FallbackProvider {

    @Override
    public String getRoute() {
        return "service-order";
    }

    @Override
    public ClientHttpResponse fallbackResponse(String route, Throwable cause) {
        return new ClientHttpResponse() {
            // 用于获取 HTTP 响应的状态码,以 HttpStatus 对象的形式返回。
            // HttpStatus 是一个枚举类型,包含了各种 HTTP 状态码,如 OK(200)、NOT_FOUND(404)、INTERNAL_SERVER_ERROR(500)等
            @Override
            public HttpStatus getStatusCode() throws IOException {
                return HttpStatus.INTERNAL_SERVER_ERROR;
            }

            // 返回 HTTP 状态码的原始数值。与 getStatusCode() 不同,这个方法直接返回一个整数,而不是 HttpStatus 枚举类型
            @Override
            public int getRawStatusCode() throws IOException {
                // 这里可以是 200、404、500 等具体的状态码数值
                return 500;
            }

            // 返回 HTTP 状态码的文本描述。例如,对于状态码 200,它会返回 "OK";对于 404,会返回 "Not Found"
            @Override
            public String getStatusText() throws IOException {
                return "OK";
            }

            // 此方法用于关闭响应资源,特别是关闭 getBody() 方法中使用的输入流。它是一个资源清理方法,确保资源的正确释放,避免资源泄漏。
            @Override
            public void close() {
                //
            }

            // 设置响应体
            @Override
            public InputStream getBody() throws IOException {
                return new ByteArrayInputStream("{\"code\":500,\"message\":\"SERVICE-ORDER服务暂时不可用,请稍后再试!\"}"
                        .getBytes(StandardCharsets.UTF_8));
            }

            // 设置响应头
            @Override
            public HttpHeaders getHeaders() {
                HttpHeaders headers = new HttpHeaders();
                headers.setContentType(new MediaType("application", "json", StandardCharsets.UTF_8));
                return headers;
            }
        };
    }

}

重启服务,尝试访问订单服务(访问前将订单服务停掉),返回消息如下图:

9fdbf1dc0402e2951850d556883d40d0_1734083631245-64f58a4e-3e27-426e-a85a-0a9d120fe6c7.png

点击下载/查看本教程相关资料或者源代码。
说说我的看法
全部评论(
没有评论
关于
本网站专注于 Java、数据库(MySQL、Oracle)、Linux、软件架构及大数据等多领域技术知识分享。涵盖丰富的原创与精选技术文章,助力技术传播与交流。无论是技术新手渴望入门,还是资深开发者寻求进阶,这里都能为您提供深度见解与实用经验,让复杂编码变得轻松易懂,携手共赴技术提升新高度。如有侵权,请来信告知:hxstrive@outlook.com
公众号