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 的讲解,相信你一定会有所收获。
评论