默认情况下,spring-cloud-zuul-ratelimit 会提供一种通用的错误响应机制,但这种响应可能并不满足所有应用程序的需求。我们可以通过实现 RateLimiterErrorHandler 接口,自定义错误处理,根据具体的业务场景和用户体验需求,提供更加定制化的错误响应。
RateLimiterErrorHandler 是 spring-cloud-zuul-ratelimit 中的一个重要接口,它主要用于处理限流过程中出现的各种错误。
接口源码:
package com.marcosbarbero.cloud.autoconfigure.zuul.ratelimit.config.repository; /** * Handles the backend storage errors. * * @author Liel Chayoun */ public interface RateLimiterErrorHandler { void handleSaveError(String key, Exception e); void handleFetchError(String key, Exception e); void handleError(String msg, Exception e); }
该接口包含三个方法:
handleSaveError(String key, Exception e) 该方法主要用于处理在保存限流信息时出现的错误。例如,当系统试图将用户的请求频率、剩余请求次数等信息存储到存储介质中时,如果出现异常,此方法会被调用,以便进行相应的错误处理,比如记录日志、抛出特定的异常、尝试重试等。
handleFetchError(String key, Exception e) 该方法主要负责处理在尝试从存储中获取限流信息时发生的错误。例如,当系统需要根据 key 从存储系统中读取用户的限流状态时,如果读取操作失败,该方法会被调用,以进行相应的错误处理,例如返回默认的限流状态、通知管理员、向用户发送错误信息等。
handleError(String msg, Exception e) 该方法是一个通用的错误处理方法,用于处理在限流操作过程中出现的其他错误。它提供了一个更宽泛的错误处理范围,适用于那些无法明确归类到 handleSaveError 或 handleFetchError 的错误情况。
DefaultRateLimiterErrorHandler 是 spring-cloud-zuul-ratelimit 提供的一个默认的限流错误处理类,它实现了 RateLimiterErrorHandler 接口。该类主要负责处理在限流过程中出现的各种错误情况,确保在出现异常时系统能够采取适当的措施。
在使用 spring-cloud-zuul-ratelimit 进行限流时,如果没有自定义的 RateLimiterErrorHandler,系统会默认使用 DefaultRateLimiterErrorHandler 来处理限流过程中出现的错误。
它可以作为基础的错误处理机制,为开发人员提供了基本的错误信息输出和异常处理,保证系统在遇到问题时能够有基本的响应。
一般情况下,只要将 spring-cloud-zuul-ratelimit 集成到项目中,DefaultRateLimiterErrorHandler 会自动被 Spring 容器管理,无需额外的配置。
DefaultRateLimiterErrorHandler 源码:
package com.marcosbarbero.cloud.autoconfigure.zuul.ratelimit.config.repository; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * @author Liel Chayoun */ public class DefaultRateLimiterErrorHandler implements RateLimiterErrorHandler { private static Logger log = LoggerFactory.getLogger(DefaultRateLimiterErrorHandler.class); @Override public void handleSaveError(String key, Exception e) { log.error("Failed saving rate for " + key + ", returning unsaved rate", e); } @Override public void handleFetchError(String key, Exception e) { log.error("Failed retrieving rate for " + key + ", will create new rate", e); } @Override public void handleError(String msg, Exception e) { log.error(msg, e); } }
从上述源码可知,DefaultRateLimiterErrorHandler 仅仅使用日志框架记录了日志,没有做其他处理。
在实际的生产环境中,开发人员通常会根据具体的业务需求和系统架构,通过实现 RateLimiterErrorHandler 接口或者继承 DefaultRateLimiterErrorHandler 类来自定义错误处理,以提供更完善、更贴合业务需求的错误处理机制。这有助于提高系统的稳定性和用户体验,在限流操作出现异常时能够更加合理地处理错误,保证系统的正常运行。
例如:通过继承 DefaultRateLimiterErrorHandler 类自定义错误处理。
package com.hxstrive.hystrix_demo.custom; import com.marcosbarbero.cloud.autoconfigure.zuul.ratelimit.config.repository.DefaultRateLimiterErrorHandler; import org.springframework.stereotype.Component; /** * 自定义限流异常处理 * @author hxstrive.com */ @Component public class RateLimiterErrorHandler extends DefaultRateLimiterErrorHandler { @Override public void handleSaveError(String key, Exception e) { System.out.println("handleSaveError: " + key + "自定义限流异常处理: " + e.getMessage()); } @Override public void handleFetchError(String key, Exception e) { System.out.println("handleFetchError: " + key + "自定义限流异常处理: " + e.getMessage()); } @Override public void handleError(String msg, Exception e) { System.out.println("handleError: " + msg + "自定义限流异常处理: " + e.getMessage()); } }
重启 Zuul 服务,并且将 Redis 停掉,再次访问 http://localhost:9000/api/product/product/get?id=1 地址,输出信息如下图:
注意,自定义的错误处理器需要通过 @Component、@Service 注解或者通过配置类的形式纳入 Spring 容器。
点击下载/查看本教程相关资料或者源代码。