Java RPC框架如何实现客户端限流配置

关键资源

关键资源总是有限的,也就意味着处理能力也有限,所以当面对大量业务时,为了保障自己能够有序的提供服务最经济的做法就是限制同一时间处理的事务数。比如银行的工作人员,一个工作人员同时只能为一个客户服务,来多了根本处理不了,不光是一种浪费而且有可以造成混乱的局面导致工作人员无法工作。

网络请求漏斗

越上层的服务器处理的事务越轻,应付请求的能力也越强,也就意味着同一请求越上层处理时间越短。为了有效的保护下层服务器,就需要对发送给下层的请求量做限流,在下层服务器可接受的范围内。否则就可能会出现下层服务器资源耗尽而无法正常提供服务的情况。

限流场景服务端限流

如果在服务端做限流,无论有多少个客户端,总的提供能力是固定的(感谢@ xuanbg提出的评论,指出服务端也可以对客户端做精准的判断,后续我再想想实现方案),所以不会因为客户端数量过多而导致资源不足,因为处理不过来的请求会被阻塞等待获取资源。

缺点

缺点也比较明显,由于服务提供者整体设置了最大限流数,此时所有的客户端共享同一份限流数据,那么有可能导致有的服务能分配到资源有些服务请求分配不到资源导致无法请求的情况。

客户端限流

客户端限流解决上服务端限流提到的问题,它能保证每个客户端都能得到响应。但是从其它方面考虑,必须针对不同的客户端做不同的限流策略:

请求量大,但时效性不高,此时将限流数控制小一些会比较合适请求量大,但时效性高,此时将限流数适当调高响应时间长,即慢接口,适当降低主流业务,核心业务,适当调高非主流业务,适当降低......

缺点

如果客户端的数量不固定,那么有可能导致客户端数量过多造成大量请求打到服务端导致处理不了的结果,所以需要严格监控客户端的调用情况。

配置复杂,需要针对每个客户端做相对精准的判断

RPC实现

限流

这里指的限流是指每秒从客户端提交到服务端的请求数量。

服务引用注解上增加限流

public @interface RpcReference {
  boolean isSync() default true;

  /**
   * 客户端最大并发数
   * @return
   */
  int maxExecutesCount() default 10;
}

创建动态代理时将限流参数传递到服务端

需要修改RpcProxy类,构造函数中增加服务引用注解参数,然后在invoke方法中从服务引用注解中获取限流参数传递给request对象。

public RpcProxy(Class<T> clazz,ReferenceConfig referenceConfig,RpcReference reference) {
    this.clazz = clazz;
    this.referenceConfig=referenceConfig;
    this.reference=reference;
    this.isSync=reference.isSync();
  }

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

    ...

    if (this.reference != null) {
      request.setMaxExecutesCount(this.reference.maxExecutesCount());
    }
    ...
  }

AbstractInvoker修改buildRpcInvocation方法

从request对象中获取限流参数,传递给RpcInvocation对象。

public interface RpcInvocation {

  ...

  int getMaxExecutesCount();

}

AccessLimitFilter修改令牌管理器

按接口分配令牌管理器,令牌管理器存储在map中共享。如果未初始化则进行令牌管理器的初始化,如果已经初始化则直接申请令牌。

public RpcInvocation buildRpcInvocation(RpcRequest request){
    RpcInvocation rpcInvocation=new RpcInvocation() {
      ...
      @Override
      public int getMaxExecutesCount() {
        return request.getMaxExecutesCount();
      }
    };
    return rpcInvocation;
  }

修改invoke方法

将invocation参数传递给acquire方法。

  public Object invoke(RpcInvoker invoker, RpcInvocation invocation) {
    logger.info("before acquire,"+new Date());
    AccessLimitManager.acquire(invocation);

    Object rpcResponse=invoker.invoke(invocation);
    logger.info("after acquire,"+new Date());
    return rpcResponse;
  }

客户端服务引用配置限流

这里配置每秒一个请求

@RpcReference(maxExecutesCount = 1)
private ProductService productService;

执行结果

如下图所示,每次请求相隔了一秒,达到了限流请求的目的。

支持方法级限流

以上只支持客户端接口级别的限流配置,可以再单独创建一个方法级的注解来配置相关参数。

支持服务端限流

服务端限流尽管有它的缺点,但为了更好的保护服务提供者,需要结合多种业务场景来配合客户端限流一起完善,取长补短共同发挥作用。

本文源码

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

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

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

(0)

相关推荐

  • Java RPC框架过滤器机制原理解析

    过滤器 字面义上理解的过滤器类似下图,从一堆物品中筛选出符合条件的留下,不符合的丢弃. GOF 职责链 GOF中有一种设计模式叫职责链,或者叫责任链,常规的UML图如下: 正统的职责链是将一个请求发给第一个接收者,接收者判断是否属于自己能处理的,如果能处理则执行操作并中止请求下发,流程到此为止.如果不能处理则将请求下发给下一个接收者一直到最后一个接收者. 变体职责链 上面提到正统的职责链有一个特点:当找到符合条件的执行者后流程中止并不会将请求继续下发给后续的执行者.这类场景比较适合比如审核操作,

  • Java RPC框架熔断降级机制原理解析

    熔断与降级 为什么在RPC环节中有熔断以及降级的需求,详细的原因这里不多解释,从网上搜索一张图做示意. 熔断 我理解熔段主要解决如下几个问题: 当所依赖的对象不稳定时,能够起到快速失败的目的快速失败后,能够根据一定的算法动态试探所依赖对象是否恢复 比如产品详细页获取产品的好评总数时,由于后端服务异常导致客户端每次都需要等到超时.如果短时间内服务不能恢复,那么这段时间内的所有请求时间都将是最大的超时时间,这类消费时间又得不到正确结果的现象是不能容忍的.所以遇到这类情况,就需要根据一定的算法判定服务

  • Java利用Sping框架编写RPC远程过程调用服务的教程

    RPC,即 Remote Procedure Call(远程过程调用),说得通俗一点就是:调用远程计算机上的服务,就像调用本地服务一样. RPC 可基于 HTTP 或 TCP 协议,Web Service 就是基于 HTTP 协议的 RPC,它具有良好的跨平台性,但其性能却不如基于 TCP 协议的 RPC.会两方面会直接影响 RPC 的性能,一是传输方式,二是序列化. 众所周知,TCP 是传输层协议,HTTP 是应用层协议,而传输层较应用层更加底层,在数据传输方面,越底层越快,因此,在一般情况下

  • Java实现布隆过滤器的方法步骤

    前言 记得前段时间的文章么?redis使用位图法记录在线用户的状态,还是需要自己实现一个IM在线用户状态的记录,今天来讲讲另一方案,布隆过滤器 布隆过滤器的作用是加快判定一个元素是否在集合中出现的方法.因为其主要是过滤掉了大部分元素间的精确匹配,故称为过滤器. 布隆过滤器 在日常生活工作,我们会经常遇到这的场景,从一个Excel里面检索一个信息在不在Excel表中,还记得被CTRL+F支配的恐惧么,不扯了,软件开发中,一般会使用散列表来实现,Hash Table也叫哈希表,哈希表的优点是快速准确

  • Java中的拦截器、过滤器、监听器用法详解

    本文实例讲述了Java中的拦截器.过滤器.监听器用法.分享给大家供大家参考,具体如下: 一.拦截器 :是在面向切面编程的就是在你的service或者一个方法,前调用一个方法,或者在方法后调用一个方法比如动态代理就是拦截器的简单实现,在你调用方 法前打印出字符串(或者做其它业务逻辑的操作),也可以在你调用方法后打印出字符串,甚至在你抛出异常的时候做业务逻辑的操作. 1.Struts2拦截器是在访问某个Action或Action的某个方法,字段之前或之后实施拦截,并且Struts2拦截器是可插拔的,

  • JAVA实现较完善的布隆过滤器的示例代码

    布隆过滤器是可以用于判断一个元素是不是在一个集合里,并且相比于其它的数据结构,布隆过滤器在空间和时间方面都有巨大的优势.布隆过滤器存储空间和插入/查询时间都是常数.但是它也是拥有一定的缺点:布隆过滤器是有一定的误识别率以及删除困难的.本文中给出的布隆过滤器的实现,基本满足了日常使用所需要的功能. 0 0 0 0 0 0 0 0 0 0 先简单来说一下布隆过滤器.其实现方法就是:利用内存中一个长度为M的位数组B并初始化里面的所有位都为0,如下面的表格所示: 然后我们根据H个不同的散列函数,对传进来

  • PHP和JAVA的XML-RPC中文问题解决办法

    问题描述:      在使用PHP和JAVA操作XML-RPC的时候,如果request中包含中文字符,会被自动编码成如下样式: 欢欢 . 环境:PHP内置XML-RPC的API,Apache的XML-RPC的JAVA API PHP下的解决方法:      起初以为是中文字符的编码问题,所以我就尝试用各种编码方式来编码中文字符,然后交给string xmlrpc_encode_request ( string method, mixed params)函数来生成XML格式的请求,可是依然如故.

  • 分析JAVA中几种常用的RPC框架

    RPC是远程过程调用的简称,广泛应用在大规模分布式应用中,作用是有助于系统的垂直拆分,使系统更易拓展.Java中的RPC框架比较多,各有特色,广泛使用的有RMI.Hessian.Dubbo等.RPC还有一个特点就是能够跨语言,本文只以JAVA语言里的RPC为例. 对于RPC有一个逻辑关系图,以RMI为例: 其他的框架结构也类似,区别在于对象的序列化方法,传输对象的通讯协议,以及注册中心的管理与failover设计(利用zookeeper). 客户端和服务端可以运行在不同的JVM中,Client只

  • Java实现简单的RPC框架的示例代码

    一.RPC简介 RPC,全称为Remote Procedure Call,即远程过程调用,它是一个计算机通信协议.它允许像调用本地服务一样调用远程服务.它可以有不同的实现方式.如RMI(远程方法调用).Hessian.Http invoker等.另外,RPC是与语言无关的. rpc框架做的最重要的一件事情就是封装,调用者和被调用者的通讯细节,客户端代理负责向调用方法的方法名参数返回值包等信息根据通信协议组织成报文发送给服务端,服务端解析报文,根据客户端传递的信息执行对应的方法,然后将返回值安装协

  • Java RPC框架如何实现客户端限流配置

    关键资源 关键资源总是有限的,也就意味着处理能力也有限,所以当面对大量业务时,为了保障自己能够有序的提供服务最经济的做法就是限制同一时间处理的事务数.比如银行的工作人员,一个工作人员同时只能为一个客户服务,来多了根本处理不了,不光是一种浪费而且有可以造成混乱的局面导致工作人员无法工作. 网络请求漏斗 越上层的服务器处理的事务越轻,应付请求的能力也越强,也就意味着同一请求越上层处理时间越短.为了有效的保护下层服务器,就需要对发送给下层的请求量做限流,在下层服务器可接受的范围内.否则就可能会出现下层

  • 详解Nginx限流配置

    本文以示例的形式,由浅入深讲解Nginx限流相关配置,是对简略的官方文档的积极补充. Nginx限流使用的是leaky bucket算法,如对算法感兴趣,可移步维基百科先行阅读.不过不了解此算法,不影响阅读本文. 空桶 我们从最简单的限流配置开始: limit_req_zone $binary_remote_addr zone=ip_limit:10m rate=10r/s; server { location /login/ { limit_req zone=ip_limit; proxy_p

  • Java Mybatis框架增删查改与核心配置详解流程与用法

    目录 Mybatis简介 Mybatis开发步骤: Mybatis的映射文件概述 Mybatis的增删改查操作 MyBatis的核心配置文件概述 MyBatis核心配置文件层级关系 MyBatis常用配置解析 Mybatis相应API 原始JDBC操作 原始jdbc操作(查询数据) 原始jdbc操作(插入数据) 原始jdbc操作的分析原始jdbc开发存在的问题如下: ①数据库连接创建.释放频繁造成系统资源浪费从而影响系统性能 ②sql 语句在代码中硬编码,造成代码不易维护,实际应用sql变化的可

  • Nginx抢购限流配置实现解析

    因业务需求经常会有抢购业务,因此需要在负载均衡前端进行限流错误.本文同样也适用于防止CC. limit_req_zone $server_name zone=sname:10m rate=1r/s; #限制服务器每秒只能有一次访问成功 #limit_req_zone $binary_remote_addr zone=one:3m rate=1r/s; #限制IP,每秒只能访问一次 #limit_req_zone $binary_remote_addr $uri zone=two:3m rate=

  • Nginx对网段内ip的连接数限流配置详解

    Nginx中的所谓连接数限制,其实是tcp连接,也就是请求方通过三次握手后成功建立的连接状态.Nginx一般为我们提供了 ngx_http_limit_conn_module 模块来提供限制连接功能.该模块可以根据定义的键来限制每个键值的连接数,如同一个IP来源的连接数. ngx_http_limit_conn_module指令解释 Syntax: limit_conn zone number; Default: - Context: http, server, location 该指令描述会话

  • .Net Core限流的实现示例

    目录 一.环境 二.基础使用 1.设置 2.规则设置 3.特殊规则的启用 三.请求返回头 四.使用Redis存储 1.访问计数 2.ip特殊规则 3.客户端特殊规则 五.修改规则 一.环境 1.vs2019 2..Net Core 3.1 3.引用 AspNetCoreRateLimit 4.0.1 二.基础使用 1.设置 在Startup文件中配置如下,把配置项都放在前面: public void ConfigureServices(IServiceCollection services) {

  • Java 常见的限流算法详细分析并实现

    目录 为什么要限流 限流算法 计数器限流 漏桶限流 令牌桶限流 为什么要限流 在保证可用的情况下尽可能多增加进入的人数,其余的人在排队等待,或者返回友好提示,保证里面的进行系统的用户可以正常使用,防止系统雪崩. 限流算法 限流算法很多,常见的有三类,分别是 计数器算法 .漏桶算法.令牌桶算法 . (1)计数器:           在一段时间间隔内,处理请求的最大数量固定,超过部分不做处理. (2)漏桶:           漏桶大小固定,处理速度固定,但请求进入速度不固定(在突发情况请求过多时

  • java限流算法详细

    目录 1.场景 2.算法详解 2.1 计数算法 2.1.1 说明 2.1.2 适用场景 2.1.3 代码 2.2 漏桶算法 2.2.1 说明 2.2.2 漏桶算法图示 2.2.3 适用场景 2.2.4 代码 2.3 令牌桶算法 2.3.1 说明 2.3.2 令牌桶算法图示 2.3.3 适用场景 2.3.4 代码 2.3.5 第三方工具类 1.场景 程序中经常需要对接口进行限流,防止访问量太大,导致程序崩溃. 常用的算法有:计数算法.漏桶算法.令牌桶算法,最常用的算法是后面两种. 2.算法详解 2

随机推荐