单进程限流:
1、令牌桶算法
令牌桶算法是以一定的速率往桶内放入令牌,业务服务从桶内获取到令牌才能进行业务操作,获取不到令牌,则拒绝服务。
2、漏桶算法
漏桶算法是固定的速率从桶内拿令牌,不固定的速率往桶内放令牌,当桶满了,则拒绝服务。
实现方式:
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>25.1-jre</version>
</dependency>
import java.util.Random;
import java.util.concurrent.TimeUnit;
import org.redisson.Redisson;
import org.redisson.api.RRateLimiter;
import org.redisson.api.RateIntervalUnit;
import org.redisson.api.RateType;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.google.common.util.concurrent.RateLimiter;
import com.gupao.jwt.JwtTokenUtils;
import com.gupao.jwt.PassToken;
import com.gupao.model.User;
import com.gupao.redis.RedisCacheManager;
import com.gupao.redis.RedissionManager;
import com.gupao.service.UserService;
@Controller
public class UserController extends BaseController {
@Autowired
RedisCacheManager redisCacheManager;
@Autowired
RedissionManager redissionManager;
@Autowired
RedissonClient redissonClient;
@Autowired
UserService userService;
//令牌桶算法 1:每秒新增的令牌数
RateLimiter tokenLimiter=RateLimiter.create(1);
//漏桶算法 1:每秒新增的令牌数 500:从冷启动速率到平均速率的间隔时间,也可以叫作预热时间
RateLimiter leakyLimiter=RateLimiter.create(1, 500, TimeUnit.MILLISECONDS);
/**
* 令牌桶限流方案一:获取不到令牌,直接走降级
* @return
* @throws Exception
*/
@RequestMapping("/tokenBucket")
@ResponseBody
// @UserLoginToken
@PassToken
public String tokenBucket() throws Exception {
long start=System.currentTimeMillis();
try {
// double limiter=rateLimiter.acquire();
// System.out.println("获取token时间:"+limiter);
// boolean flag=rateLimiter.tryAcquire();
//如果500毫秒内获取不到令牌,直接走降级
boolean flag=tokenLimiter.tryAcquire(500, TimeUnit.MILLISECONDS);
if(!flag) {
System.out.println("服务器太忙了!");
return "服务器太忙了!";
}
Random random=new Random();
Integer id=random.nextInt(10000);
User user=new User(id, "admin"+id, "admin"+id);
boolean result=userService.addUser(user);
if(result) {
System.out.println("新增用户成功:"+user.toString());
return user.toString();
}else {
System.out.println("新增用户失败");
return "新增用户失败";
}
} catch (Exception e) {
System.out.println("异常"+e);
return "500";
}finally {
long end=System.currentTimeMillis();
System.out.println("耗时:"+(end-start));
}
}
/**
* 令牌桶限流方案二:如果获取不到令牌,就一直等待
* @return
* @throws Exception
*/
@RequestMapping("/tokenBucket1")
@ResponseBody
// @UserLoginToken
@PassToken
public String tokenBucket1() throws Exception {
long start=System.currentTimeMillis();
try {
//如果获取不到令牌 就一直等待
double limiter=tokenLimiter.acquire();
System.out.println("获取token时间:"+limiter);
// boolean flag=rateLimiter.tryAcquire();
// if(!flag) {
// System.out.println("服务器太忙了!");
// return "服务器太忙了!";
// }
Random random=new Random();
Integer id=random.nextInt(10000);
User user=new User(id, "admin"+id, "admin"+id);
boolean result=userService.addUser(user);
if(result) {
System.out.println("新增用户成功:"+user.toString());
return user.toString();
}else {
System.out.println("新增用户失败");
return "新增用户失败";
}
} catch (Exception e) {
System.out.println("异常"+e);
return "500";
}finally {
long end=System.currentTimeMillis();
System.out.println("耗时:"+(end-start));
}
}
/**
* 漏桶限流方案一:如果获取不到令牌,直接走降级
* @return
*/
@RequestMapping("/leakyBucket1")
@ResponseBody
// @UserLoginToken
@PassToken
public String leakyBucket1() {
long start=System.currentTimeMillis();
try {
// double limiter=rateLimiter.acquire();
// System.out.println("获取token时间:"+limiter);
// boolean flag=rateLimiter.tryAcquire();
boolean flag=leakyLimiter.tryAcquire(500, TimeUnit.MILLISECONDS);
if(!flag) {
System.out.println("服务器太忙了!");
return "服务器太忙了!";
}
Random random=new Random();
Integer id=random.nextInt(10000);
User user=new User(id, "admin"+id, "admin"+id);
boolean result=userService.addUser(user);
if(result) {
System.out.println("新增用户成功:"+user.toString());
return user.toString();
}else {
System.out.println("新增用户失败");
return "新增用户失败";
}
} catch (Exception e) {
System.out.println("异常"+e);
return "500";
}finally {
long end=System.currentTimeMillis();
System.out.println("耗时:"+(end-start));
}
}
/**
* 漏桶限流方案二:如果获取不到令牌,就一直等待
* @return
*/
@RequestMapping("/leakyBucket")
@ResponseBody
// @UserLoginToken
@PassToken
public String leakyBucket() {
long start=System.currentTimeMillis();
try {
double limiter=leakyLimiter.acquire();
System.out.println("获取token时间:"+limiter);
// boolean flag=rateLimiter.tryAcquire();
// if(!flag) {
// System.out.println("服务器太忙了!");
// return "服务器太忙了!";
// }
Random random=new Random();
Integer id=random.nextInt(10000);
User user=new User(id, "admin"+id, "admin"+id);
boolean result=userService.addUser(user);
if(result) {
System.out.println("新增用户成功:"+user.toString());
return user.toString();
}else {
System.out.println("新增用户失败");
return "新增用户失败";
}
} catch (Exception e) {
System.out.println("异常"+e);
return "500";
}finally {
long end=System.currentTimeMillis();
System.out.println("耗时:"+(end-start));
}
}
/**
* 分布式限流方案二:如果获取不到令牌,就一直等待
* @return
*/
@RequestMapping("/redissionLimit")
@ResponseBody
// @UserLoginToken
@PassToken
public String redissionLimit() {
long start=System.currentTimeMillis();
try {
RRateLimiter redisLimiter=redissionManager.getRRateLimiter("userLimiter");
redisLimiter.trySetRate(RateType.PER_CLIENT, 1, 1, RateIntervalUnit.SECONDS);
redisLimiter.acquire();
// System.out.println("获取token时间:"+limiter);
// boolean flag=rateLimiter.tryAcquire();
// if(!flag) {
// System.out.println("服务器太忙了!");
// return "服务器太忙了!";
// }
Random random=new Random();
Integer id=random.nextInt(10000);
User user=new User(id, "admin"+id, "admin"+id);
boolean result=userService.addUser(user);
if(result) {
System.out.println("新增用户成功:"+user.toString());
return user.toString();
}else {
System.out.println("新增用户失败");
return "新增用户失败";
}
} catch (Exception e) {
e.printStackTrace();
System.out.println("异常"+e);
return "500";
}finally {
long end=System.currentTimeMillis();
System.out.println("耗时:"+(end-start));
}
}
/**
* 分布式限流方案一:如果获取不到令牌,直接走降级
* @return
*/
@RequestMapping("/redissionLimit1")
@ResponseBody
// @UserLoginToken
@PassToken
public String redissionLimit1() {
long start=System.currentTimeMillis();
try {
// Config config = new Config();
// config.useSingleServer().setAddress("redis://192.168.126.11:6379");
// RedissonClient redissionLimiter = Redisson.create(config);
// RRateLimiter redisLimiter=redissionLimiter.getRateLimiter("test");
// redisLimiter.trySetRate(RateType.PER_CLIENT, 1, 1, RateIntervalUnit.SECONDS);
RRateLimiter redisLimiter=redissionManager.getRRateLimiter("userLimiter");
redisLimiter.trySetRate(RateType.PER_CLIENT, 1, 1, RateIntervalUnit.SECONDS);
boolean flag=redisLimiter.tryAcquire(500, TimeUnit.MILLISECONDS);
if(!flag) {
System.out.println("服务器太忙了!");
return "服务器太忙了!";
}
Random random=new Random();
Integer id=random.nextInt(10000);
User user=new User(id, "admin"+id, "admin"+id);
boolean result=userService.addUser(user);
if(result) {
System.out.println("新增用户成功:"+user.toString());
return user.toString();
}else {
System.out.println("新增用户失败");
return "新增用户失败";
}
} catch (Exception e) {
e.printStackTrace();
System.out.println("异常"+e);
return "500";
}finally {
long end=System.currentTimeMillis();
System.out.println("耗时:"+(end-start));
}
}
分布式限流:
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.10.5</version>
</dependency>
<bean id="fstCodec" class="org.redisson.codec.FstCodec" />
<redisson:client id="redissonClient" threads="0"
netty-threads="0" codec-ref="fstCodec" >
<redisson:single-server
idle-connection-timeout="10000" ping-timeout="1000" connect-timeout="10000"
timeout="3000" retry-attempts="3" retry-interval="1500"
subscriptions-per-connection="5" client-name="none"
address="redis://192.168.126.11:6379"
subscription-connection-minimum-idle-size="1"
subscription-connection-pool-size="50" connection-minimum-idle-size="10"
connection-pool-size="64" database="0" />
</redisson:client>
import org.redisson.api.RRateLimiter;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class RedissionManager {
@Autowired
private RedissonClient redissonClient;
// public void setRedissonClient(RedissonClient redissonClient) {
// this.redissonClient = redissonClient;
// }
public RRateLimiter getRRateLimiter(String key) {
return redissonClient.getRateLimiter(key);
}
}
分享到:
相关推荐
**面试篇**包含了高并发场景下的优化策略和常见问题,比如优化加锁方式可能导致的死锁,缓存穿透、击穿和雪崩的现象及其解决方案,以及Java中synchronized和Lock的区别和使用场景。 **系统架构篇**涉及高并发下的...
### JavaWeb并发编程与高并发解决方案 #### 一、并发编程概述 在现代软件开发中,尤其是对于基于JavaWeb的应用程序来说,面对大量的用户请求和数据处理任务时,高效的并发处理能力至关重要。并发编程旨在利用多...
在IT行业中,高并发分布式解决方案是构建大规模、高性能系统的关键技术。随着互联网业务的飞速发展,处理亿级甚至更高流量的网站已经成为常态,而如何有效地应对这些流量,确保系统的稳定性和可扩展性,就成为了IT...
在探讨Java并发编程与高并发解决方案的过程中,我们会涉及到一系列核心概念和相关技术。本文将基于文档《Java并发编程与高并发解决方案-学习笔记***.pdf》中提供的内容,来详细阐述并发编程和高并发的基本概念、CPU...
【互联网高并发架构设计】 高并发架构设计是解决大规模用户同时访问系统时,确保系统稳定、高效运行的关键。在互联网领域,特别是在电商、社交等业务中,秒杀、红包领取等场景经常出现高并发,因此设计合理的架构至...
### Java秒杀系统方案优化与高性能高并发实战 在当今互联网时代,随着用户数量的急剧增加,对于服务器的压力也越来越大,特别是在一些特定的场景下,比如抢购、秒杀活动等,系统的高并发处理能力成为了衡量一个应用...
在互联网行业中,高并发是衡量系统性能的关键指标,特别是在大型互联网平台的设计中。高并发意味着系统需要具备同时处理大量请求的能力,确保用户在高峰期也能获得流畅的体验。本讲主要探讨了高并发业务架构设计的...
在亿级流量的互联网服务中,分布式限流是保障系统稳定性和高可用性的重要手段。随着用户数量的急剧增长,单机的处理能力已经无法满足需求,因此分布式系统成为主流。在这种背景下,如何有效地实现分布式限流就显得至...
【高并发解决方案】 高并发是互联网系统设计的关键因素,它涉及到如何处理大量同时发生的请求,以确保系统的稳定性和效率。高并发场景下,常见的性能指标包括响应时间、吞吐量、每秒查询率(QPS)和并发用户数。...
在分析给定文件内容的基础上,以下是对"高并发高可用的分布式电商平台架构研究"这一主题的知识点的详细阐述。 分布式电商平台架构是为了应对传统软件架构在面对大规模并发请求时,性能下降、可拓展性不足等问题而...
### Java秒杀系统方案优化——高性能与高并发实践 #### 一、引言 随着互联网技术的迅猛发展,用户数量的急剧增长对系统的稳定性和性能提出了更高的要求。特别是在秒杀场景下,面对短时间内大量用户的并发访问,...
计数器限流算法是比较常用的一种限流方案,也是最为粗暴直接的,主要用来限制总并发数,比如数据库连接池大小、线程池大小、接口访问并发数等都是使用计数器算法。 三、限流代码实践 下面,我们将详细介绍 ...
在现代互联网环境中,高并发Web服务器的设计与优化是至关重要的技术课题。面对大规模用户访问,如何构建稳定、高效且能够处理海量请求的Web服务器是每个技术团队都需要关注的问题。本资料"高并发WEB服务器卓有成效...
2. **高并发解决方案**: - **系统缓存**:使用Redis作为分布式缓存,存储热点数据,如商品详情、用户信息等,减少对数据库的访问压力,提高响应速度。 - **降级策略**:在系统负载过高时,可以采取降级策略,例如...
在互联网行业中,构建高可用和高并发的业务架构是一项至关重要的任务。这涉及到对系统设计原则的深刻理解和实践经验。海恩法则和墨菲定律在系统设计中起着指导作用,提醒我们在面对潜在问题时,必须保持警惕并深入...
构建高可用性互联网直播视频推流系统是一项复杂的工程技术任务,它要求工程师...通过上述技术的综合应用和优化,可以建设出一个既能够应对高并发需求,又能在各种网络环境下保持稳定可靠传输的互联网直播视频推流系统。
7. **互联网高并发解决方案**:面对大量用户请求,需要掌握如何处理高并发,如使用异步非阻塞IO(NIO、AIO)、消息队列(如RabbitMQ、Kafka)进行流量削峰填谷,以及数据库分库分表等策略。 8. **互联网安全架构**...