您的位置:

Spring Boot限流方案

考虑到应用系统可能会遭受恶意的流量冲击或者是突发的高并发请求,我们需要实现对系统资源的限流操作,以确保系统优雅的处理请求。Spring Boot限流是从监控分析,性能调优出发,阻止非法请求,控制并发,保障系统可用以及数据安全等方面都能给出解答,下面从框架、降级、限流器、方案、组件、插件、redis、注解、springcloud限流组件选取等方面进行详细的阐述。

一、Spring Boot限流框架

Spring Boot限流框架可以分为两类: 基于外部组件的限流和基于自研组件的限流。 基于外部组件的常见限流框架:Netflix Hystrix、阿里Sentinel,银联OPS、京东Cat等; 基于自研组件的限流框架: Rate Limiter、Bucket4J等。 Netflix Hystrix是一种基于线程和信号模型的隔离器,用于延迟和故障容错,主要是按照一定规则对访问服务的进行限流限速或者降级处理。阿里Sentinel是一款优秀的开源API高可用保护框架,提供外部的流量控制、降级、熔断和系统负载等保护能力。银联OPS支持依据多种指标实现对分布式系统般的限流,结果百分比统计;京东Cat则是用于监控和管理大规模分布式系统的开源框架。

二、Spring Boot限流降级

由于流量太大等情况,甚至会导致系统崩溃,所以需要在限流失败的时候进行如何优雅的降级处理。Spring Boot限流降级措施包括: - 快速失败:当请求超过限流阈值时,快速直接给出失败响应; - 返回静态响应:当请求超过阈值时,返回预设的静态响应内容; - 返回动态降级:当请求超过阈值时,根据实际情况动态降级,例如关闭某个功能,降低返回结果精度等手段。

三、Spring Boot限流器

限流器是Spring Boot限流体系中的重要组件之一,管控着系统并发访问或流量的统计和流量的控制等。他是限流的精华,那么知道Java中主流的限流的实现方式,可以分为以下几种: - 计数器算法:最简单常见限流算法,通过一个计数器和阈值来控制访问频率; - 漏桶算法:控制速率,通过不断向漏桶中放水来限流; - 令牌桶算法:控制速率,每过来一个请求就消耗一个令牌。

四、Spring Boot限流方案

Spring Boot限流方案包括限流线程池、令牌桶流控和漏桶流控。

五、Spring Boot限流组件

目前常用的Spring Boot限流组件有Sentinel,Hystrix等。 Sentinel是一个全面的流量管理框架,主要是从流量控制和熔断机制来控制流量,可以及时响应和处理,方便做到及时恢复。Hystrix 是Netflix开发的一款容错框架,以线程隔离或者信号量模式对不同的依赖请求进行隔离,从而限制请求量。其流量控制是依靠分布式线程池来实现的,非常强大和灵活。

六、Spring Boot限流插件

限流插件可以对Dubbo服务进行流量控制,基于 dubbo的TokenBucket做到对服务限流;另外还有apollo、sentinel等流控组件,可以结合Spring Boot进行使用。

七、Spring Boot限流设置

可以通过属性设置或代码设置两种方式来实现Spring Boot限流设置。属性配置示例代码如下: ``` # 配置Sentinel流控规则 spring.cloud.sentinel.datasource.ds1.nacos.server-addr=127.0.0.1:8848 spring.cloud.sentinel.datasource.ds1.nacos.data-id=${spring.application.name}-sentinel spring.cloud.sentinel.datasource.ds1.nacos.group-id=SENTINEL_GROUP spring.cloud.sentinel.filter.order=0 ``` 通过代码动态设置限流规则示例代码如下: ``` // Sentinel控制台的"应用名称" String application = "myApp"; // 需要流控的服务名称,按 application:serviceName 格式拼接 String resource = application + ":" + "someService"; // 配置项名称,多个配置项可用","隔开 String param = "timeout" // 1 // 手动添加管制规则 FlowRule rule = new FlowRule(); rule.setResource(resource); rule.setCount(10); rule.setGrade(RuleConstant.FLOW_GRADE_QPS); rule.setLimitApp("default"); FlowRuleManager.loadRules(Collections.singletonList(rule)); // 2 // 手动更新管制规则 FlowRule rule = new FlowRule(); rule.setResource(resource); rule.setCount(20); rule.setGrade(RuleConstant.FLOW_GRADE_QPS); rule.setLimitApp("default"); FlowRuleManager.loadRules(Collections.singletonList(rule)); ```

八、Spring Boot限流注解

可以使用@RateLimit注解实现方法限流,示例代码如下: ``` @GetMapping("/test") @RateLimit(key="userId", time = 1, count = 10, msg="操作过于频繁,请稍后再试") public void test(@RequestParam String userId) { System.out.println("test"); } ```

九、Spring Boot限流Redis

可以使用Redis实现限流,存储规则访问次数与过期时间相结合,示例代码如下: ``` //根据ip限流 @RequestMapping("/test") public String test(@RequestParam String ip)throws Exception{ String luaScript = "local key = KEYS[1]\n" + "local limit = tonumber(ARGV[1])\n" + "local expireTimeMS = tonumber(ARGV[2])\n" + "local curLimit = tonumber(redis.call('get', key) or '0')\n" + "if curLimit + 1 > limit then return 0 end\n" + "redis.call('INCRBY', key, 1)\n" + "redis.call('pexpire', key, expireTimeMS)\n" + "return 1"; Jedis jedis = jedisPool.getResource(); try { String limitCount= jedis.eval(luaScript, Collections.singletonList("Ip_Limit:" + ip), Collections.singletonList("1000"), Collections.singletonList("60"), Integer.toString(1000*60)).toString(); if("0".equals(limitCount)){ return "访问过于频繁"; } //正常返回 }finally { jedis.close(); } } ```

十、Spring Cloud限流组件选取

Spring Cloud全家桶中的限流组件包括Gateway、Zuul,可以结合具体业务场景进行选取和使用。

十一、总结

本文对Spring Boot限流进行了详细的阐述,从框架、降级、限流器、方案、组件、插件、redis、注解、Spring Cloud限流组件等方面展开讲解,期望能对读者有所启示。