`
jin8000608172
  • 浏览: 140064 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

互联网高并发限流方案分析

阅读更多
单进程限流:
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);
	}
}


分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics