热门标签 | 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

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

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


推荐阅读
  • MyBatisCodeHelperPro 2.9.3 最新在线免费激活方法
    MyBatisCodeHelperPro 2.9.3 是一款强大的代码生成工具,适用于多种开发环境。本文将介绍如何在线免费激活该工具,帮助开发者提高工作效率。 ... [详细]
  • 本文详细记录了 MIT 6.824 课程中 MapReduce 实验的开发过程,包括环境搭建、实验步骤和具体实现方法。 ... [详细]
  • 高效重装Windows 10系统指南
    如何快速地为您的电脑重装Windows 10系统?本文将详细介绍从下载系统镜像到安装完成的每一步操作。 ... [详细]
  • Spring Boot使用AJAX从数据库读取数据异步刷新前端表格
      近期项目需要是实现一个通过筛选选取所需数据刷新表格的功能,因为表格只占页面的一小部分,不希望整个也页面都随之刷新,所以首先想到了使用AJAX来实现。  以下介绍解决方法(请忽视 ... [详细]
  • 探讨密码安全的重要性
    近期,多家知名网站如CSDN、人人网、多玩、开心网等的数据库相继被泄露,其中大量用户的账户密码因明文存储而暴露无遗。本文将探讨黑客获取密码的常见手段,网站如何安全存储用户信息,以及用户应如何保护自己的密码。 ... [详细]
  • 尽管Medium是一个优秀的发布平台,但在其之外拥有自己的博客仍然非常重要。这不仅提供了另一个与读者互动的渠道,还能确保您的内容安全。本文将介绍如何使用Bash脚本将Medium文章迁移到个人博客。 ... [详细]
  • pypy 真的能让 Python 比 C 还快么?
    作者:肖恩顿来源:游戏不存在最近“pypy为什么能让python比c还快”刷屏了,原文讲的内容偏理论,干货比较少。我们可以再深入一点点,了解pypy的真相。正式开始之前,多唠叨两句 ... [详细]
  • 1.前言PAP和CHAP协议是目前的在PPP(MODEM或ADSL拨号)中普遍使用的认证协议,CHAP在RFC1994中定义,是一种挑战响应式协议&#x ... [详细]
  • 本文详细介绍了如何在 CentOS 7 及其衍生发行版(如 Red Hat, Oracle, Scientific Linux 7)上安装和完全卸载 GitLab。包括安装必要的依赖关系、配置防火墙、安装 GitLab 软件包以及常见问题的解决方法。 ... [详细]
  • 本打算教一步步实现koa-router,因为要解释的太多了,所以先简化成mini版本,从实现部分功能到阅读源码,希望能让你好理解一些。希望你之前有读过koa源码,没有的话,给你链接 ... [详细]
  • Encountering frequent mismatches during Terraform apply operations, particularly with resource attributes. ... [详细]
  • Spring Boot与Graylog集成实现微服务日志聚合与分析
    本文介绍了如何在Graylog中配置输入源,并详细说明了Spring Boot项目中集成Graylog的日志聚合和分析方法,包括logback.xml的多环境配置。 ... [详细]
  • 文章目录python包-requests关于requests包安装和使用pythonrequests请求超时设置工作中遇到的常见问题整理访问https网站,报错cer ... [详细]
  • ABP框架是ASP.NET Boilerplate的简称,它不仅是一个开源且文档丰富的应用程序框架,还提供了一套基于领域驱动设计(DDD)的最佳实践架构模型。本文将详细介绍ABP框架的特点、项目结构及其在Web API优先架构中的应用。 ... [详细]
  • 四、作为您的 VCS 的 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社区 版权所有