1,RateLimiter 是 guava 提供的基于令牌桶算法的实现类, 可以非常简单的完成限流特技, 并且根据系统的实际情况来调整生成 token 的速率.
通常可应用于抢购限流防止冲垮系统; 限制某接口, 服务单位时间内的访问量, 譬如一些第三方服务会对用户访问量进行限制; 限制网速, 单位时间内只允许上传下载多少字节等.
guava 的 maven 依赖
- <dependency>
- <groupId>com.google.guava</groupId>
- <artifactId>guava</artifactId>
- <version>25.1-jre</version>
- </dependency>
2, 令牌桶的原理, 有一个独立线程一直以一个固定的速率往桶中存放令牌
客户端去桶中获取令牌, 获取到令牌, 就可以访问, 获取不到, 说明请求过多, 需要服务降级.
- 3,
- package com.aiyuesheng.controller;
- import java.util.concurrent.TimeUnit;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.beans.factory.annotation.Value;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.Web.bind.annotation.RestController;
- import com.aiyuesheng.hystrix.OrderHystrixCommand;
- import com.aiyuesheng.service.OrderService;
- import com.aiyuesheng.utils.LimitService;
- import com.alibaba.fastjson.JSONObject;
- import com.google.common.util.concurrent.RateLimiter;
- @RestController
- public class Index {// 令牌桶: 1.0 表示 每秒中生成 1 个令牌存放在桶中
- RateLimiter rateLimiter = RateLimiter.create(1.0);
- @Autowired
- private OrderService orderService;
- // 令牌桶限流
- @RequestMapping("/searchCustomerInfoByRateLimiter")
- public Object searchCustomerInfoByRateLimiter() {
- // 1. 限流判断
- // 如果在 0.5 秒内 没有获取不到令牌的话, 则会一直等待
- System.out.println("生成令牌等待时间:" + rateLimiter.acquire());
- boolean acquire = rateLimiter.tryAcquire(500, TimeUnit.MILLISECONDS); // 每次发送请求, 愿意等待 0.5 秒, 如果设为 1 秒, 每次都能查询成功, 因为没秒中都会放入一个令牌到桶中
- if (!acquire) {
- System.out.println("稍后再试!");
- return "稍后再试!";
- }
- // 2. 如果没有达到限流的要求, 直接调用接口查询
- System.out.println(orderService.searchCustomerInfo());
- return orderService.searchCustomerInfo();
- }
- }
来源: http://www.bubuko.com/infodetail-3135287.html