2012-02-23 37 views
4

我需要跟踪特定时间范围内的某些事件,并在事件数量达到特定数量时采取行动。更详细地说,我连接到外部服务并提交确认状态等于CONF或FAIL的请求。我需要能够监视响应以检测在给定时间范围内是否有不寻常的失败次数,例如, > 3在最后5秒内失败,以便我可以检查错误并采取相应措施。我可以选择检查连续3次失败,但我更喜欢基于时间的方法。Java收集过期条目

我一直在测试番石榴阅读本post后的CacheLoader但同时条目(我只存储FAIL事件)在Cache中出现的呼叫到期的预期,以size()(以确定失败的次数)亦包括过期的条目。这似乎是它应该如何工作根据documentation,如果我没有误解的事情?有没有办法从缓存中获取“活动”事件的数量?

我猜想另一种解决方案是使用像Esper这样的CEP框架,但对于我的简单需求来说,它看起来像是矫枉过正和麻烦。有没有人有完全不同的方法来建议,以促进我的要求?由于

+1

你看到什么'EhCache'缓存框架?我建议看看它。我认为解决你的要求。请参阅http://ehcache.org/ – MJM 2012-02-23 13:49:38

+2

我想我不明白这个问题。发送到外部服务。如果错误响应,则添加到带有时间戳的队列中。删除太旧的项目。如果列表长度>阈值,则执行一些操作。如果这种方法证明太慢,那么(并且只有这样)才能优化。一旦优化成为可以使用整数图,其中地图的关键是几秒钟的时间。当你添加一个错误时(使用秒作为键,递增计数),你确切地知道还有哪些其他键可以相加。 – 2012-02-23 14:03:56

+0

@TonyEnnis我不明白常规队列如何解决我的问题。我需要有某种迭代过程来监视和删除不能成为所需解决方案的条目。 – hgus1294 2012-02-23 16:26:05

回答

6

充分利用Cache活性元素的确切数目将需要锁定整个缓存,这是极其昂贵的。不过,您也许可以使用cleanUp()方法确保size不会意外计算已悄悄驱逐的条目。

我不会取决于在这给你确切的结果,但它应该显着提高结果的准确性。

+0

'size()'之前的'cleanUp()'诀窍!谢谢。我已经搞混了一个基于Esper的解决方案,我仍在测试。我要么接受这个答案,要么提供我自己的答案,取决于哪个解决方案更容易/更好。 – hgus1294 2012-02-23 16:23:52

0

我还没有使用它,但它看起来像this可能会满足你的需要

+3

从番石榴10.0(2011年9月28日发布)开始,许多MapMaker方法已被弃用,以支持新的CacheBuilder,这是我一直在测试而没有成功的。 – hgus1294 2012-02-23 13:48:26

1

我认为Guava收集与最接近的功能,你想要的是MinMaxPriorityQueue与有限的最大尺寸。您必须按时间顺序放置故障事件,并定期检查第一个元素和最后一个元素之间的差异以及是否已满。

但你基本上想要的是一米。您可以从Coda Hale的指标库中尝试this Meter

+0

非常感谢,但我认为使用路易斯提供的解决方案的Guava“缓存”更适合我,因为我不需要自己处理监控。 – hgus1294 2012-02-23 16:33:41

1

你可以装饰一个集合实现来做到这一点。像这样:

public class ExpirableArrayList<E> extends ArrayList<E> { 

    private final Date creation = new Date(); 

    private final long timeToLiveInMs; 

    public ExpirableArrayList(long timeToLiveInMs, int initialCapacity) { 
     super(initialCapacity); 
     this.timeToLiveInMs = timeToLiveInMs; 
    } 

    public ExpirableArrayList(long timeToLiveInMs) { 
     this.timeToLiveInMs = timeToLiveInMs; 
    } 

    public ExpirableArrayList(long timeToLiveInMs, Collection<? extends E> c) { 
     super(c); 
     this.timeToLiveInMs = timeToLiveInMs; 
    } 

    private void expire() { 
     if (System.currentTimeMillis() - creation.getTime() > timeToLiveInMs) { 
      clear(); 
     } 
    } 

    @Override 
    public int size() { 
     expire(); 
     return super.size(); 
    } 

    @Override 
    public boolean isEmpty() { 
     expire(); 
     return super.isEmpty(); 
    } 

    @Override 
    public boolean contains(Object o) { 
     expire(); 
     return super.contains(o); 
    } 

    @Override 
    public Iterator<E> iterator() { 
     expire(); 
     return super.iterator(); 
    } 

    @Override 
    public Object[] toArray() { 
     expire(); 
     return super.toArray(); 
    } 

    @Override 
    public <T> T[] toArray(T[] a) { 
     expire(); 
     return super.toArray(a); 
    } 

    @Override 
    public boolean add(E e) { 
     expire(); 
     return super.add(e); 
    } 

    @Override 
    public boolean remove(Object o) { 
     expire(); 
     return super.remove(o); 
    } 

    @Override 
    public boolean containsAll(Collection<?> c) { 
     expire(); 
     return super.contains(c); 
    } 

    @Override 
    public boolean addAll(Collection<? extends E> c) { 
     expire(); 
     return super.addAll(c); 
    } 

    @Override 
    public boolean addAll(int index, Collection<? extends E> c) { 
     expire(); 
     return super.addAll(index, c); 
    } 

    @Override 
    public boolean removeAll(Collection<?> c) { 
     expire(); 
     return super.removeAll(c); 
    } 

    @Override 
    public boolean retainAll(Collection<?> c) { 
     expire(); 
     return super.retainAll(c); 
    } 

    @Override 
    public E get(int index) { 
     expire(); 
     return super.get(index); 
    } 

    @Override 
    public E set(int index, E element) { 
     expire(); 
     return super.set(index, element); 
    } 

    @Override 
    public E remove(int index) { 
     expire(); 
     return super.remove(index); 
    } 

    @Override 
    public int indexOf(Object o) { 
     expire(); 
     return indexOf(o); 
    } 

    @Override 
    public int lastIndexOf(Object o) { 
     expire(); 
     return lastIndexOf(o); 
    } 

    @Override 
    public ListIterator<E> listIterator() { 
     expire(); 
     return listIterator(); 
    } 

    @Override 
    public ListIterator<E> listIterator(int index) { 
     expire(); 
     return listIterator(); 
    } 

    @Override 
    public List<E> subList(int fromIndex, int toIndex) { 
     expire(); 
     return subList(fromIndex, toIndex); 
    } 
}