文档章节

[Java]计算单机TPS、并对任务限流

健康的程序员
 健康的程序员
发布于 2015/12/29 19:50
字数 935
阅读 94
收藏 1

类结构

说明:

SpeedControlConstant 定义的一些与限流相关的常量
SpeedControlHelper 单机TPS限流类,提供当前任务TPS的计算功能
TaskDO 任务DO,定义了任务类型、任务的执行逻辑。实现了Runnable接口
TaskStateDO 任务状态DO,定义了任务的TPS、执行次数、执行时间等
TaskStateSingleton 统计所有任务状态的单例类
TpsTest 测试类


直接上代码

package com.taobao.tps;

/**
 * 限流常量类
 * 
 * @author <a href="mailto:zq_dong@sina.cn">zhangqi.dzq</a>
 * @version 1.0
 * @since 2015年12月29日
 */
public class SpeedControlConstant {
	// 单机tps设置50
	public static int serverTps = 50;
}
package com.taobao.tps;

/**
 * 单机TPS限流功能类
 * 
 * @author <a href="mailto:zq_dong@sina.cn">zhangqi.dzq</a>
 * @version 1.0
 * @since 2015年12月29日
 */
public class SpeedControlHelper {

	/**
	 * 判断是否被限流
	 * 
	 * @param taskType
	 * @return false限流
	 */
	public static boolean speedControl(String taskType) {
		int tpsThreshod = SpeedControlConstant.serverTps;// tps阀值
		int currentTps = currentTps(taskType);// 当前tps
		if (tpsThreshod <= currentTps) {
			return false;
		}
		return true;
	}

	/**
	 * 获取当前任务类型tps
	 * 
	 * @param taskType
	 * @return
	 */
	public static int currentTps(String taskType) {
		TaskStateSingleton taskStateSingleton = TaskStateSingleton.getInstance();
		TaskStateDO currentTask = taskStateSingleton.getTaskStateDO(taskType);
		if (currentTask == null) {
			// 这里有并发问题,但是统计tps不需要特别精准。添加了并发控制反而会影响性能
			currentTask = new TaskStateDO();
			taskStateSingleton.putTaskStateDO(taskType, currentTask);
		}
		return currentTask.calcuTps();
	}

	/**
	 * 设置当前任务类型执行时间
	 * 
	 * @param taskType
	 * @param time
	 */
	public static void setExecTime(String taskType, long time) {
		TaskStateSingleton taskStateSingleton = TaskStateSingleton.getInstance();
		TaskStateDO currentTask = taskStateSingleton.getTaskStateDO(taskType);
		if (currentTask == null) {
			// logger..
			return;
		}
		currentTask.state(time);
	}
}
package com.taobao.tps;

/**
 * 任务
 * 
 * @author <a href="mailto:zq_dong@sina.cn">zhangqi.dzq</a>
 * @version 1.0
 * @since 2015年12月29日
 */
public class TaskDO implements Runnable {
	private String taskType;

	public TaskDO(String taskType) {
		this.taskType = taskType;
	}

	public String getTaskType() {
		return taskType;
	}

	public void run() {
		try {
			long startTime = System.currentTimeMillis();
			Thread.sleep(15);
			long endTime = System.currentTimeMillis();
			SpeedControlHelper.setExecTime(taskType, endTime - startTime);
		} catch (InterruptedException e) {
			// logger..
		}
	}

}
package com.taobao.tps;

import java.util.concurrent.atomic.AtomicInteger;

/**
 * 任务状态
 * 
 * @author <a href="mailto:zq_dong@sina.cn">zhangqi.dzq</a>
 * @version 1.0
 * @since 2015年12月29日
 */
public class TaskStateDO {
	/**
	 * 任务类型
	 */
	private String taskType;

	/**
	 * 一个统计时间区间内的总执行次数
	 */
	private int execCount;

	/**
	 * 一个统计时间区间内的总执行耗时
	 */
	private long totalTime;

	/**
	 * 一个统计时间区间内的平均执行耗时
	 */
	private int averageTime;

	/**
	 * 当前1秒内执行的次数
	 */
	private AtomicInteger secondExecCount = new AtomicInteger(0);

	/**
	 * 当前秒
	 */
	private long currentSecond = 0;

	public TaskStateDO() {
		reset();
	}

	/**
	 * 获取taskType
	 * 
	 * @return taskType
	 */
	public String getTaskType() {
		return taskType;
	}

	/**
	 * 设置taskType
	 * 
	 * @param taskType 要设置的taskType
	 */
	public void setTaskType(String taskType) {
		this.taskType = taskType;
	}

	/**
	 * 获取totalTime
	 * 
	 * @return totalTime
	 */
	public long getTotalTime() {
		return totalTime;
	}

	/**
	 * 获取execCount
	 * 
	 * @return execCount
	 */
	public int getExecCount() {
		return execCount;
	}

	/**
	 * 获取averageTime
	 * 
	 * @return averageTime
	 */
	public int getAverageTime() {
		return averageTime;
	}

	/**
	 * 统计任务的秒级执行次数
	 * 
	 * @return
	 */
	public int calcuTps() {
		if (currentSecond == System.currentTimeMillis() / 1000) {
			return secondExecCount.incrementAndGet();// 1s的执行次数
		} else {
			currentSecond = System.currentTimeMillis() / 1000;
			secondExecCount.set(1);
			return 1;
		}
	}

	/**
	 * 统计任务执行时间
	 * 
	 * @param time
	 */
	public void state(long time) {
		try {
			execCount++;
			totalTime += time;
			averageTime = (int) (totalTime / execCount);
		} catch (Exception e) {
			reset();
		}
	}

	/**
	 * 重置方法,没有设置为零,防止除法抛异常
	 */
	public void reset() {
		execCount = 1;
		totalTime = 100;
	}

}
package com.taobao.tps;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * 统计全量任务单例
 * 
 * @author <a href="mailto:zq_dong@sina.cn">zhangqi.dzq</a>
 * @version 1.0
 * @since 2015年12月29日
 */
public class TaskStateSingleton {
	private Map<String, TaskStateDO> taskStateMap = new HashMap<String, TaskStateDO>();

	private ReadWriteLock lock = new ReentrantReadWriteLock();

	private Lock read = lock.readLock();

	private Lock write = lock.writeLock();

	private TaskStateSingleton() {
	}

	// 获取实例
	public static TaskStateSingleton getInstance() {
		return SingletonHolder.taskStateSingleton;
	}

	private static class SingletonHolder {
		private static final TaskStateSingleton taskStateSingleton = new TaskStateSingleton();
	}

	public Map<String, TaskStateDO> getTaskStateMap() {
		try {
			read.lock();
			return taskStateMap;
		} finally {
			read.unlock();
		}
	}

	/**
	 * 新增一个任务统计信息
	 */
	public void putTaskStateDO(String taskType, TaskStateDO taskStateDO) {
		try {
			write.lock();
			taskStateMap.put(taskType, taskStateDO);
		} finally {
			write.unlock();
		}
	}

	/**
	 * 查询一个任务统计信息
	 */
	public TaskStateDO getTaskStateDO(String taskType) {
		try {
			read.lock();
			return taskStateMap.get(taskType);
		} finally {
			read.unlock();
		}
	}

}
package com.taobao.tps;

import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * 测试类
 * 
 * @author <a href="mailto:zq_dong@sina.cn">zhangqi.dzq</a>
 * @version 1.0
 * @since 2015年12月29日
 */
public class TpsTest {
	public static ThreadPoolExecutor executer = new ThreadPoolExecutor(4, 4, 4, TimeUnit.SECONDS,
			new LinkedBlockingQueue<Runnable>(500));

	public static void main(String[] args) throws Exception {
		while (true) {
			TaskDO task = new TaskDO("calcu_item_value");
			if (!SpeedControlHelper.speedControl(task.getTaskType())) {
				print("被限流..");
				continue;
			}
			executer.submit(task);
			print("添加任务成功");
			Thread.sleep(10);
		}
	}

	public static void print(Object obj) {
		System.out.print(obj.toString());
	}
}


建议用服务器测试代码,工作PC测试可以比较卡。。



© 著作权归作者所有

共有 人打赏支持
上一篇: Btrace使用
健康的程序员
粉丝 7
博文 167
码字总数 43098
作品 0
杭州
程序员
私信 提问
Java并发:分布式应用限流 Redis + Lua 实践

任何限流都不是漫无目的的,也不是一个开关就可以解决的问题,常用的限流算法有:令牌桶,漏桶。在之前的文章中,也讲到过,但是那是基于单机场景来写。 之前文章:接口限流算法:漏桶算法&...

关注公众号_搜云库_每天更新
08/17
0
0
轻量级数据库中间件利器Sharding-JDBC深度解析

本文根据DBAplus社群第114期线上分享整理而成。 主题简介: 1、关系型数据库中间件核心功能介绍 2、Sharding-JDBC架构及内核解析 3、Sharding-JDBC未来展望 关系型数据库凭借灵活查询的SQL和...

张亮
2017/07/28
0
0
下单接口调优实战,性能提高10倍

概述 最近公司的下单接口有些慢,老板担心无法支撑双11,想让我优化一把,但是前提是不允许大改,因为下单接口太复杂了,如果改动太大,怕有风险。另外开发成本和测试成本也非常大。对于这种...

Sam哥哥聊技术
10/19
0
7
JavaAgent-SandBox

1.前言 之前初步学习了javaAgent,并做了一份总结《JavaAgent学习笔记》。然后在看到《JVM-Sandbox 基于JVM的非侵入式运行期AOP解决方案》之后,接触到了集团的sandBox。并尝试使用这种有真正...

何度
05/09
0
0
RocketMQ与Kafka对比

RocketMQ与Kafka对比(18项差异) 淘宝内部的交易系统使用了淘宝自主研发的Notify消息中间件,使用Mysql作为消息存储媒介,可完全水平扩容,为了进一步降低成本,我们认为存储部分可以进一步...

莫问viva
2015/05/08
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Mybatis 中$与#的区别,预防SQL注入

一直没注意Mybatis 中$与#的区别,当然也是更习惯使用#,没想到避免了SQL注入,但是由于要处理项目中安全渗透的问题,不可避免的又遇到了这个问题,特此记录一下。 首先是共同点: 在mybatis...

大雁南飞了
10分钟前
0
0
Cydia的基石:MobileSubstrate

在MAC与IOS平台上,动态库的后缀一般是dylid,而加载这些动态库的程序叫做dynamic linker(dyld)。这个程序有很多的环境变量来设置程序的一些行为,最为常用的一个环境变量叫做"DYLD_INSERT_...

HeroHY
13分钟前
0
0
Spring Clould负载均衡重要组件:Ribbon中重要类的用法

Ribbon是Spring Cloud Netflix全家桶中负责负载均衡的组件,它是一组类库的集合。通过Ribbon,程序员能在不涉及到具体实现细节的基础上“透明”地用到负载均衡,而不必在项目里过多地编写实现...

Ala6
22分钟前
0
0
让 linux 删除能够进入回收站

可以参考这个贴子 https://blog.csdn.net/F8qG7f9YD02Pe/article/details/79543316 从那个git地址 把saferm.sh下载下来 把saferm.sh复制到 /usr/bin 目录下 在用~/目下 的.bashrc 下加一句这...

shzwork
31分钟前
0
0
Qt那些事0.0.9

关于QThread,无F*k说的。文档说的差不多,更多的是看到很多人提到Qt开发者之一的“你TM的做错了(You're doing it wrong...)”,这位大哥2010年写的博客,下面评论很多,但主要还是集中在2...

Ev4n
今天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部