引言
在微服务架构和分布式系统中,对服务的请求量、响应时间等指标的实时监控至关重要。阿里巴巴开源的 Sentinel 是一个用于流量控制、熔断降级、系统负载保护的中间件。它通过一系列的度量指标来实现对系统状态的实时感知,而 LongAdder
正是 Sentinel 实现这些度量的核心数据结构之一。
一、LongAdder:线程安全的高性能计数器
LongAdder
是 Java 8 引入的一个新类,位于 java.util.concurrent.atomic
包中。它的设计目的是为了在高并发环境下提供高性能的加法操作,尤其适合用于计数场景。LongAdder
的实现借鉴了 Striped64
类,后者是 ConcurrentHashMap
的基础组件之一,通过减少锁的竞争来提高并发性能。
示例:使用 LongAdder
计数
import java.util.concurrent.atomic.LongAdder;public class LongAdderExample { private static final int THREAD_COUNT = 100; private static final int TASK_COUNT_PER_THREAD = 10000; public static void main(String[] args) throws InterruptedException { LongAdder longAdder = new LongAdder(); Thread[] threads = new Thread[THREAD_COUNT]; for (int i = 0; i < THREAD_COUNT; i++) { threads[i] = new Thread(() -> { for (int j = 0; j < TASK_COUNT_PER_THREAD; j++) { longAdder.increment(); } }); threads[i].start(); } for (Thread thread : threads) { thread.join(); } System.out.println("Total count: " + longAdder.longValue()); }}
二、Sentinel 中的 LongAdder 应用
在 Sentinel 中,LongAdder
被广泛应用于统计各种度量指标,例如资源的请求次数、响应时间等。这是因为 LongAdder
在高并发场景下能够提供优秀的性能和准确的数据统计,非常适合 Sentinel 这种需要实时监控系统状态的场景。
源码解析:Sentinel 中的度量指标存储
在 Sentinel 的源码中,DefaultMetricRecord
类是用于存储度量指标的主要载体,其中就使用了 LongAdder
来存储诸如 passCount
(通过的请求次数)、blockCount
(被限流的请求次数)等数据。
// Sentinel 源码片段示意public class DefaultMetricRecord implements MetricRecord { private final LongAdder passCount = new LongAdder(); private final LongAdder blockCount = new LongAdder(); private final LongAdder exceptionCount = new LongAdder(); // ...其他属性和方法 public long getPassCount() { return passCount.longValue(); } public long getBlockCount() { return blockCount.longValue(); } public long getExceptionCount() { return exceptionCount.longValue(); }}
三、LongAdder 的内部实现
LongAdder
的内部实现基于 Striped64
,其核心思想是通过分割(striping)技术来减少锁的竞争。它维护了一个数组,每个元素代表一个槽(cell),每个槽都可以独立地进行加法操作。当线程需要进行加法操作时,它会选择一个槽进行操作,如果该槽已经被占用,则会尝试其他的槽。这样,即使在高并发场景下,也能极大地减少锁的争用,从而提高整体的性能。
源码解析:LongAdder
的 add 方法
// LongAdder 源码片段示意public final void add(long x) { Cell[] as; long b, s; int h; if ((as = cells) != null || !casBase(b = base, b + x)) { synchronized (this) { if (as == null || (h = ThreadLocalRandom.getProbe()) >= as.length) ThreadLocalRandom.rescaleProbe(h); else if (cells == as) lazySetCells(null); Cell a = as[(h & (as.length - 1))]; if (a == null) as[h & (as.length - 1)] = a = new Cell(); a.value += x; s = sum(); if (base != b && s != b) base = s; } }}
结语
LongAdder
在 Sentinel 中扮演着重要的角色,它不仅提高了度量指标的统计效率,还保证了数据的一致性和准确性。通过本文的介绍,相信你已经对 LongAdder
及其在 Sentinel 中的应用有了更深的理解。掌握这一核心组件的运作机制,对于构建高性能的流量控制和系统保护策略至关重要。
更多搜索作者名称【源码解析】 知识星球,与你一起探索技术深处的秘密。
在知识星球,我们将继续深入探讨 Sentinel 的其他核心组件和技术细节,包括但不限于限流算法、熔断策略和系统保护机制。加入我们,让我们一起挖掘技术背后的奥秘,提升你的技能,成为真正的技术专家。
如果你对 Sentinel、高并发计数、流量控制等话题感兴趣,欢迎加入我的知识星球,那里有更多深度分析和实战案例等待着你。
来源:
互联网
本文观点不代表源码解析立场,不承担法律责任,文章及观点也不构成任何投资意见。
评论列表