服务调用的QPS控制(Java)

  • QPS控制器实现类代码:
/**
 * @desc QPS控制器
 * @author visy.wang
 * @date 2020/9/29 10:13
 */
public class QPSCtrl {
	/**
	 * QPS值
	 */
	private int qps;
	/**
	 * 一个周期内的调用次数
	 */
	private int count;
	/**
	 * 一个周期的起始时间(时间戳)
	 */
	private long startTime;
	/**
	 * 周期长度(毫秒)
	 */
	private static final int PERIOD = 1000;

	/**
	 * 通过指定QPS创建控制器(内部使用)
	 * @param qps QPS值
	 */
	private QPSCtrl(int qps){
		this.qps = qps;
	}

	/**
	 * 创建QPSCtrl实例
	 * @param qps QPS值
	 * @return Object
	 */
	public static QPSCtrl create(int qps){
		return new QPSCtrl(qps);
	}

	/**
	 * 开始下一个周期
	 * @param startTime 起始时间戳
	 */
	private void next(long startTime){
		this.count = 1;
		this.startTime = startTime;
		//测试用,可删除
		System.out.println(" ");
	}

	/**
	 * qps控制(线程阻塞,休眠实现)
	 * 适用于多线程环境
	 */
	public synchronized void ctrl(){
		long now = System.currentTimeMillis();
		long duration = now - this.startTime;
		if(duration < PERIOD){
			if(this.count < this.qps){
				this.count ++;
			}else{
				try{
					Thread.sleep(PERIOD - duration);
				}catch (InterruptedException e){
					e.printStackTrace();
				}
				this.next(System.currentTimeMillis());
			}
		}else{
			this.next(now);
		}
	}
}

*使用(测试):

/**
 * @desc QPS控制器测试
 * @author visy.wang
 * @date 2020/9/29 10:25
 */
public class TestQPS {
	/**
	 * 在多线程环境下,请确保拿到的QPSCtrl对象是同一个,
	 * 建议在此处初始化,当然也可用别的方式创建(但需保证是同一个)
	 * 不同的QPSCtrl对象是彼此独立的
	 */
	private static QPSCtrl qpsCtrl1 = QPSCtrl.create(2);
	private static QPSCtrl qpsCtrl2 = QPSCtrl.create(3);
	
	public void test1(int i){
		//调用ctrl()来实现QPS的控制
		qpsCtrl1.ctrl();
		System.out.print(i+"(I) ");
	}

	public void test2(int i){
		//超出QPS值会阻塞在这里,直到下一个周期
		qpsCtrl2.ctrl();
		System.out.print(i+"(II) ");
	}

	public static void main(String[] args) {

		TestQPS testQPS = new TestQPS();

		new Thread(()->{
			for(int i=1; i<=6; i++){
				testQPS.test1(i);
			}
		}).start();

		new Thread(()->{
			for(int i=7; i<=12; i++){
				testQPS.test1(i);
			}
		}).start();

		new Thread(()->{
			for(int i=13; i<=18; i++){
				testQPS.test2(i);
			}
		}).start();
	}
}
  • 输出:
 
7(I) 8(I)  
13(II) 14(II) 15(II)  
9(I) 10(I)  
16(II) 17(II) 18(II)  
11(I) 1(I)  
12(I) 2(I)  
3(I) 4(I)  
5(I) 6(I) 

你可能感兴趣的:(服务调用的QPS控制(Java))