老废物乐园

CompletableFuture 在聚合接口中的性能实践

商品详情页 P99 1.8 秒,五个 RPC 串行调用 12 月中旬,前端同学甩过来一张截图:商品详情页首屏白屏 2 秒多,用户投诉"点商品没反应"。我去看 SkyWalking 的拓扑,这个接口平均 690 ms,P99 1.8 s,P999 3.2 s。 接口干的事很简单,串着调了 5 个下游:

Administrator Administrator 发布于 2020-12-31

LongAdder 为什么比 AtomicLong 快

压测数据:同样的计数,快了 6 倍 十一月中旬做网关的埋点统计改造,需要统计每个接口的调用次数和总耗时。我一开始用的 AtomicLong: private final Map<String, AtomicLong> counters = new ConcurrentHashMap<>(); pu

Administrator Administrator 发布于 2020-11-13

一次线程池参数设置不当导致的雪崩

十月十六号:一个线程池配置引发的连锁故障 那天下午三点,监控系统开始报"下单接口超时率 35%"。我打开看的时候,发现不只是下单——商品详情、购物车、用户信息,几乎所有接口都在超时。网关的活跃连接数从平时的 200 涨到了 7800。 整个服务集群像是被什么东西卡住了。 现象:线程全在 WAITIN

Administrator Administrator 发布于 2020-10-16

原子类与 CAS:ABA 问题及解决方案

面试官追问"ABA 具体怎么解决",我卡住了 12 月中的一次面试。聊到 CAS,我说"它有个 ABA 问题",面试官问"什么场景下真的会遇到 ABA?怎么解决?" 我答"加版本号",他又追了一句"JDK 里加版本号的那个类,你知道它的 compareAndSet 是怎么实现的吗?" 答不上来。回去

Administrator Administrator 发布于 2019-12-16

CountDownLatch、CyclicBarrier、Semaphore 使用场景辨析

Code Review 时发现同事用 CyclicBarrier 写了个一次性等待 9 月中的一次 code review,我看到同事写了这么一段:一个接口要并行查三个数据源然后汇总,他用 CyclicBarrier 做同步。功能是对的,但读起来很别扭——CyclicBarrier 那套 await

Administrator Administrator 发布于 2019-09-26

BlockingQueue 家族与生产者消费者模型落地

读 ThreadPoolExecutor 源码时,我顺手压测了三种队列 9 月份啃线程池源码,看到构造函数里那个 BlockingQueue<Runnable> workQueue 参数,我才意识到自己从来没认真选过它——一直是 Executors.newFixedThreadPool(20) 一路

Administrator Administrator 发布于 2019-09-12

一次线上死锁排查:jstack 定位与修复

批量扣款任务卡死后,单笔扣款接口也全挂了 7 月 5 号早上 9 点 12 分,监控开始告警:/api/deduct 接口响应时间从 60 毫秒飙到 30 秒全部超时。同时 DBA 在群里说,account 表上有锁等待,已经持续 4 分钟。 第一反应是数据库慢查询。但登上机器看,应用这边 CPU

Administrator Administrator 发布于 2019-07-08

线程池的拒绝策略怎么选?一次消息队列积压的教训

凌晨两点的告警:消息积压 12 万条 6 月 18 号大促那晚,我睡到两点被电话叫醒。监控群里刷的是一条 RocketMQ 的告警:order_pay_topic 消费 TPS 从平时的 800 掉到了 30,积压量 12 万条还在涨。 赶紧登机器看日志,消费者进程活着,CPU 只有 11%,但日志

Administrator Administrator 发布于 2019-06-21

AQS 源码初探:ReentrantLock 是怎么实现的

jstack 里那个等了 40 秒的线程 5 月中旬,运营反馈大客户导出特别慢,一个 20 万行的订单导出要跑三分钟。我抓了几份 jstack,发现有个线程的行为很奇怪: "export-thread-7" #48 prio=5 os_prio=0 tid=0x00007f8c4c0d8000 ni

Administrator Administrator 发布于 2019-05-24

ThreadPoolExecutor 源码解析:execute 之后发生了什么

同事问了个我答不上来的问题 2 月中旬,组里做短信发送模块的改造,同事在配置线程池时问我:corePoolSize 用完之后,是立刻扩容到 maximumPoolSize,还是先往队列里塞? 我当时脱口而出"先扩容到 max"。说完自己就心虚了,因为印象里看过"队列满了才会扩"的说法。答不上来的问题

Administrator Administrator 发布于 2019-02-21