自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(87)
  • 收藏
  • 关注

原创 10 行代码给 Agent 加上自我纠错能力

Agent 输出了一个错误的 SQL 查询——没有人类介入,它自己能发现并修正吗?:黑盒 → 入口 → 核心机制 → 三层实现 → 锚点前三篇我们做了三件事:给 Agent 装上了大脑(ReAct 的推理循环)、装上了计划能力(PtE 的规划执行分离)、以及看清了它们的 Token 账单。Agent 从"能回答问题"进化到了"能完成多步任务"。ReAct 每步都推理但不会检查推理对不对。PtE 先规划再执行但不会验证计划合不合理。

2026-08-17 06:42:45 297

原创 把 Agent 的推理从循环体内拉到循环体外

ReAct 每一步都做"推理→行动"循环,Token 消耗大、执行慢。Plan-then-Execute 把推理集中到规划阶段,一次性制定完整计划再执行。:理解了"规划与执行分离",你就知道为什么有些场景 Token 可以省一半。上篇我们把 ReAct 拆成了"推理→行动"的每步循环——每一步 LLM 都先想再干。这篇我们来看一个反直觉的进化:如果让 Agent 先一次性规划好所有步骤再执行,Token 能省多少?

2026-08-17 06:42:19 300

原创 ReAct 原理深度拆解:12 行代码到生产部署的完整指南

LLM 能回答问题但无法完成多步任务——ReAct 给 LLM 装上了"思考→行动→验证"的试错循环:一个答不出的问题 → 最简实现 → 每轮 Token 账单 → 决策框架 → 一句话锚点上篇我们提到 ReAct 是 Agent 最核心的执行模式——看一眼三元组图就懂了。但一张图能告诉你的事太少了;它不告诉你每轮消耗多少 Token、不告诉你什么情况下会死循环、不告诉你生产实现和教程实现差了多远。

2026-08-14 11:16:58 286

原创 ConcurrentHashMap 面试八股 vs 生产踩坑:三个事故让你重新理解线程安全

上篇讲了线程池参数面试和生产场景的落差,这篇我们来看另一道高频面试题——ConcurrentHashMap。线程安全?标准答案背得滚瓜烂熟,但组合操作照样翻车。

2026-08-14 11:16:23 356

原创 Dubbo 服务版本管理不善导致灰度失败

灰度发布流量全量走到旧版本,新版本 Provider 零流量,registry 机器齐全却路由不到→→→→。

2026-08-12 08:37:28 475

原创 日志凭空消失?Filter 顺序错了——Dubbo 一个 order 值让 ExceptionFilter 成了摆设

Provider 端 SecurityFilter 拦截了非法请求,返回了错误——但 ExceptionFilter 没写那行日志。

2026-08-12 08:37:00 524

原创 BeanDefinitionOverrideException 排查:Dubbo dubboBootstrapApplicationListener 重复注册

Spring Boot 2.1.5 + Dubbo 2.7.6,启动报 BeanDefinitionOverrideException,bean 名称 ‘dubboBootstrapApplicationListener’

2026-08-11 07:59:43 544

原创 Dubbo LeastActive 负载均衡新节点被打满?源码解析 active 计数器陷阱

追根溯源:Consumer 发起 RPC 调用时,经过进入集群层的负载均衡选择(AbstractClusterInvoker.java#L253-L266根据 Consumer URL 的参数实例化对应的策略实现。如果配了,就走#L40-L114):L63——获取每个 Provider 当前活跃请求数L69-L75: 找到活跃数最低的 Provider——每次找到更低值就重置选中的节点集合L95-L97: 如果只有一个 Provider 活跃数最低,直接返回,忽略权重第三行是关键。

2026-08-11 07:59:10 534

原创 排查 3 小时,问题竟在 Dubbo 路由规则:一个 force 的坑

上篇讲了 Dubbo 异步调用回调未执行的源码追踪,这篇来看另一个同样反直觉的问题。Dubbo(2.7.23)报错 ——但注册中心 Provider 明明在线。翻到 的源码才发现——路由规则把 Provider 全过滤了。凌晨 2 点,线上报警:Consumer 调用远程服务超时。查看日志,堆栈里躺着一条干巴巴的异常:这条规则的意思是"只允许调用 网段的 Provider"。但这次灰度发布的机器全在 ——加上 ,Consumer 直接拿不到任何 Provider。【直觉 vs 现实】:大多数人看到"N

2026-08-10 07:40:29 309

原创 Dubbo 2.7.5 的线程上下文陷阱:从版本演进看 AllChannelHandler 的设计之痛

Dubbo 消费端配置 async=true 异步调用,通过 RpcContext.getFuture() 拿到 CompletableFuture 注册 whenComplete 回调,但回调始终不执行。100 QPS 时正常,500 QPS 时大面积静默,滚动重启恢复,15 分钟后又复现。:Dubbo 2.7.5 DubboInvoker → AllChannelHandler 线程池排队 → DefaultFuture.complete → ThreadlessExecutor 副作用。

2026-08-10 07:40:05 606

原创 Dubbo 泛化调用参数序列化异常排查:PojoUtils 的三个隐匿陷阱

网关层泛化调用$invoke批量调用 Provider,时偶出现 ClassCastException / InstantiationException / StackOverflowError→ 3 个陷阱各自的源码位置上篇讲了 Dubbo 线程池满,根因在 Linux 用户线程数限制。这次 Dubbo 泛化调用又报了一个异常——。第一反应是 Hessian2 序列化问题,检查了一圈序列化配置,全是正常的。不是序列化的问题。

2026-08-09 09:08:06 332

原创 源码级排查:Dubbo 线程池爆满的另类根因——Linux nproc 限制

Dubbo Provider 报,线程池配置合理、QPS 正常:Dubbo 拒绝策略源码 → ThreadPoolExecutor.addWorker() → JVM pthread_create 失败 → ulimit -u 限制上篇我们排查了 Dubbo 直连模式调用失败的问题,根源是 URL 构建少了一个参数。这次 Dubbo 又报了另一个经典错误——线程池爆满,但这次根因不在 Dubbo 代码里。

2026-08-09 09:07:26 435

原创 DaemonSet 滚动更新导致 Prometheus 采集中断——优雅终止排查实录

DaemonSet RollingUpdate 过程中旧 Pod 被 SIGTERM → 进程不优雅退出 → Prometheus 采集链路断裂: Pod(优雅终止机制) → CRI(信号转发) → Node(kubelet 驱逐) → 集群(PDB 边界)上篇讲了 DaemonSet 更新策略的选择陷阱——OnDelete 和 RollingUpdate 各有适用场景。这篇我们来看 RollingUpdate 本身的一个更隐蔽的问题:更新过程中服务中断。

2026-08-08 08:37:10 723

原创 DaemonSet OnDelete 策略详解:为何 rollout restart 无效及正确迁移方案

给 fluent-bit DaemonSet 改了镜像版本,命令成功了——但 Pod 一个都没重启: Pod 状态 → 策略分层对比 → Node 版本漂移 → 集群策略选择上篇讲了 DaemonSet RollingUpdate 导致节点逐个宕机——原因是 CNI Pod 被终止后节点网络断连,kubelet 无法上报心跳,node controller 直接判 NotReady。教训是"关键基础设施 DaemonSet 别用 RollingUpdate"。

2026-08-08 08:36:20 684

原创 DaemonSet 滚动更新:节点一台接一台宕机,根因在更新策略

DaemonSet 滚动更新 CNI 配置 → DaemonSet Pod 逐节点终止重建 → 节点逐台 NotReady: Pod → CRI → Node → 集群 逐层排查上篇讲了 Pod 调度不均衡问题——nodeAffinity 配置写反导致 Pod 挤在同一台节点,资源利用率一边倒。这篇我们来看另一个因配置引发的连锁反应:DaemonSet 滚动更新导致节点逐个宕机。

2026-08-07 08:32:46 475

原创 K8s 调度不均衡排查实录:required 和 preferred 选错引发的连锁反应

上篇我们聊了 Pod CrashLoopBackOff 时日志拿不到的排查思路,用 crictl 绕过 kubectl 直接读容器运行时日志。这篇看一个完全不同的方向——Pod 不是起不来,是起来了但分布不均衡。:Deployment 20 副本上线后,Pod 全堆在 2 台 Node,其余 Node 资源充裕但无 Pod 被调度:Events 发现 FailedScheduling → 统计匹配标签的 Node 数 → 审阅亲和性配置 → 修正为 preferred → Pod 分布均匀。

2026-08-07 08:31:56 411

原创 K8s 实战:CrashLoopBackOff 状态下 kubectl logs 拿不到日志的三层排查方案

Pod 一直 CrashLoopBackOff,kubectl logs 看不到崩溃前的错误日志:坐标 → 分层 → 路径 → 定位 → 标点以下排查基于 K8s v1.25,容器运行时为 containerd v1.6。crictl 命令在 containerd v1.6+ 支持-a参数查看所有容器。

2026-08-06 08:52:45 392

原创 Pod 启动慢排查实录:Init Container + ImagePullPolicy 双重优化

灰度 5% 流量 → 超时率飙升 → 回滚 → 新版 Pod 启动慢了 3 分钟:坐标 → 分层 → 路径 → 定位 → 标点以下排查基于 K8s v1.25,容器运行时为 containerd 1.6。

2026-08-06 08:52:05 463

原创 Nginx upstream keepalive 连接池中毒排查实录

Nginx 反代部分请求 502 / body 错乱 / 上游报"invalid header field" |:tcpdump → keepalive 连接请求边界错位 → Content-Length 不匹配 → Nginx event-driven state machine 未校验 socket 残留上篇我们看了中间层通过 conntrack 超时静默发 RST 导致连接断裂的情况,这篇来看另一种连接异常——连接没断,但数据被悄无声息地污染了。

2026-08-05 08:42:26 501

原创 TCP keepalive 与 conntrack 超时不一致导致连接 RST——排查全过程

连接空闲 30 分钟后复用报错 |上篇我们分析了 TCP RST 包的常见原因——端口未监听、防火墙拦截、应用层主动关闭。这篇来看一个更隐蔽的场景:两端连接都是 ESTABLISHED,中间层却悄悄断了。T0.000 客户端发出业务数据。T0.001 中间设备回了 RST——中间这 1ms,数据包在 conntrack 表里查无此人。不是端口问题,不是进程挂了——是内核的 conntrack 表项被清了,而两端都不知道。

2026-08-05 08:41:37 422

原创 MySQL GROUP BY 性能优化:执行计划分析 + 索引重构实战

月度 Top 消费用户查询从 0.12 秒变 4.7 秒,加了索引也没用:EXPLAIN → Using temporary → 临时表磁盘溢出 → 组合覆盖索引上篇讲了索引失效的 10 种场景,这次我们来看一个更隐蔽的坑——索引没失效,查询照样慢。

2026-08-03 09:52:34 701

原创 RocketMQ 消息堆积怎么办?线程池用完才是病根

业务端到端耗时从 200ms 涨到 5s,消息堆积 50 万条。业务方怀疑生产者慢,链路追踪发现消费端才是根因——20 个消费者线程全部卡在同步 DB 写入上,形成 rebalance 死亡螺旋:消费 lag 监控 → 消费者线程池 → 消费者源码 → 业务代码 → 修复方案上篇讲了 10909 VIP 端口阻塞导致 RocketMQ 消息发送端大量超时,这次我们来看消费端最经典的问题——消息堆积。下单接口耗时从 200ms 涨到 5s,业务方第一反应是数据库慢。DBA 查了一圈——数据库毫无压力。

2026-08-03 09:52:04 415

原创 RocketMQ 消息发送失败排查实录:一行代码引发的线上事故

订单服务灰度上线,消息发送成功率骤降 0%,Broker 端一切正常:应用日志 → 端口特征 → 网络排查 → 源码追查本文所有日志时间已统一到 UTC+8上篇我们分析了 RocketMQ Broker 高负载下的 SYSTEM_BUSY 根因——磁盘 IO 打满导致发送队列排队超时。这次遇到的案例走向了另一个极端:所有指标都正常。订单服务上线了一个新版本。5 分钟后,用户反馈"下单后收不到物流通知"——不是慢,是完全收不到。查监控:消息发送成功率 0%。

2026-08-02 09:18:26 489

原创 CMS GC 频繁 promotion failed 排查——调大堆为什么没用

6GB 堆的订单服务持续 promotion failed,调大堆后次数反而翻倍。:GC 日志定位 → 碎片化/并发周期跟不上的双根因判断 → CMS 参数微调方案 → 迁移 G1/ZGC 的长期路径上篇讲了 Metaspace OOM 时如何通过 TraceClassLoading 定位动态类加载泄漏,这篇我们来看另一个维度的老年代问题——CMS promotion failed 不是堆不够大,是碎片化和并发周期跟不上。

2026-08-02 09:17:36 465

原创 生产事故:ScheduledThreadPoolExecutor 定时任务执行间隔从5秒变成30秒

每 5 秒执行一次的定时任务,实际间隔变成了 8 秒、15 秒、30 秒——越来越慢:检查执行时间 → 区分 fixedRate vs fixedDelay → 验证异常处理 → 监控线程池状态上篇讲了核心线程数设错导致吞吐下降,这篇我们来看线程池配置里一个更隐蔽的定时器陷阱——的任务"丢"了,但实际上不是丢了,是排不上队。一个定时任务,配了,每 5 秒执行一次。上线第一周正常。第二周发现:任务执行间隔变成了 8 秒、15 秒、30 秒——不是膨胀,是"堵车"了。而代码里只有一个人在开车。

2026-07-30 07:56:56 313

原创 生产事故:线程池核心线程数设200,CPU才50%但接口全超时

8C16G 容器,线程池 200 个核心线程,CPU 50% 但 P99 延迟从 50ms 涨到 800ms:判断任务类型 → 公式计算 → 压测验证 → 持续监控上篇讲了拒绝策略选型失误导致任务静默丢失,这篇我们来看线程池配置里另一个更隐蔽的参数——核心线程数。配大了线程打架,配小了队列积压,而且大部分人的直觉都是错的。8 核 CPU,200 个核心线程。你认为吞吐会是多少?如果答案是"很高",那你需要读完这篇。

2026-07-30 07:55:57 359

原创 opencode 源码拆解:FormatError 集中式错误路由的设计与实现

opencode 的错误定义分布在各个模块中,但遵守相同的模式:每个自定义错误类继承自,自带一个_tag标签和一个结构化字段集。}) {}}) {}}) {}_tag的独特之处在于它由 Schema 自动生成,不可篡改。这意味着 FormatError 可以用字符串匹配_tag来精准路由——不依赖instanceof,不依赖鸭子类型,一个纯函数就能覆盖全部已知错误。

2026-07-29 08:22:41 468

原创 project/workspace设计:monorepo下工作单元的组织与隔离策略

9 个字段(标识组(id, name, icon)——你是谁。id是自动生成的(由 git repo 的 path hash 决定),name和icon由用户设置或自动发现(discover()方法在 worktree 里扫favicon.*边界组(worktree, vcs, sandboxes)——你在哪。worktree 是物理根目录,vcs 是版本控制类型(目前只有"git"),sandboxes 是额外的工作目录列表。

2026-07-29 08:21:42 433

原创 Git 集成:AI 代理中的版本控制工作流设计

Git 集成的意义超越了"封装了一个 git 调用"。第一层——Git.Service 解决了"怎么安全调用 git"的问题。6 个跨平台 cfg、Effect.catch 兜底、15 个结构化方法。你不需要在每个工具函数里写execSync。第二层——Vcs.Service 解决了"业务需要什么语义"的问题。mode="git"和两个模式把 diff 的边界计算封装成 1 个方法调用。Agent 不需要知道 merge-base、HEAD 存在性、默认分支名——Vcs 帮你处理了 5 个边界。第三层。

2026-07-28 09:54:33 521

原创 Spring @Async 注解失效排查:同实例方法调用导致的代理绕过问题

接口 P99 从 200ms 涨到 400ms,调用量没变——耗时操作本该异步却被同步阻塞:断言 → 现场 → 拆解 → 处方 → 雷标。

2026-07-28 09:53:57 904

原创 线程池满了:拒绝策略选型失误导致任务丢失,没有报错的数据黑洞

/ 生产推荐:记录 + 告警 + 降级@Override// 1. 记录拒绝信息log.error("[{}] 拒绝任务: queue={}/{}, active={}/{}, pool={}/{}",poolName,// 2. 发告警alertService.send("线程池拒绝告警", poolName, ...);// 3. 执行降级逻辑。

2026-07-27 09:35:51 436

原创 踩坑实录:@Transactional + REQUIRES_NEW 导致数据半提交,连接池被打满

@Transactional 嵌套调用导致数据半改——一个注解管不到两个数据库连接:现场 → 三层边界拆解(JDBC/传播/数据源)→ 处方 → 雷标上篇文章讲了同一个类里方法调方法不走代理导致不生效——这是"代理绕过"的问题。这篇我们更进一步:就算走了代理、正常触发了,它到底管了多少?你以为会管所有数据源?它只管理了一个 JDBC Connection 的 begin/commit/rollback。同一个 DataSource 上开的新 Connection 它也不管。

2026-07-27 09:34:35 506

原创 Spring 事务 REQUIRES_NEW 嵌套调用:连接池翻倍的秘密

上篇文章解决了"同一个类里方法调方法不走代理"的问题——你在方法 A 上加,调本类方法 B,B 的事务配置被无视,退化为 outer 事务的一部分。现在你知道了,把方法 B 抽到另一个 Service,给它加上,于是 B 应该有一个"全新独立"的事务。这个直觉只对了一半。更隐蔽的是,如果 B 和 A 共享同一个 EntityManagerFactory,B 的回滚可能顺手把 A 的 PersistenceContext 也污染了——而你还在开心的 catch 异常,以为万事大吉。

2026-07-26 08:56:18 486

原创 @Transactional 同类自调用失效:AOP 代理绕过原理与三种解决方案

运营批量导入 48 条用户数据,@Transactional 加了但只成功了 30 条——同类自调用导致事务没生效:断言 → 现场 → 拆解(代理机制/自调用根因)→ 处方 → 雷标:~12 分钟。

2026-07-26 08:55:43 396

原创 MAT OQL 排查字符串泄漏:从 4GB Dump 到一行代码的定位过程

代码用做处理器级缓存,但没有 put 上限、没有 TTL、没有 LRU。业务逻辑漏了删除已完成的条目,所有历史 orderId 留在了 Map 里。问题不在单个对象——单个 String 不过几十字节。问题在缓存模型选型与业务生命周期不匹配。如果缓存对象数不超过 1 万,用没问题;但这个场景下 map 键数会每日增长,注定爆炸。

2026-07-25 15:35:32 533

原创 opencode CLI 入口层源码拆解:effectCmd + InstanceStore + bootstrap 三层设计

拆解 opencode 源码 · 第二章 CLI 入口与启动流程 · 总结篇如果你要设计一个 CLI 入口层,你会先做什么?大部分人从框架选型开始:yargs 还是 commander.js?但 opencode 的第二章揭示了另一个顺序——。因为整个 CLI 层的形状,是由 Effect-ts 运行时决定的,不是由 yargs 决定的。。本文不重复三篇正文的技术细节——它们已经在 02-01 到 02-03 里了。。

2026-07-25 15:34:51 512

原创 opencode 源码拆解(一)总结篇:前置篇的设计哲学与四条核心原则

这是 opencode 最频繁出现的模式。在 Effect-ts 章节中我们看到}) {}— 第 1–6 行同样的模式也出现在 monorepo 的catalog机制中——一个版本号定义在根,全仓库 29 个包共享。修改一行,所有包自动继承。

2026-07-24 09:22:40 494

原创 opencode 配置系统源码拆解:5 层来源合并管道与 Config.Service 实现

opencode 的配置系统 686 行——比起 naive 方案每个模块自己读配置,是多写了 600 行。但换来的是 5 层来源的自由组合、63 字段的集中管理、两条入口统一查询、运行时 patchJsonc 原地编辑。200 行搭好管道,永远只加来源不改查询。上一篇我们看到了"注册表模式"的力量。这一篇是"合并管道模式"——不是横向扩展(加命令),而是纵向叠加(加来源)。下一篇拆 Git 集成,看第三个模式:Session 内嵌的状态管理。

2026-07-24 09:21:58 457

原创 起底 opencode 斜杠命令:184 行代码撑起 /review /commit /diff

整个命令系统的核心是一个 Schema 定义:8 个字段定义一条命令的一切。最关键的字段是template—— 它的类型是,注释写得很清楚:有些命令模板是 MCP 远程解析的懒加载 Promise,不是静态字符串。你可能会想:为什么不用string而是用Unknown?这不就丢了类型安全吗?作者的选择恰恰相反:Unknown不是放弃类型,而是拥抱两种加载模式。静态模板在初始化时就拿到字符串,MCP 模板在首次访问时才触发 RPC。如果设计成string。

2026-07-23 09:45:55 629

原创 opencode 源码拆解:run 命令从 CLI 到 Agent Loop 的三层路由设计

如果你要设计一个能从终端命令一路走到 AI Agent 循环的架构——用户敲一行 ,你的系统怎么把这个字符串变成一次完整的 LLM 推理?你可能会想:这有什么难的? 解析一下,switch-case 分发,函数里调 LLM,完事。对,但如果你的 CLI 有 20+ 个选项、3 种交互模式(非交互/本地交互/远程附加)、还需要加载完整的项目上下文(配置、插件、Provider)——switch-case 会在第 5 个选项时变成一团浆糊。opencode 的作者也经历了这个演变。前两篇拆了 yargs 注册

2026-07-23 09:44:56 548

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除