去年用 JDK 21 虚拟线程接重构一个 HTTP 聚合服务,压测时吞吐死活上不去。翻 JFR 发现大量"虚拟线程被 pin 在载体线程上"的事件——罪魁是代码里随处可见的 synchronized。JDK 22/23 的改进,正好把这块骨头啃了下来。 Pin 是什么,为什么是性能杀手 虚拟线程的精
我们一个网关服务,平时 P99 延迟 40ms 很稳,但每天凌晨批量任务后总有几次 200ms+ 的卡顿尖刺。G1 的 Mixed GC 停顿在堆大时是元凶。JDK 21 上 ZGC 已经成熟,我决定赌一把把它换上。 切换决策:先看停顿从哪来 先用 JFR 抓了一周 GC 数据。G1 在 16G 堆
我们的内部知识库 RAG 上线第一周,产品拿了个真实问题测试:"年假怎么休?"模型一本正经地答了去年的旧政策。查下来,召回的文档里既有新政策也有旧政策,模型没分清哪个是现行有效的。RAG 的难点从来不在"接上模型",而在"召回准不准、排得对不对"。 第一板斧:切分策略 最初按固定 500 字符硬切,
团队想给客服系统加 AI 能力,产品经理一句"接个大模型"听起来轻巧。真要做时,我发现最大的问题不是模型效果,而是:AI 该放在系统哪一层?和现有业务怎么融?出错了怎么办?这层边界不清,迟早把核心交易拖下水。 边界划分:AI 是增强,不是核心 我的第一原则是:AI 能力必须处在非关键路径。下单、扣款
有天凌晨告警:订单服务报错率突增。我登录 Kibana 翻日志,几千行文本里找那一条异常,正则写到手抖,花了 20 分钟才定位。痛定思痛,把日志从"人看"改成"机器看"——结构化输出,这套改造后来的排障时间从 20 分钟降到 40 秒。 为什么要从文本日志切到结构化 文本日志是给人扫的,机器分析要正
用 Spring AI(1.0 GA 稳定版)做 RAG,最早我是在业务代码里手写"先检索、拼 prompt、再调模型"三段式。逻辑散落、难复用、难插拔。后来发现 Spring AI 的 Advisor 机制就是为这事设计的——把"检索增强"做成可串联的拦截器。 Advisor 是什么:请求响应之间
大模型再能聊,它本身算不了实时库存、查不了数据库。要让它"动手",得靠 Function Calling:模型决定调哪个函数、填什么参数,Java 侧真实执行,再把结果喂回去。这趟趟过的坑,比想象中深。 工具注册:把 Java 方法暴露给模型 用 Spring AI(1.0 GA 稳定版)注册一个工
订单系统里,一个下单成功事件要同时触发:发短信、更新统计、同步搜索索引、通知风控。一开始我用 @TransactionalEventListener 在一个方法里全干了,结果短信接口抖一下,整个下单事务被拖慢。这种"一个事件多个消费者"的场景,正是 Spring Integration 的主场。 消
我们的一个内部工具服务,部署在 Serverless 上,每次冷启动要 8 秒。函数计费按运行时长,8 秒里一半在"加载类、初始化 Spring 上下文",用户已经走了。老板问能不能压到 2 秒内,于是有了这次冷启动专项优化。 先量化,再动手 不量就优化是瞎猜。我用 -Xlog:class+load
一个服务在 K8s 里跑得好好的,突然被重启,看 Pod 事件只有一行 OOMKilled。我第一反应是"堆不够了",加了 -Xmx 之后反而重启更频繁。后来才明白,我搞混了两种 OOM。 两个 OOM 不是一回事 JVM 的堆 OOM(java.lang.OutOfMemoryError: Jav