返回顶部
首页 > 资讯 > 后端开发 > Python >springboot+redis 实现分布式限流令牌桶的示例代码
  • 876
分享到

springboot+redis 实现分布式限流令牌桶的示例代码

2024-04-02 19:04:59 876人浏览 安东尼

Python 官方文档:入门教程 => 点击学习

摘要

1、前言 网上找了很多Redis分布式限流方案,要不就是太大,需要引入第三方jar,而且还无法正常运行,要不就是定时任务定时往key中放入数据,使用的时候调用,严重影响性能,所以着手

1、前言

网上找了很多Redis分布式限流方案,要不就是太大,需要引入第三方jar,而且还无法正常运行,要不就是定时任务定时往key中放入数据,使用的时候调用,严重影响性能,所以着手自定义实现redis令牌桶。
只用到了spring-boot-starter-data-redis包,并且就几行代码。

2、环境准备

a、idea新建SpringBoot项目,引入spring-data-redis包
b、编写令牌桶实现方法RedisLimitExcutor
c、测试功能,创建全局拦截器,测试功能

3、上代码

在这里插入图片描述

Maven添加依赖


        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

令牌桶实现方法RedisLimitExcutor


package com.example.redis_limit_demo.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;


@Component
public class RedisLimitExcutor {

    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    public void setStringRedisTemplate(StringRedisTemplate stringRedisTemplate) {
        this.stringRedisTemplate = stringRedisTemplate;
    }

    
    public boolean tryAccess(String key, int limitCount, int seconds) {
        String luaScript = buildLuaScript();
        RedisScript<Long> redisScript = new DefaultRedisScript<>(luaScript, Long.class);
        List<String> keys = new ArrayList<>();
        keys.add(key);
        Long count = stringRedisTemplate.execute(redisScript, keys, String.valueOf(limitCount), String.valueOf(seconds));
        if (count != 0) {
            return true;
        } else {
            return false;
        }
    }

    
    private static final String buildLuaScript() {
        StringBuilder lua = new StringBuilder();
        lua.append(" local key = KEYS[1]");
        lua.append("\nlocal limit = tonumber(ARGV[1])");
        lua.append("\nlocal curentLimit = tonumber(redis.call('get', key) or \"0\")");
        lua.append("\nif curentLimit + 1 > limit then");
        lua.append("\nreturn 0");
        lua.append("\nelse");
        lua.append("\n redis.call(\"INCRBY\", key, 1)");
        lua.append("\nredis.call(\"EXPIRE\", key, ARGV[2])");
        lua.append("\nreturn curentLimit + 1");
        lua.append("\nend");
        return lua.toString();
    }
}

拦截器配置WEBAppConfig


package com.example.redis_limit_demo.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorReGIStry;
import org.springframework.web.servlet.config.annotation.WebmvcConfigurer;


@Configuration
public class WebAppConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(getRequestInterceptor()).addPathPatterns("
@Configuration
public class RequestInterceptor implements HandlerInterceptor {
    @Autowired
    private RedisLimitExcutor redisLimitExcutor;


    
    @Override
    public boolean preHandle(httpservletRequest request, HttpServletResponse response, Object handler) {
        
        String url = request.getRequestURI();
        String ip = getIpAdd(request);
        //QPS设置为5,手动刷新接口可以测试出来
        if (!redisLimitExcutor.tryAccess(ip+url, 5, 1)) {
            throw new RuntimeException("调用频繁");
        } else {
            return true;
        }
    }

    public static final  String getIpAdd(HttpServletRequest request) {
        String ipAddress = request.getHeader("x-forwarded-for");
        if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getHeader("Proxy-Client-IP");
        }
        if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getRemoteAddr();
            if (ipAddress.equals("127.0.0.1") || ipAddress.equals("0:0:0:0:0:0:0:1")) {
                // 根据网卡取本机配置的IP
                InetAddress inet = null;
                try {
                    inet = InetAddress.getLocalHost();
                } catch (UnknownHostException e) {
                    return null;
                }
                ipAddress = inet.getHostAddress();
            }
        }
        // 如果通过代理访问,可能获取2个IP,这时候去第二个(代理服务端IP)
        if (ipAddress.split(",").length > 1) {
            ipAddress = ipAddress.split(",")[1].trim();
        }
        return ipAddress;
    }


}

测试controller


package com.example.redis_limit_demo.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RequestMapping("demo")
@RestController
public class DemoController {


    @RequestMapping("limit")
    public String demo() {
        //todo 写业务逻辑
        return "aaaaa";
    }

}

4、运行项目,访问接口

http://localhost:8080/demo/limit

在这里插入图片描述

当刷新频率高了以后,就会报错

5、码云地址(GitHub经常访问不到)

备注:

1、 redis的key可以根据实际情况设置,入例子中的ip+url,可以将全部流量进行控制,防止恶意刷接口,但需要注意的是,使用ip方式,要将QPS设置大一些,因为会出现整个大厦公用一个ip的情况。也可以使用url+userName,将QPS设置小一点,可以更加精准的限制api的访问。
2、可以将抛出异常进行全局捕获和统一返回。

到此这篇关于springboot+redis 实现分布式限流令牌桶的示例代码的文章就介绍到这了,更多相关springboot redis分布式限流令牌桶内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: springboot+redis 实现分布式限流令牌桶的示例代码

本文链接: https://lsjlt.com/news/124811.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • springboot+redis 实现分布式限流令牌桶的示例代码
    1、前言 网上找了很多redis分布式限流方案,要不就是太大,需要引入第三方jar,而且还无法正常运行,要不就是定时任务定时往key中放入数据,使用的时候调用,严重影响性能,所以着手...
    99+
    2024-04-02
  • SpringBoot+Redis+Lua分布式限流的实现
    Redis支持LUA脚本的主要优势 LUA脚本的融合将使Redis数据库产生更多的使用场景,迸发更多新的优势: 高效性:减少网络开销及时延,多次redis服务器网络请求的操作,使用L...
    99+
    2022-11-13
    SpringBoot Redis Lua分布式限流 SpringBoot 分布式限流
  • Springboot+Redis实现API接口限流的示例代码
    添加Redis的jar包. <dependency> <groupId>org.springframework.boot</groupId&...
    99+
    2024-04-02
  • Go 基于令牌桶的限流器实现
    目录简介 原理概述具体实现原理 限流器如何限流 简介 如果一般流量过大,下游系统反应不过来,这个时候就需要限流了,其实和上地铁是一样的,就是减慢上游访问下游的速度。 限制访问服务的...
    99+
    2024-04-02
  • Spring Cloud Gateway中的令牌桶限流算法实例分析
    这篇“Spring Cloud Gateway中的令牌桶限流算法实例分析”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一...
    99+
    2023-06-29
  • springboot+zookeeper实现分布式锁的示例代码
    目录依赖本地封装配置测试代码JMeter测试InterProcessMutex内部实现了zookeeper分布式锁的机制,所以接下来我们尝试使用这个工具来为我们的业务加上分布式锁处理...
    99+
    2024-04-02
  • Springboot使用redis实现接口Api限流的示例代码
    前言 该篇介绍的内容如题,就是利用redis实现接口的限流(  某时间范围内 最大的访问次数 ) 。 正文  惯例,先看下我们的实战目录结构: 首先...
    99+
    2024-04-02
  • ASP.NET Core中使用令牌桶限流的实现
    在限流时一般会限制每秒或每分钟的请求数,简单点一般会采用计数器算法,这种算法实现相对简单,也很高效,但是无法应对瞬时的突发流量。 比如限流每秒100次请求,绝大多数的时间里都不会超过...
    99+
    2024-04-02
  • 用Go+Redis实现分布式锁的示例代码
    目录为什么需要分布式锁 分布式锁需要具备特性 实现 Redis 锁应先掌握哪些知识点 set 命令 Redis.lua 脚本 go-zero 分布式锁 RedisLock 源码分析 ...
    99+
    2024-04-02
  • 用Go+Redis实现分布式锁的示例代码
    目录为什么需要分布式锁分布式锁需要具备特性实现 Redis 锁应先掌握哪些知识点set 命令Redis.lua 脚本go-zero 分布式锁 RedisLock 源码分析关于分...
    99+
    2022-06-07
    GO 示例 分布式 分布 分布式锁 Redis
  • redis如何实现分布式限流
    Redis可以使用令牌桶算法来实现分布式限流。令牌桶算法是一种常用的限流算法,它通过维护一个固定容量的令牌桶,每秒钟往桶里放入一定数...
    99+
    2023-09-09
    redis
  • 利用Redis实现分布式限流
    标题:利用Redis实现分布式限流正文:随着互联网的快速发展,网站和服务的并发访问量不断增加,为了保护后端系统的稳定性,限制并发访问量成为了一项重要的任务。在分布式系统中,为了保证多个服务实例之间的共享状态,我们可以使用Redis作为分布式...
    99+
    2023-11-07
    分布式 redis 限流
  • SpringBoot+Redis实现布隆过滤器的示例代码
    目录简述Redis 安装 Bloom Filter基本指令结合 SpingBoot方式一方式二简述 关于布隆过滤器的详细介绍,我在这里就不再赘述一遍了 我们首先知道:BloomFil...
    99+
    2024-04-02
  • java基于jedisLock—redis分布式锁实现示例代码
    分布式锁是啥?单机锁的概念:我们正常跑的单机项目(也就是在tomcat下跑一个项目不配置集群)想要在高并发的时候加锁很容易就可以搞定,java提供了很多的机制例如:synchronized、volatile、ReentrantLock等锁的...
    99+
    2023-05-30
    jedislock redis 分布式锁
  • Redis和Lua实现分布式限流器
    本篇文章为大家展示了Redis和Lua实现分布式限流器,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。原理计数器算法是指在一段窗口时间内允许通过的固定数量的请求, 比...
    99+
    2024-04-02
  • Go+Redis实现常见限流算法的示例代码
    目录固定窗口滑动窗口hash实现list实现漏桶算法令牌桶滑动日志总结限流是项目中经常需要使用到的一种工具,一般用于限制用户的请求的频率,也可以避免瞬间流量过大导致系统崩溃,或者稳定消息处理速率。并且有时候我们还需要使用...
    99+
    2023-04-02
    Go Redis实现限流算法 Go Redis限流算法 Go 限流算法
  • redis分布式锁的实现示例
    小编给大家分享一下redis分布式锁的实现示例,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!Redissonredisson和下...
    99+
    2024-04-02
  • 四种分布式限流算法和代码实现
    带着问题走近限流为什么要限流呢?就像我上面说的,流量多,的确是一件好事,但是如果过载,把系统打挂了,那大家都要吃席了。没逝吧所以,在各种大促活动之前,要对系统进行压测,评估整个系统的峰值QPS,要做一些限流的设置,超过一定阈值,就拒绝处理或...
    99+
    2023-08-15
  • SpringBoot利用限速器RateLimiter实现单机限流的示例代码
    目录一. 概述二. SpringBootDemo2.1 依赖2.2 application.yml2.3 启动类2.4 定义一个限流注解 RateLimiter.java2.5 代理...
    99+
    2024-04-02
  • 如何在Redis中实现分布式限流
    在Redis中实现分布式限流可以通过使用Redis的计数器和过期时间来实现。以下是一种基于计数器和过期时间的简单实现方式: 使用R...
    99+
    2024-04-09
    Redis
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作