Spring Cloud升级之路 - Hoxton - 8. 修改实例级别的熔断为实例+方法级别

简介: Spring Cloud升级之路 - Hoxton - 8. 修改实例级别的熔断为实例+方法级别

实例级别的熔断带来的困扰


如之前系列(Spring Cloud升级之路 - Hoxton - 4. 使用Resilience4j实现实例级别的隔离与熔断)所述,我们实现了实例级别的熔断。但是在生产中发现,并不是所有情况下都表现良好。首先如果发布了新接口,但是不小心回滚了,调用新接口就会报错,从而导致整个实例都不能访问。还有就是某些实例某个接口出现了问题,但是其他接口是好的,熔断掉整个实例有点浪费。于是乎,我们将实例级别的熔断改成 实例 + 方法级别。


对于 OpenFeign 修改


首先,我们只针对断路器进行修改,线程隔离还是实例级别的,如果也抽象为实例+方法级别的,线程数与线程池的数量就太多了。


每个 Feign 调用都是有 url 的,我们是不是可以通过 url 获取不同的断路器呢?这样做是可以的,的确实现了实例 + 方法级别的熔断。但是有一个问题,对于有 PathVaraiable 的 FeignClient,相当于每个参数都会新建一个断路器,这并不是我们想要的,例如:


package com.github.hashjang.hoxton.service.consumer.feign;
//省略import
@FeignClient(value = "service-provider")
public interface ServiceProviderTestReadTimeoutFeignCleint {
    @RequestMapping(value = "/test-read-time-out/{userId}", method = RequestMethod.GET)
    String testTimeoutGet(@PathVariable String userId);
}

这样的话,对于每一个 userId 都会生成一个不同的断路器,这样断路器实际上可能没起到该有的作用。


所以,还是用实际 Feign 接口的类全限定方法名称作为唯一标识。


LoadBalancerConfig.java:


@Override
public Response execute(Request request, Request.Options options) throws IOException {
    String serviceName = request.requestTemplate().feignTarget().name();
    String serviceInstanceId = getServiceInstanceId(request);
    String serviceInstanceMethodId = getServiceInstanceMethodId(request);
    ThreadPoolBulkhead threadPoolBulkhead;
    CircuitBreaker circuitBreaker;
    try {
        //每个实例一个线程池
        threadPoolBulkhead = threadPoolBulkheadRegistry.bulkhead(serviceInstanceId, serviceName);
    } catch (ConfigurationNotFoundException e) {
        threadPoolBulkhead = threadPoolBulkheadRegistry.bulkhead(serviceInstanceId);
    }
    try {
        //每个服务实例具体方法一个resilience4j熔断记录器,在服务实例具体方法维度做熔断,所有这个服务的实例具体方法共享这个服务的resilience4j熔断配置
        circuitBreaker = circuitBreakerRegistry.circuitBreaker(serviceInstanceMethodId, serviceName);
    } catch (ConfigurationNotFoundException e) {
        circuitBreaker = circuitBreakerRegistry.circuitBreaker(serviceInstanceMethodId);
    }
    //省略之后代码
}
private String getServiceInstanceId(Request request) throws MalformedURLException {
    String serviceName = request.requestTemplate().feignTarget().name();
    URL url = new URL(request.url());
    return serviceName + ":" + url.getHost() + ":" + url.getPort();
}
private String getServiceInstanceMethodId(Request request) throws MalformedURLException {
    String serviceName = request.requestTemplate().feignTarget().name();
    URL url = new URL(request.url());
    //通过微服务名称 + 实例 + 方法的方式,获取唯一id
    String methodName = request.requestTemplate().methodMetadata().method().toGenericString();
    return serviceName + ":" + url.getHost() + ":" + url.getPort() + ":" + methodName;
}


对于 Spring Cloud Gateway 修改


对于 Spring Cloud Gateway,仅仅是在断路器上面加上 url, 同样的,会有上面说的,如果 url 中带有某个参数的 PathVariable,会生成很多独立的断路器的问题,这个目前还没有什么办法好解决。 并且,网关对于 404 并不认为是错误,只对IO异常以及超时会有错误。这种情况下,对于实例熔断,也并不是不能接受,虽然还会有某个接口超时导致实例熔断的风险,但是将超时时间设置足够长,以后后续的微服务进行异常处理熔断,也是可以接受的。


综合评估之后,网关还是继续保持实例级别的熔断

相关文章
|
18天前
|
人工智能 JSON 前端开发
Spring Boot解决跨域问题方法汇总
Spring Boot解决跨域问题方法汇总
|
2天前
|
移动开发 前端开发 NoSQL
ruoyi-nbcio从spring2.7.18升级springboot到3.1.7,java从java8升级到17(二)
ruoyi-nbcio从spring2.7.18升级springboot到3.1.7,java从java8升级到17(二)
15 0
|
3天前
|
监控 安全 Java
Spring cloud原理详解
Spring cloud原理详解
14 0
|
7天前
|
Java Spring
Spring的@Retryable实现方法重试
`@Retryable`注解用于配置异常重试,参数包括:指定异常类型`value`,额外包含异常`include`,排除异常`exclude`,最大尝试次数`maxAttempts`和回退策略`backoff`。可选地,可以用`retryExceptions`列表替换`value`。当重试失败,可使用`@Recover`注解定义恢复逻辑。
17 1
|
7天前
|
消息中间件 负载均衡 Java
【Spring Cloud 初探幽】
【Spring Cloud 初探幽】
14 1
|
9天前
|
Java 开发者 微服务
Spring Cloud原理详解
【5月更文挑战第4天】Spring Cloud是Spring生态系统中的微服务框架,包含配置管理、服务发现、断路器、API网关等工具,简化分布式系统开发。核心组件如Eureka(服务发现)、Config Server(配置中心)、Ribbon(负载均衡)、Hystrix(断路器)、Zuul(API网关)等。本文讨论了Spring Cloud的基本概念、核心组件、常见问题及解决策略,并提供代码示例,帮助开发者更好地理解和实践微服务架构。此外,还涵盖了服务通信方式、安全性、性能优化、自动化部署、服务网格和无服务器架构的融合等话题,揭示了微服务架构的未来趋势。
32 6
|
11天前
|
Java 微服务 Spring
Spring Boot中获取配置参数的几种方法
Spring Boot中获取配置参数的几种方法
21 2
|
13天前
|
JSON Java Apache
Spring Cloud Feign 使用Apache的HTTP Client替换Feign原生httpclient
Spring Cloud Feign 使用Apache的HTTP Client替换Feign原生httpclient
|
13天前
|
负载均衡 Java 开发者
Spring Cloud:一文读懂其原理与架构
Spring Cloud 是一套微服务解决方案,它整合了Netflix公司的多个开源框架,简化了分布式系统开发。Spring Cloud 提供了服务注册与发现、配置中心、消息总线、负载均衡、熔断机制等工具,让开发者可以快速地构建一些常见的微服务架构。