互联网高并发限流方案分析
程序员文章站
2022-06-11 09:26:52
...
单进程限流:
1、令牌桶算法
令牌桶算法是以一定的速率往桶内放入令牌,业务服务从桶内获取到令牌才能进行业务操作,获取不到令牌,则拒绝服务。
2、漏桶算法
漏桶算法是固定的速率从桶内拿令牌,不固定的速率往桶内放令牌,当桶满了,则拒绝服务。
实现方式:
分布式限流:
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); } }
上一篇: 微信被删除好友挽回应该怎么做?
下一篇: play 并发问题