Math 如何通过系统测量事件发生率
我需要测量软件系统消耗消息队列中消息的速率,并定期报告该速率 具体而言,消息来自消息队列系统,我需要(每秒)报告在多个滚动窗口内收到的消息数量,例如,最后一秒、最后5秒、最后30秒等Math 如何通过系统测量事件发生率,math,message-queue,rate,Math,Message Queue,Rate,我需要测量软件系统消耗消息队列中消息的速率,并定期报告该速率 具体而言,消息来自消息队列系统,我需要(每秒)报告在多个滚动窗口内收到的消息数量,例如,最后一秒、最后5秒、最后30秒等 虽然我相信我可以建立这个,但我不确定我会以最有效的方式进行!我也确信有库可以做到这一点(我使用的是JVM,所以我想到了ApacheCommonsMath),但我甚至不知道谷歌应该用什么词来表达!:-) 您可能可以将其实现为拦截器,因此搜索拦截器,并结合消息队列产品名称和语言名称。这就是我最后写的内容 package
虽然我相信我可以建立这个,但我不确定我会以最有效的方式进行!我也确信有库可以做到这一点(我使用的是JVM,所以我想到了ApacheCommonsMath),但我甚至不知道谷歌应该用什么词来表达!:-) 您可能可以将其实现为拦截器,因此搜索拦截器,并结合消息队列产品名称和语言名称。这就是我最后写的内容
package com.example;
import java.util.Arrays;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class BucketCounter {
private final Lock rollLock = new ReentrantLock();
private final int[] bucketSizes;
private final int[] buckets;
private final int[] intervals;
private final AtomicInteger incoming = new AtomicInteger(0);
public BucketCounter(int... bucketSizes) {
if (bucketSizes.length < 1) {
throw new IllegalArgumentException("Must specify at least one bucket size");
}
this.bucketSizes = bucketSizes;
this.buckets = new int[bucketSizes.length];
Arrays.sort(bucketSizes);
if (bucketSizes[0] < 1) {
throw new IllegalArgumentException("Cannot have a bucket of size < 1");
}
intervals = new int[bucketSizes[bucketSizes.length - 1]];
}
public int count(int n) {
return incoming.addAndGet(n);
}
public int[] roll() {
final int toAdd = incoming.getAndSet(0);
rollLock.lock();
try {
final int[] results = new int[buckets.length];
for (int i = 0, n = buckets.length; i < n; i++) {
results[i] = buckets[i] = buckets[i] - intervals[bucketSizes[i] - 1] + toAdd;
}
System.arraycopy(intervals, 0, intervals, 1, intervals.length - 1);
intervals[0] = toAdd;
return results;
} finally {
rollLock.unlock();
}
}
}
package.com.example;
导入java.util.array;
导入java.util.concurrent.AtomicInteger;
导入java.util.concurrent.locks.Lock;
导入java.util.concurrent.locks.ReentrantLock;
公营柜台{
private final Lock rollLock=新的ReentrantLock();
私人最终整数[]美元大小;
私人最终整数[]桶;
私有最终int[]间隔;
私有最终AtomicInteger传入=新的AtomicInteger(0);
公共BucketCounter(内部…bucketSizes){
如果(bucketSizes.length<1){
抛出新的IllegalArgumentException(“必须指定至少一个桶大小”);
}
此参数。bucketSizes=bucketSizes;
this.bucket=新整数[bucketSizes.length];
数组。排序(bucketSizes);
如果(bucketSizes[0]<1){
抛出新的IllegalArgumentException(“不能有大小小于1的桶”);
}
间隔=新整数[bucketSizes[bucketSizes.length-1];
}
公共整数计数(整数n){
返回传入的.addAndGet(n);
}
公共int[]roll(){
final int toAdd=传入的.getAndSet(0);
rollLock.lock();
试一试{
最终int[]结果=新int[bucket.length];
for(int i=0,n=bucket.length;i
通过传递不同的时间增量(例如1、5、30)对其进行初始化。然后安排后台线程在每个“时间段”调用roll()
。如果你每秒钟叫一次,那么你的桶是1、5和30秒。如果你每5秒调用一次,那么你的存储桶是5、25和150秒,以此类推。基本上,存储桶用“调用次数roll()
is called”)表示
roll()
还返回每个存储桶的当前计数数组。请注意,这些数字是原始计数,不是每个时间间隔的平均值。如果你想测量“比率”而不是“计数”,你需要自己做这个划分
最后,每次事件发生时,调用count()
。我已经用其中一些设置了一个系统,我在每条消息上调用count(1)
来计算传入的消息,在每条消息上调用count(message.size())
来计算传入的字节率,等等
希望有帮助。这是我基于指数平滑的解决方案。它不需要任何后台线程。您将为要跟踪的每个滚动窗口创建一个实例。对于每个相关事件,您将在每个实例上调用newEvent
public class WindowedEventRate {
private double normalizedRate; // event rate / window
private long windowSizeTicks;
private long lastEventTicks;
public WindowedEventRate(int aWindowSizeSeconds) {
windowSizeTicks = aWindowSizeSeconds * 1000L;
lastEventTicks = System.currentTimeMillis();
}
public double newEvent() {
long currentTicks = System.currentTimeMillis();
long period = currentTicks - lastEventTicks;
lastEventTicks = currentTicks;
double normalizedFrequency = (double) windowSizeTicks / (double) period;
double alpha = Math.min(1.0 / normalizedFrequency, 1.0);
normalizedRate = (alpha * normalizedFrequency) + ((1.0 - alpha) * normalizedRate);
return getRate();
}
public double getRate() {
return normalizedRate * 1000L / windowSizeTicks;
}
}
谢谢你的回复,但我不知道这是什么意思!我不知道什么是“拦截器”,除非你说的是AOP之类的东西。而且特定的消息队列产品和语言基本上是不相关的。@dty您也可以尝试“回调”。这方面有什么进展吗?我基本上也有相同的要求,最后我自己写了。我会在回复中发布。谢谢发布。我想避免背景线程的复杂性。我正在研究一种基于指数平滑的解决方案。等我写完了我会把它贴出来的。你能解释一下它是怎么工作的吗?特别是,你能解释一下历史事件是如何从结果中去除的吗?我可以试试。我们希望对成员变量normalizedRate执行指数平滑。每次我们得到一个新事件时,我们更新为:normalizedRate(t)=(normalizedFrequency*alpha)+(normalizedRate*(1-alpha))。请注意,我的实现不能很好地处理长时间缺席的事件,也就是说,它只在观察到新事件时更新normalizedRate,因此,当预期的事件速率至少为每个窗口周期1时,它将工作得最好。我在考虑如何处理这件事。今天我将尝试更好地记录事情并更新我的答案。更直接地回答您的问题。因此,在每次更新时,我们计算一个新值,它是新“度量”的一部分,也是旧值的一部分。查找“指数平滑”或“卡尔曼滤波”。对此,我没有强有力的数学基础,但在我的实现中,我将新度量的权重分配给它所代表的窗口的比例。这可能有助于通过手工操作和示例来了解历史值是如何“指数衰减”的。您可以查看启动,例如normalizedRate=0,事件以恒定的2/s或类似速度开始发生。谢谢我会详细阅读你的回复,稍后再查阅参考资料。