写点什么

深入理解 Metrics(二):Counters

作者:冰心的小屋
  • 2022-11-08
    上海
  • 本文字数:1335 字

    阅读完需:约 4 分钟

1. Counters 的使用 

在 account 模块内部使用 Counters 统计异常发生的次数,一段时间内超过预置阀值会触发报警。

下面的一段代码是 account 用来检测用户登录失败发生的次数

public class MetricsCounterTest extendsTest0Abstract {   private List<String> users;   private String password;    @Autowired   @Qualifier("officialCustomerService")   private LoginService loginService;    @Before   public void before() {       password = "RIYU3ZOsYAThlfqfazyEbT+qe5ACN";       users = new ArrayList<>();       users.add("bingxin.li@tendcloud.com">bingxin.li@tendcloud.com");       users.add("bingxin.li001@tendcloud.com">bingxin.li001@tendcloud.com");       users.add("bingxin.li002@tendcloud.com">bingxin.li002@tendcloud.com");       users.add("bingxin.li003@tendcloud.com">bingxin.li003@tendcloud.com");       users.add("bingxin.li004@tendcloud.com">bingxin.li004@tendcloud.com");       users.add("bingxin.li005@tendcloud.com">bingxin.li005@tendcloud.com");       users.add("libingxin2013@outlook.com">libingxin2013@outlook.com");    }    @Test   public void login() throws Exception {       MetricRegistry metrics = new MetricRegistry();       ConsoleReporter reporter = ConsoleReporter.forRegistry(metrics).build();       reporter.start(1, TimeUnit.SECONDS);        Counter counter = metrics.counter(       MetricRegistry.name(MetricsCounterTest.class, "failed","size"));        for (String user : users) {           try {               loginService.login(Base64.getEncoder().encodeToString(user.getBytes()),password);           } catch (HttpUnauthorizedException e) {                counter.inc();                TimeUnit.SECONDS.sleep(2);                Assert.assertTrue(counter.getCount() < 3);           }       }    }}
复制代码

2. Counter 层级结构

Counter 内部通过持有 LongAdderAdapter 的实例来实现 Counting 接口,而 LongAdderAdapter 内部依赖的是 JDK1.8 并发原子操作的 LongAdder。

那么 Counter 是如何获取到 LongAdderAdapter 的实例呢?

3. LongAdder 工作原理

通过上面的创建和适配过程,并发原子操作最终交由 LongAdder 类完成,下面让我们来研究下 LongAdder 类的处理流程。

工作流程说明:

1. LongAdder 继承 Striped64 类,Striped64 使用不安全的 Unsafe 类来进行原子操作。

2. LongAdder 最核心的就是 add(long x) 方法,不管自增和自减都会调用此方法。 

3. add 方法基于 base 的 CAS 操作返回值来验证是否发生并发。 

4. 未发生并发:后续的原子操作、返回值都是基于 base。

5. 发生并发:通过 Cell 数组将原子操作分散到子项中进行,Cell 是 Striped64 的内部类,里面有存储 long 值的 value 字段。 

6. Cell 数组的索引:依赖与当前线程的 threadLocalRandomProbe。

获取偏移量的代码解析:

是否发生了并发操作:

实际的并发操作:

4. 结束语 

Java 除了并发包,还有很多集合类也是是 Doug Lea 编写的,通过本章对 Counters 的讲解,相信你一定会有所收获。


发布于: 刚刚阅读数: 3
用户头像

分享技术上的点点滴滴,让我们一起进步。 2013-08-06 加入

一杯咖啡,一首老歌,一段代码,欢迎做客冰屋。

评论

发布
暂无评论
深入理解Metrics(二):Counters_Java_冰心的小屋_InfoQ写作社区