利特尔规则
利特尔规则派生于排队论,用以下数学公式示意:
L = λW
L 系统中存在的平均请求数目。
λ 请求有用到达速率。例如:5/s 示意每秒有5个请求到达系统。
W 请求在系统中的平均守候执行时间。
排队论:研究服务系统中排队征象随机纪律的学科,探讨排队有关的数目指标的概率纪律性。
场景
我们先假设一个店肆员工调整场景。
条件
-
每个客户一次只买一只炸鸡;
-
每位员工制作一个炸鸡需要1分钟。
-
客户买炸鸡时守候时间越短,体验越好。
若是你是一家炸鸡店老板,今年受疫情影响需要对店里的员工举行调整,你会若何处置?
这个问题本质就是员工利用率与客户体验之间的权衡。
-
为了让客户保持极佳体验,需要保持员工数目或增添员工;
-
为制止资源虚耗,控制人力成本,需要淘汰空闲员工。
假设店里现在有3名员工。你若何举行员工调整决议。我们剖析以下几种情形。
当 平均客流量 = 3人/分钟 客户守候时间稍短,体验优越,而且员工事情都是饱和。此时不需要调整。
当 平均客流量 < 3人/分钟 客户守候时间稍短,体验优越,然则始终有一个员工在打酱油,此时可以思量减裁一人。
当 平均客流量 > 3人/分钟 客户5,6,7守候时间延伸体验稍差,此时可以凭据现实情况增添员工。
平均每分钟客流量 ≈ 员工数 为最佳。
线程池
实在线程池处置也算是一个排队模子。简化Java线程池处置模子如下:
线程池义务执行大致阶段:提交 --> 入行列或直接执行 ---> 现实执行
-
义务提交频率:每秒义务提交数;
-
义务行列守候平均耗时:义务行列守候总耗时除以现实执行数;
-
义务现实执行平均耗时:义务现实运行总耗时除以现实执行数;
-
义务执行平均耗时:义务行列守候平均耗时加义务现实执行平均耗时;
我们可以凭据以下指标来评估调整线程池参数
线程池中平均义务数 = 义务提交频率 * 义务执行平均耗时
线程守候耗时与响应时间比率 = 义务行列守候总耗时 / (义务行列守候总耗时 + 义务现实执行总耗时)
当 线程守候耗时与响应时间比率 过高,说明义务排队较多,评估当前线程池巨细是否合理,连系系统负载举行响应调整。
当 线程池中平均义务数 < 现在线程池巨细 应适当削减线程数目。
当 系统平均处置义务数 > 现在线程池巨细 在这种情况下,先评估当前系统是否有能力支持更大的线程数目(如CPU数,内存等),然后再举行调整。
代码片断
@Slf4j
public class MonitoredThreadPoolExecutor extends ThreadPoolExecutor {
//义务提交乐成时间
private final ConcurrentHashMap<Runnable, Long> timeOfRequest = new ConcurrentHashMap<>();
//义务现实最先执行时间
private final ThreadLocal<Long> startTime = new ThreadLocal<>();
//上一个义务提交乐成时间
private long lastArrivalTime;
// 义务现实执行总数
private final AtomicInteger numberOfRequestsRetired = new AtomicInteger();
// 义务提交总数
private final AtomicInteger numberOfRequests = new AtomicInteger();
// 义务现实执行总耗时
private final AtomicLong totalServiceTime = new AtomicLong();
// 义务在行列守候总耗
private final AtomicLong totalPoolTime = new AtomicLong();
// 新义务提交总耗时
private final AtomicLong aggregateInterRequestArrivalTime = new AtomicLong();
public MonitoredThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit,
BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) {
super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler);
}
@Override
protected void beforeExecute(Thread worker, Runnable task) {
super.beforeExecute(worker, task);
startTime.set(System.nanoTime());
}
@Override
protected void afterExecute(Runnable task, Throwable t) {
try {
long start = startTime.get();
totalServiceTime.addAndGet(System.nanoTime() - start);
totalPoolTime.addAndGet(start - timeOfRequest.remove(task));
numberOfRequestsRetired.incrementAndGet();
} finally {
if (null != t) {
log.error(AppSystem.ERROR_LOG_PREFIX + "线程池处置异常:", Throwables.getRootCause(t));
}
super.afterExecute(task, t);
}
}
@Override
public void execute(Runnable task) {
long now = System.nanoTime();
numberOfRequests.incrementAndGet();
synchronized (this) {
if (lastArrivalTime != 0L) {
aggregateInterRequestArrivalTime.addAndGet(now - lastArrivalTime);
}
lastArrivalTime = now;
timeOfRequest.put(task, now);
}
super.execute(task);
}
}
测试
两组迭代请求,一次提交10个义务,线程数为1
两组迭代请求,一次提交10个义务,线程数为10
两组迭代请求,一次提交10个义务,线程数为50
上面测试对照片面。现实应凭据系统历久平均指标举行调整。
总结
利特尔规则应用场景许多。迎接人人留言交流!
,Sunbet www.sunbet.xyz是Sunbet指定的Sunbet官网,Sunbet提供Sunbet(Sunbet)、Sunbet、申博代理合作等业务。
网友评论
最新评论