热门标签 | HotTags
当前位置:  开发笔记 > 开发工具 > 正文

JavaRPC框架熔断降级机制原理解析

这篇文章主要介绍了JavaRPC框架熔断降级机制原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

熔断与降级

为什么在RPC环节中有熔断以及降级的需求,详细的原因这里不多解释,从网上搜索一张图做示意。

熔断

我理解熔段主要解决如下几个问题:

当所依赖的对象不稳定时,能够起到快速失败的目的快速失败后,能够根据一定的算法动态试探所依赖对象是否恢复

比如产品详细页获取产品的好评总数时,由于后端服务异常导致客户端每次都需要等到超时。如果短时间内服务不能恢复,那么这段时间内的所有请求时间都将是最大的超时时间,这类消费时间又得不到正确结果的现象是不能容忍的。所以遇到这类情况,就需要根据一定的算法判定服务短时间不可用,将后面的请求进行快速失败处理,这样可以节省服务等待时间。

同时,后端服务是有可能自主或者人为在一定时间内恢复的,所以之前被判定为快速失败的服务,需要有能力去试探服务是否已经恢复。

上面提到的快速失败以及自主恢复现象就是熔断

降级

降级是指自己的待遇下降了,从RPC调用环节来讲,就是去访问一个本地的伪装者而不是真实的服务,但这对调用端来说是没有区别的。拿电商展示某个产品的详细页来说:

当加载评论时,由于评论服务不可用,此时可以返回一些默认的评论当加载产品库存,由于库存服务不可用,此时可以固定显示一个库存数

上面提供返回默认评论,固定库存的服务就是伪装服务,这类服务一般不依赖其它服务,稳定性最高。由伪装者提供服务给客户端的现象就是服务降级。

RPC如何支持熔断与降级

一种最简单的办法就是借用hystrix来实现。

引入包依赖

由于示例未采用注解式方案,所以只需要引用下面两个包即可。


  com.netflix.hystrix
  hystrix-core
  ${hystrix-version}


  com.netflix.hystrix
  hystrix-metrics-event-stream
  ${hystrix-version}

实现命令模式

hystrix遵循命令模式,这里可以往这个标准的UML图上去套。

创建一个新的类,RpcHystrixCommand,继承自HystrixCommand即可。

我这里采用线程隔离方式。

构造函数参数

由于需要远程调用,所以构造函数需要接收远程调用所需求必要参数

/**
 * 远程目标方法
 */
private Method method;

/**
 * 远程目标接口
 */
private Object obj;

/**
 * 远程方法所需要的参数
 */
private Object[] params;

/**
 * 远程接口客户端引用注解
 */
private RpcReference rpcReference;

/**
 * RPC客户端配置
 */
private ReferenceConfig referenceConfig;

构造函数方法签名:

public RpcHystrixCommand(Object obj, Method method, Object[] params, RpcReference rpcReference, ReferenceConfig referenceConfig)

初始化hystrix

这里只是一个示例,所以参数设置比较随意,详细的可参考文档。

super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("CircuitBreakerRpcHystrixCommandGroup"))
            .andCommandKey(HystrixCommandKey.Factory.asKey("CircuitBreakerRpcHystrixCommandKey"))
            .andCommandPropertiesDefaults(
                HystrixCommandProperties.Setter()
                    .withCircuitBreakerEnabled(true)
                    .withCircuitBreakerRequestVolumeThreshold(1)
                    .withCircuitBreakerErrorThresholdPercentage(50)
                    .withCircuitBreakerSleepWindowInMilliseconds(5*1000)
                    .withMetricsRollingStatisticalWindowInMilliseconds(10*1000)
            )
            .andThreadPoolKey(HystrixThreadPoolKey.Factory.asKey("CircuitBreakerRpcHystrixCommandPool"))
            .andThreadPoolPropertiesDefaults(
                HystrixThreadPoolProperties.Setter().withCoreSize(100)
        )
    );

run()函数

run()函数就是正常调用时所需要执行的方法,将调用远程通信的逻辑迁移到此,由于此处不涉及今天讲的熔断降级,所以不用关心里面的代码。

@Override
protected Object run() {
 // 执行远程调用
}

扩展rpcReference注解以支持降级

在之前的注解中增加一个属性,用来配置服务伪装者所属的类对象

public @interface RpcReference {
  /**
   * 服务降级的伪装者类对象
   * @return
   */
  Class<&#63;> fallbackServiceClazz() default Object.class;
}

getFallback()函数

当快速失败时,我们希望返回一些预先准备好的值给到客户端,实现这个需求就需要实现这个fallback函数。

伪装者的逻辑由于是客户端控制,所以我们通过参数来动态支持。 通过rpcReference注解可以获取配置的伪装者

protected Object getFallback() {

    Method[] methods = this.rpcReference.fallbackServiceClazz().getMethods();
    for (Method methodFallback : methods) {
      if(this.method.getName().equals(methodFallback.getName())){
        try {
          Object fallbackServiceMock= ApplicationContextUtils.getApplicationContext().getBean(this.rpcReference.fallbackServiceClazz());
          return methodFallback.invoke(fallbackServiceMock,this.params);
        } catch (IllegalAccessException e) {
          logger.error("RpcHystrixCommand.getFallback error",e);
        } catch (InvocationTargetException e) {
          logger.error("RpcHystrixCommand.getFallback error",e);
        }
      }
    }
    throw new RpcException("service fallback unimplement");
  }

RpcProxy嵌入熔断降级机制

代理的invoke方法,将改调用命令模式的execute方法来代替。

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

  RpcHystrixCommand rpcHystrixCommand=new RpcHystrixCommand(proxy,method,args,this.reference,this.referenceConfig);
  return rpcHystrixCommand.execute();
}

客户端使用

dubbo有一个mock机制,功能有些弱,有兴趣可以自行研究。我这里更加倾向于根据逻辑来判断是否使用熔断降级,降级的逻辑需要有更多的支持。

Spring Cloud的熔断降级的做法与我的类似,它是通过注解在接口上

@FeignClient(value = "JIM-CLOUD-PROVIDER-SERVER",fallback = ProductServiceHystrix.class)
public interface ProductService {
  @RequestMapping(value = "/product/{productId}",method = RequestMethod.GET)
  String getById(@PathVariable("productId") final long productId);

}

创建伪装者接口

定义伪装者接口,约定成员方法的签名与真身相同。

public interface ProductCommentMockService {
  Product getById(Long productId);
}

实现伪装者接口

实现伪装者接口,这里不光是简单的固定数据,可心任意编写伪装者业务逻辑,与普通的service bean 没有区别。

@Service
public class ProductCommentMockServiceImpl implements ProductCommentMockService {
  @Override
  public Product getById(Long productId) {

    Product mockProduct=new Product();
    mockProduct.setId(0L);
    mockProduct.setName("mock product name");

    return mockProduct;
  }
}

服务引用使用熔断降级机制

在引用远程服务接口的注解上,配置伪装者接口的类即可。

@RpcReference(
    maxExecutesCount = 1,
    fallbackServiceClazz = ProductCommentMockService.class
)
private ProductService productService;

测试

故意不启动服务端,请求接口,此时出现mock数据说明组件功能正常。

{"id":0,"name":"mock product name"}

待解决问题

由于熔断器采用的是新线程执行,所以会影响Rpc上下文传递的参数传递。

本文源码

https://github.com/jiangmin168168/jim-framework

文中代码是依赖上述项目的,如果有不明白的可下载源码

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


推荐阅读
  • 云原生边缘计算之KubeEdge简介及功能特点
    本文介绍了云原生边缘计算中的KubeEdge系统,该系统是一个开源系统,用于将容器化应用程序编排功能扩展到Edge的主机。它基于Kubernetes构建,并为网络应用程序提供基础架构支持。同时,KubeEdge具有离线模式、基于Kubernetes的节点、群集、应用程序和设备管理、资源优化等特点。此外,KubeEdge还支持跨平台工作,在私有、公共和混合云中都可以运行。同时,KubeEdge还提供数据管理和数据分析管道引擎的支持。最后,本文还介绍了KubeEdge系统生成证书的方法。 ... [详细]
  • 微软头条实习生分享深度学习自学指南
    本文介绍了一位微软头条实习生自学深度学习的经验分享,包括学习资源推荐、重要基础知识的学习要点等。作者强调了学好Python和数学基础的重要性,并提供了一些建议。 ... [详细]
  • 打开文件管理器_【教程】模组管理器3.1食用指南
    文编:byakko最近有部分小伙伴反应还不会使用unity模组管理器,现在我就给大家讲一下unity模组管理器——从下载到使用。完整视频版以下是无WiF ... [详细]
  • 阿里Treebased Deep Match(TDM) 学习笔记及技术发展回顾
    本文介绍了阿里Treebased Deep Match(TDM)的学习笔记,同时回顾了工业界技术发展的几代演进。从基于统计的启发式规则方法到基于内积模型的向量检索方法,再到引入复杂深度学习模型的下一代匹配技术。文章详细解释了基于统计的启发式规则方法和基于内积模型的向量检索方法的原理和应用,并介绍了TDM的背景和优势。最后,文章提到了向量距离和基于向量聚类的索引结构对于加速匹配效率的作用。本文对于理解TDM的学习过程和了解匹配技术的发展具有重要意义。 ... [详细]
  • 本文详细解析了JavaScript中相称性推断的知识点,包括严厉相称和宽松相称的区别,以及范例转换的规则。针对不同类型的范例值,如差别范例值、统一类的原始范例值和统一类的复合范例值,都给出了具体的比较方法。对于宽松相称的情况,也解释了原始范例值和对象之间的比较规则。通过本文的学习,读者可以更好地理解JavaScript中相称性推断的概念和应用。 ... [详细]
  • Android中高级面试必知必会,积累总结
    本文介绍了Android中高级面试的必知必会内容,并总结了相关经验。文章指出,如今的Android市场对开发人员的要求更高,需要更专业的人才。同时,文章还给出了针对Android岗位的职责和要求,并提供了简历突出的建议。 ... [详细]
  • 生成对抗式网络GAN及其衍生CGAN、DCGAN、WGAN、LSGAN、BEGAN介绍
    一、GAN原理介绍学习GAN的第一篇论文当然由是IanGoodfellow于2014年发表的GenerativeAdversarialNetworks(论文下载链接arxiv:[h ... [详细]
  • [译]技术公司十年经验的职场生涯回顾
    本文是一位在技术公司工作十年的职场人士对自己职业生涯的总结回顾。她的职业规划与众不同,令人深思又有趣。其中涉及到的内容有机器学习、创新创业以及引用了女性主义者在TED演讲中的部分讲义。文章表达了对职业生涯的愿望和希望,认为人类有能力不断改善自己。 ... [详细]
  • JavaScript设计模式之策略模式(Strategy Pattern)的优势及应用
    本文介绍了JavaScript设计模式之策略模式(Strategy Pattern)的定义和优势,策略模式可以避免代码中的多重判断条件,体现了开放-封闭原则。同时,策略模式的应用可以使系统的算法重复利用,避免复制粘贴。然而,策略模式也会增加策略类的数量,违反最少知识原则,需要了解各种策略类才能更好地应用于业务中。本文还以员工年终奖的计算为例,说明了策略模式的应用场景和实现方式。 ... [详细]
  • 关于我们EMQ是一家全球领先的开源物联网基础设施软件供应商,服务新产业周期的IoT&5G、边缘计算与云计算市场,交付全球领先的开源物联网消息服务器和流处理数据 ... [详细]
  • 本文介绍了PhysioNet网站提供的生理信号处理工具箱WFDB Toolbox for Matlab的安装和使用方法。通过下载并添加到Matlab路径中或直接在Matlab中输入相关内容,即可完成安装。该工具箱提供了一系列函数,可以方便地处理生理信号数据。详细的安装和使用方法可以参考本文内容。 ... [详细]
  • 无损压缩算法专题——LZSS算法实现
    本文介绍了基于无损压缩算法专题的LZSS算法实现。通过Python和C两种语言的代码实现了对任意文件的压缩和解压功能。详细介绍了LZSS算法的原理和实现过程,以及代码中的注释。 ... [详细]
  • 解决Cydia数据库错误:could not open file /var/lib/dpkg/status 的方法
    本文介绍了解决iOS系统中Cydia数据库错误的方法。通过使用苹果电脑上的Impactor工具和NewTerm软件,以及ifunbox工具和终端命令,可以解决该问题。具体步骤包括下载所需工具、连接手机到电脑、安装NewTerm、下载ifunbox并注册Dropbox账号、下载并解压lib.zip文件、将lib文件夹拖入Books文件夹中,并将lib文件夹拷贝到/var/目录下。以上方法适用于已经越狱且出现Cydia数据库错误的iPhone手机。 ... [详细]
  • 本文介绍了数模国赛的报名参加方法,包括学校报名和自己报名的途径。同时给出了建模竞赛的建议,重在历练的同时掌握方法以及弥补自己的短板。此外,还分享了论文的结构和模型求解部分的注意事项,包括数学命题的表述规范和计算方法的原理等。 ... [详细]
  • 【MicroServices】【Arduino】装修甲醛检测,ArduinoDart甲醛、PM2.5、温湿度、光照传感器等,数据记录于SD卡,Python数据显示,UI5前台,微服务后台……
    这篇文章介绍了一个基于Arduino的装修甲醛检测项目,使用了ArduinoDart甲醛、PM2.5、温湿度、光照传感器等硬件,并将数据记录于SD卡,使用Python进行数据显示,使用UI5进行前台设计,使用微服务进行后台开发。该项目还在不断更新中,有兴趣的可以关注作者的博客和GitHub。 ... [详细]
author-avatar
小辉0110_737
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有