一个后台线程断言异常如何杀掉整个插件功能:read-action线程模型踩坑实录
IntelliJ平台PsiReference双向导航:从isReferenceTo到word-index的架构权衡
需求:让框架式调用也能双向跳转
业务代码里大量存在这种框架式调用——方法名藏在字符串字面量里:
1 | // MyBatis 风格:字符串 = Dao 接口方法名 |
IDE 原生对这种字符串无能为力。插件的诉求是四向导航:
| 位置 | 操作 | 期望 |
|---|---|---|
Java "getXxx" 字符串 |
Ctrl+B | 跳 Dao 方法 / Moc XML |
| Dao 方法声明处 | Ctrl+B / Find Usages | 反查字符串 |
Mapper XML <select id> |
Ctrl+B | 弹「Dao 方法 + 调用点」 |
Moc XML name 属性 |
Ctrl+B | 弹 Java 调用点 |
这篇文章记录实现过程中的三次架构演进——每一次都是被真实现象(选择框不弹、进度条死循环、几万文件搜索)逼出来的重新设计。
IDEA插件内存泄漏与GC风暴:一次jstat驱动的完整排查与修复
背景:装了插件的 IDEA 卡到不能用
团队自研的 IDEA 插件更新后,出现了一个很诡异的症状:什么都没做,只是打开了几个文件,IDEA 就卡得不行。CPU 风扇狂转、界面掉帧、时不时冻结几秒。
比”卡”更有价值的是手里的 GC 数据。连续抓了几轮 jstat -gcutil:
1 | S0 S1 E O M CCS YGC YGCT FGC FGCT GCT |
只看数字就能拆出三层信号。这篇文章完整复盘这次排查:从 jstat 解读、到沿执行路径找代码证据、到三类修复的设计与验证。
从同步超时到异步流式:一次MES报表导出链路的完整改造
老 MES 系统里”导出”大概是最容易被低估的功能:早期数据量小,一个同步接口把数据查出来写成 Excel 直接回传,皆大欢喜。等到单表日志类数据涨到千万行、报表动辄几十万行时,这条链路开始连环爆雷。本文记录一次完整的导出链路改造:从同步超时丢文件,到「提交即返回 + 游标流式读取 + 异步写入 + 桌面通知取件」的全套架构,包括关键实现细节、踩过的每一个坑,以及清楚留着的优化债。
一、同步导出的四宗罪
改造前的链路是典型的”一把梭”:
1 | 用户点导出 → 请求线程分页循环查全量 → 攒成大 List → 写 Excel → HTTP 响应回传 |
数据量上来后暴露的问题按出现频率排序:
- 网关超时:内部走 Ribbon/Zuul 网关,读超时默认 10 秒,导出耗时一超,连接被网关掐断——用户拿到半个文件或一个报错页;
- 内存压力:全量行同时驻留 JVM 堆(
List<Map>+ 写缓冲),几个人并发导出大报表,堆直接见顶; - 体验差:用户必须挂着页面等,手一抖刷新就前功尽弃;
- 不可回溯:一旦超时,服务端即便把文件写出来了也没法交给用户,白白浪费一次全量查询。
期间打过一层补丁:同步导出超时后转后台继续写,完成后上传文件、发通知。这解决了一部分问题,但”用户先同步等 30 秒”的体验和分页翻页式读取的额外开销还在。于是有了这次彻底的改造。
平滑数据迁移:28GB预警发送日志表的在线瘦身实战
JVM堆与物化:一次MES服务假死事故的完整诊断
jar包直接替换单个class文件或修改文件内容的方法
仅修改某个类的实现逻辑或修复bug而不重新编译构建整个项目时,可以使用命令行工具手动替换class文件。
一次mysql数据库备份还原导致的生产环境事故
事故直接原因


1 | pv dengqimes_20250519_144357.sql | mysql --database=dengqimes-test --user=zy_mes -pr4UQBwBV --host=127.0.0.1 --port=3306 --default-character-set=utf8mb4 |
使用 pv | mysql的组合,老版mysql在shell命令处理参数时,会忽略 dengqimes-test 中的 -,导致实际上mysql将备份还原到了数据库 dengqimes 上。而正式环境和测试环境数据库名恰好仅用-加后缀进行区分。
- “pv | myslq 版本演示”
NGINX反向代理配置实现不同客户端请求路径都在后端统一映射到同一路径
要实现的效果

| 客户端请求路径 | 后端接收路径 |
|---|---|
https://域名/J5BfNtYvHW/api |
http://后端:54321/J5BfNtYvHW/api |
https://域名/api |
http://后端:54321/J5BfNtYvHW/api |
要实现 所有客户端请求路径 最终在后端统一映射到 /J5BfNtYvHW/api,可以通过以下两种方案实现:
- 双路径代理(无重写)
- 路径重写
方案一:路径重写(推荐)
1 | server { |
路径映射效果:
| 客户端请求路径 | 后端接收路径 |
|---|---|
https://域名/J5BfNtYvHW/api |
http://后端:54321/J5BfNtYvHW/api |
https://域名/api |
http://后端:54321/J5BfNtYvHW/api |
方案二:双路径代理(无重写)
1 | server { |
路径映射效果
| 客户端请求路径 | 后端接收路径 |
|---|---|
https://域名/J5BfNtYvHW/api |
http://后端:54321/J5BfNtYvHW/api |
https://域名/api |
http://后端:54321/J5BfNtYvHW/api |