how to count number of requests in last second, minute and hour

后端 未结 10 2082
情歌与酒
情歌与酒 2020-12-07 09:35

There is a hypothetical web server which supports only one very simple API - count of requests received in the last hour, minute and second. This server is very popular in t

10条回答
  •  情话喂你
    2020-12-07 10:23

    Here is a generic Java solution that can keep track of the number of events for the last minute.

    The reason I used ConcurrentSkipListSet is because it guarantees O(log N) average time complexity for search, insert and remove operations. You can easily change the code below to make the duration (1 minute by default) configurable.

    As suggested in the answers above, it is a good idea to clean up stale entries periodically, using a scheduler for example.

    @Scope(value = "prototype")
    @Component
    @AllArgsConstructor
    public class TemporalCounter {
    
        @Builder
        private static class CumulativeCount implements Comparable {
    
            private final Instant timestamp;
            private final int cumulatedValue;
    
            @Override
            public int compareTo(CumulativeCount o) {
                return timestamp.compareTo(o.timestamp);
            }
        }
    
        private final CurrentDateTimeProvider currentDateTimeProvider;
        private final ConcurrentSkipListSet metrics = new ConcurrentSkipListSet<>();
    
        @PostConstruct
        public void init() {
            Instant now = currentDateTimeProvider.getNow().toInstant();
            metrics.add(new CumulativeCount(now, 0));
        }
    
        public void increment() {
            Instant now = currentDateTimeProvider.getNow().toInstant();
            int previousCount = metrics.isEmpty() ? 0 : metrics.last().cumulatedValue;
            metrics.add(new CumulativeCount(now, previousCount + 1));
        }
    
        public int getLastCount() {
            if (!metrics.isEmpty()) {
                cleanup();
    
                CumulativeCount previousCount = metrics.first();
                CumulativeCount mostRecentCount = metrics.last();
                if (previousCount != null && mostRecentCount != null) {
                    return mostRecentCount.cumulatedValue - previousCount.cumulatedValue;
                }
            }
            return 0;
        }
    
        public void cleanup() {
            Instant upperBoundInstant = currentDateTimeProvider.getNow().toInstant().minus(Duration.ofMinutes(1));
            CumulativeCount c = metrics.lower(CumulativeCount.builder().timestamp(upperBoundInstant).build());
            if (c != null) {
                metrics.removeIf(o -> o.timestamp.isBefore(c.timestamp));
                if (metrics.isEmpty()) {
                    init();
                }
            }
        }
    
        public void reset() {
            metrics.clear();
            init();
        }
    }
    

提交回复
热议问题