<?xml version="1.0" encoding="utf-8" ?><rss version="2.0"><channel><title><![CDATA[zijieduke的博客]]></title><description><![CDATA[]]></description><link>https://blog.csdn.net/zijieduke</link><language>zh-cn</language><generator>https://blog.csdn.net/</generator><copyright><![CDATA[Copyright &copy; zijieduke]]></copyright><item><title><![CDATA[线上 70% 的问题难排查，都是日志乱写导致的]]></title><link>https://blog.csdn.net/zijieduke/article/details/166095418</link><guid>https://blog.csdn.net/zijieduke/article/details/166095418</guid><author>zijieduke</author><pubDate>Sun, 20 Sep 2026 09:06:14 +0800</pubDate><description><![CDATA[做后端排查线上问题久了，有一个特别深的感触：绝大多数故障并不是代码逻辑有多难、框架有多坑，而是日志信息缺失、打印混乱、格式随意，导致明明两分钟能定位的BUG，硬生生排查半天。日志体积暴增，磁盘疯狂写入，日志文件滚动极快，关键信息瞬间被冲刷覆盖，反而更难排查。还有更离谱的，捕获异常后直接空吞，完全不打印日志。很多项目接入链路追踪很晚，就是因为前期日志没有追踪维度，每次排查都要人工筛选、匹配、过滤，效率极低。线上出现问题，日志只能告诉你“这里出错了”，但完全不告诉你为什么错、哪一行错、什么异常类型。]]></description><category></category></item><item><title><![CDATA[Netty 开发随记：那些调试半天才能定位到的隐性问题]]></title><link>https://blog.csdn.net/zijieduke/article/details/165832966</link><guid>https://blog.csdn.net/zijieduke/article/details/165832966</guid><author>zijieduke</author><pubDate>Fri, 18 Sep 2026 08:30:57 +0800</pubDate><description><![CDATA[还有，如果把这个解码器放在 pipeline 的靠后位置，前面处理器已经消费了部分 ByteBuf，解码器拿到残缺数据，会直接彻底乱掉。Demo 确实没问题，一旦放到真实业务，处理粘包拆包、空闲检测、异常输出、内存回收，各种奇奇怪怪的现象就冒出来。这里也有一个细节，业务线程池不要用无界队列，客户端疯狂推送消息的时候，任务无限堆积，直接 OOM。部分异常发生在业务异步线程里面，不会走到这个回调，异步内部必须自己 try‑catch，否则直接把业务线程池搞崩。日志什么输出都没有，只看到连接断开。]]></description><category></category></item><item><title><![CDATA[LocalDateTime 那些文档不说、线上必炸的隐性问题]]></title><link>https://blog.csdn.net/zijieduke/article/details/165713035</link><guid>https://blog.csdn.net/zijieduke/article/details/165713035</guid><author>zijieduke</author><pubDate>Thu, 17 Sep 2026 09:18:32 +0800</pubDate><description><![CDATA[但实际开发下来发现，很多线上时间错乱、比对异常、序列化报错、入库数据偏差问题，全是新时间API的隐性特性导致的。线上服务器如果是默认UTC时区，代码生成的当前时间、数据库取出的时间，会直接出现时差错乱。Java8 新时间 API 确实比旧 API 优秀，但很多开发者只学会了基础用法，不了解时区、序列化、框架适配的底层细节。大部分时间错乱、序列化异常、环境不一致的问题，不是代码逻辑错了，是忽略了时间对象的底层特性和环境差异。而且转换过程如果不指定时区，转换出的时间戳完全错乱，统计、排序、日志时间全部出错。]]></description><category></category></item><item><title><![CDATA[Spring MVC 参数接收容易踩的 6 个隐形坑]]></title><link>https://blog.csdn.net/zijieduke/article/details/165568703</link><guid>https://blog.csdn.net/zijieduke/article/details/165568703</guid><author>zijieduke</author><pubDate>Wed, 16 Sep 2026 08:13:28 +0800</pubDate><description><![CDATA[字段 UserName、setter setUserName，Spring 解析对应的参数名为 u serName，和前端传入的 userName 不匹配，直接绑定失败。但线上很多 400、参数为空、类型转换异常、接收不到数据的问题，都不是写错注解导致的，是对 Spring MVC 参数绑定规则细节不了解。Spring MVC 参数绑定的大部分问题，都不是代码写错了，是默认机制不熟悉。第二种写法会被当成单个字符串，不会自动分割成数组，导致集合长度为1，数据异常。]]></description><category></category></item><item><title><![CDATA[SpringBoot 线程池踩坑实录：别再乱用 @Async 了，线上空指针、任务丢失全是坑]]></title><link>https://blog.csdn.net/zijieduke/article/details/165433489</link><guid>https://blog.csdn.net/zijieduke/article/details/165433489</guid><author>zijieduke</author><pubDate>Tue, 15 Sep 2026 09:03:28 +0800</pubDate><description><![CDATA[知道默认线程池有问题，很多人开始自定义线程池，写一个配置了自定义线程池，@Async 还是用的默认池。我之前就是卡在这个问题上，配置明明没问题，就是不生效。// 核心线程数：常驻线程 executor.setCorePoolSize(10);// 最大线程数：并发峰值上限 executor.setMaxPoolSize(50);// 队列容量：缓冲任务数 executor.setQueueCapacity(200);]]></description><category></category></item><item><title><![CDATA[我终于读懂了「代码整洁」的底层逻辑（不止是规范）]]></title><link>https://blog.csdn.net/zijieduke/article/details/165284504</link><guid>https://blog.csdn.net/zijieduke/article/details/165284504</guid><author>zijieduke</author><pubDate>Mon, 14 Sep 2026 09:22:31 +0800</pubDate><description><![CDATA[我从来不觉得代码整洁是「八股文」「形式主义」。每一次规范命名、每一次逻辑拆分、每一次优化嵌套、每一次精简冗余代码，都是在打磨自己的工程思维。不用追求一次性写出完美代码，没有人能做到。写完代码多复盘、迭代代码多优化、遗留代码慢慢重构。不用跟风学各种花哨的架构、冷门的技术，先把最基础的代码写干净、写规范、写易懂。能写出整洁、稳定、可维护代码的开发者，永远不缺竞争力。与所有普通开发者共勉。]]></description><category></category></item><item><title><![CDATA[踩坑记录：Vite+Vue3 本地运行正常，打包上线白屏、无报错、空白页]]></title><link>https://blog.csdn.net/zijieduke/article/details/165104516</link><guid>https://blog.csdn.net/zijieduke/article/details/165104516</guid><author>zijieduke</author><pubDate>Sat, 12 Sep 2026 11:08:04 +0800</pubDate><description><![CDATA[1. Vite 项目只要是非根目录部署，第一件事就是改 base 和路由 history 路径，不要等上线翻车再改。2. 白屏优先看资源路径、路由基础路径、Nginx 重写规则，90% 问题出在这里。3. 本地正常线上异常，基本都是环境差异、打包差异、路径差异，不是代码逻辑问题。4. 以后所有 Vue3 + Vite 项目，直接统一一套部署配置，不用每次踩坑复盘。希望这篇复盘能帮到正在白屏折磨的朋友，少踩坑，少加班。]]></description><category></category></item><item><title><![CDATA[二叉树递归解题：别死背遍历模板，抓住核心套路就够了]]></title><link>https://blog.csdn.net/zijieduke/article/details/164951892</link><guid>https://blog.csdn.net/zijieduke/article/details/164951892</guid><author>zijieduke</author><pubDate>Fri, 11 Sep 2026 08:51:47 +0800</pubDate><description><![CDATA[拆分、递归、合并。只要能分清自上而下和自下而上，LeetCode简单、中等二叉树题基本可以通杀。比起死记硬背模板，理解递归拆分的思想，才是刷题的捷径。]]></description><category></category></item><item><title><![CDATA[那些被我们过度设计的架构，最后都成了还不清的技术债]]></title><link>https://blog.csdn.net/zijieduke/article/details/164808027</link><guid>https://blog.csdn.net/zijieduke/article/details/164808027</guid><author>zijieduke</author><pubDate>Thu, 10 Sep 2026 09:45:17 +0800</pubDate><description><![CDATA[有时候，一个简单的CRUD加上一个本地缓存，就能完美解决的业务问题，非要套上事件驱动架构，最后搞得连加个字段都要改五六个文件。真正成熟的架构，往往都是“长”出来的，而不是“设计”出来的。就像那些经历了双十一考验的系统，最初可能也就是几台机器扛着，随着流量一点点涨上去，才在瓶颈处做针对性的优化。与其在早期为了虚无缥缈的未来焦虑，不如把眼前的业务逻辑写清楚，把接口契约定好，把测试覆盖率提上去。好的架构，不是看它用了多少复杂的组件，而是看它能不能在业务跑偏的时候，让你有足够的时间和精力去调整。]]></description><category></category></item><item><title><![CDATA[我盯着满屏的屎山代码，突然不想重构了]]></title><link>https://blog.csdn.net/zijieduke/article/details/164720039</link><guid>https://blog.csdn.net/zijieduke/article/details/164720039</guid><author>zijieduke</author><pubDate>Wed, 09 Sep 2026 10:01:21 +0800</pubDate><description><![CDATA[但回到现实里，大部分公司的项目，本质上就是个巨大的草台班子。说实话，以前刚毕业那会儿，看到这种代码，我恨不得连夜把原作者揪出来骂一顿，然后大刀阔斧地全删了重写。毕竟，技术再牛，线上挂了也是白搭。我灌了半杯凉透的咖啡，本来打算趁着这会儿没啥需求，把那个拖了半个月的订单模块重构一下。以前遇到Bug，第一反应是：这底层逻辑肯定有缺陷，我要从源码级排查，顺便优化一下架构。现在我的目标降级了：只要我离职的时候，接手的人不要半夜给我打电话骂娘，我就谢天谢地了。在屎山上雕花，雕着雕着，屎山塌了，背锅的还是你。]]></description><category></category></item><item><title><![CDATA[都在吹“读写分离“解千愁，来聊聊主从延迟的那些“脏数据“坑]]></title><link>https://blog.csdn.net/zijieduke/article/details/164575766</link><guid>https://blog.csdn.net/zijieduke/article/details/164575766</guid><author>zijieduke</author><pubDate>Tue, 08 Sep 2026 09:58:04 +0800</pubDate><description><![CDATA[现在的技术圈，尤其是博客和公众号，特别喜欢鼓吹"新架构"、"新中间件"。好像不用ShardingSphere分库分表就不叫高并发，不用读写分离就不叫微服务。但说实话，大部分中小公司的业务体量，单库单表完全够用。引入读写分离，多维护一套主从同步、多承担一份延迟风险，收益却未必对等。如果你每天DAU不到十万，QPS不到三位数，踏踏实实用单库，做好索引优化和SQL审核，比什么都强。等哪天业务量真的上来了，主库扛不住了，你再引入读写分离。那时候你踩过的坑、总结的经验，才是真金白银换来的。]]></description><category></category></item><item><title><![CDATA[写代码久了，慢慢读懂了程序员的温柔与固执]]></title><link>https://blog.csdn.net/zijieduke/article/details/164451373</link><guid>https://blog.csdn.net/zijieduke/article/details/164451373</guid><author>zijieduke</author><pubDate>Mon, 07 Sep 2026 09:56:41 +0800</pubDate><description><![CDATA[每天对着黑白控制台、密密麻麻的代码、不停跳动的日志，外人看枯燥又乏味，只有自己知道，编程这件事，藏着我们独有的处事方式和人生态度。哪怕代码行数多一点，注释详细一点，逻辑拆分清晰一点，后续接手的人能一眼看懂，线上出问题能快速定位，这就是好代码。参数一定要校验，接口一定要做降级，异常一定要捕获，日志一定要打全，重复代码一定要封装，无用代码一定要清理。迭代更新是程序的常态，也是成长的常态。熬夜排查的bug终于解决，卡顿的接口成功优化，臃肿的代码重构后变得简洁清晰，新的技术点顺利落地，需求完美上线无报错。]]></description><category></category></item><item><title><![CDATA[聊聊工作中踩过的 5 个 Java 线程池致命坑]]></title><link>https://blog.csdn.net/zijieduke/article/details/164360403</link><guid>https://blog.csdn.net/zijieduke/article/details/164360403</guid><author>zijieduke</author><pubDate>Fri, 04 Sep 2026 09:44:05 +0800</pubDate><description><![CDATA[写这篇文章的初衷，是发现很多开发者对线程池的理解只停留在面试层面，落地代码全是问题。结合线上踩坑经验，总结几条永久受用的开发原则：1.坚决杜绝 Executors 静态创建线程池，全部手动自定义参数；2. 所有线程池必须使用有界队列，杜绝 OOM 隐患；3. 拒绝策略按需适配核心/非核心业务，禁止无脑丢弃任务；4. 业务按优先级、场景做线程池隔离；5. 线程必须自定义命名，方便线上问题排查；6. 自定义线程池必须手动优雅关闭，适配服务上下线；]]></description><category></category></item><item><title><![CDATA[线上服务突然OOM，别急着加内存，先看看这几个隐蔽的内存泄漏点]]></title><link>https://blog.csdn.net/zijieduke/article/details/164324971</link><guid>https://blog.csdn.net/zijieduke/article/details/164324971</guid><author>zijieduke</author><pubDate>Thu, 03 Sep 2026 09:41:57 +0800</pubDate><description><![CDATA[内存泄漏这东西，代码review很难发现，因为从语法上看完全没问题。压测阶段把内存监控拉满，别只看QPS和RT线上告警配好，Young GC频率、老年代占比、Full GC次数，三个指标缺一不可代码规范里把ThreadLocal、静态集合、大对象查询这几条写死，CR的时候重点看别等半夜被电话叫醒才想起来排查，那时候你的脑子根本转不动。]]></description><category></category></item><item><title><![CDATA[技术债务像极了爱情，当时爽了，后面全得还]]></title><link>https://blog.csdn.net/zijieduke/article/details/164288946</link><guid>https://blog.csdn.net/zijieduke/article/details/164288946</guid><author>zijieduke</author><pubDate>Wed, 02 Sep 2026 09:30:44 +0800</pubDate><description><![CDATA[今天一个字段长度改一下，明天一个接口加个参数，后天发现性能扛不住了，回过头来看那段代码，就跟看自己十年前写的QQ空间日志一样，尴尬得脚趾抠地。那代码写得，怎么说呢，像极了刚毕业时候的我，满脑子都是"能跑就行"。你不仅要理解当时的业务逻辑，还要猜当时写代码的人是怎么想的，更绝望的是，那个人可能已经离职了，连个问的人都没有。命名要见名知意，方法要单一职责，注释要写为什么而不是是什么，最重要的，不要写你自己三个月后都看不懂的代码。算了，不感慨了，还有个定时任务的日志要查，今早用户反馈数据对不上。]]></description><category></category></item><item><title><![CDATA[那天，我的ThreadLocal内存泄漏了，还顺带把线上服务拖垮了]]></title><link>https://blog.csdn.net/zijieduke/article/details/164252777</link><guid>https://blog.csdn.net/zijieduke/article/details/164252777</guid><author>zijieduke</author><pubDate>Tue, 01 Sep 2026 09:47:18 +0800</pubDate><description><![CDATA[下午三点，正打算摸鱼搞杯咖啡，报警群炸了。服务A的GC频率飙到每分钟十几次，停顿时间平均1.2秒，接口超时率直接奔着30%就去了。赶紧拉了个dump，MAT打开一看，好家伙，相关的对象占用了将近4个G的堆内存，而且全是同一个自定义类的实例。第一反应是“谁特么没 remove？但转念一想，代码review了好几轮，拦截器里明明做了清理。再说了，这服务跑了快俩月了，之前一直稳如老狗，怎么偏偏今天炸了？后来翻了半天，发现是有人往里塞了一个超大对象——用户权限树，这玩意儿在某个特殊场景下膨胀到了几十MB。]]></description><category></category></item><item><title><![CDATA[代码之外，认知与选择才是长期护城河]]></title><link>https://blog.csdn.net/zijieduke/article/details/164205325</link><guid>https://blog.csdn.net/zijieduke/article/details/164205325</guid><author>zijieduke</author><pubDate>Mon, 31 Aug 2026 09:46:15 +0800</pubDate><description><![CDATA[入行开发这么多年，闲来无事翻看自己刚工作时写的烂代码，还有当初乱七八糟的学习笔记，真的感慨万千。读书的时候只会写一些简单的Demo，业务代码清一色无脑CRUD，完全不用考虑性能、兼容和拓展性。毕业后入职接手真实线上项目，一步步迭代业务、排查故障、参与架构优化，慢慢摸到了后端开发的门道。回头看这几年的成长，其实最大的收获，根本不是熟练掌握了多少热门框架，也不是啃完了多少底层源码。比起技术栈的堆砌，思维和认知的提升，才是拉开程序员差距的关键。。]]></description><category></category></item><item><title><![CDATA[记一次线上OOM的排查与修复：从怀疑人生到索然无味]]></title><link>https://blog.csdn.net/zijieduke/article/details/164163775</link><guid>https://blog.csdn.net/zijieduke/article/details/164163775</guid><author>zijieduke</author><pubDate>Sat, 29 Aug 2026 09:01:18 +0800</pubDate><description><![CDATA[事情发生在上周四下午，我刚泡好一杯速溶咖啡，准备摸鱼看看技术文章，群里突然炸了。“服务挂了，返回500。“订单接口超时，链路追踪全红。“大佬快看下，是不是又有人乱发请求？我一边心里mmp一边打开Grafana，好家伙，内存使用曲线跟过山车似的，直接冲破上限然后掉下来，GC频率飙升到每秒十几次。]]></description><category></category></item><item><title><![CDATA[那个让我加班到凌晨三点的Bug，最后居然是因为…]]></title><link>https://blog.csdn.net/zijieduke/article/details/164136798</link><guid>https://blog.csdn.net/zijieduke/article/details/164136798</guid><author>zijieduke</author><pubDate>Fri, 28 Aug 2026 09:01:26 +0800</pubDate><description><![CDATA[项目是去年从离职同事手里接过来的Spring Boot服务，代码风格怎么说呢，属于那种“能跑就行”的典范——一个Service里塞了四千多行，依赖链长得像北京早高峰的二环路。事务不提交，连接不释放，数据库连接池被慢慢耗尽，新请求进来拿不到连接就开始排队，RT就上去了。把SQL扒下来在本地执行了一遍，加索引，推上去，没变化。进一步看，这个Set里存的是全量的支付回调记录ID，没有设置过期时间，也没有做分片。又看了眼手机，运维老张八点多发了条“辛苦了兄弟，搞定了说一声”，后面跟了个抱拳的表情。]]></description><category></category></item><item><title><![CDATA[凌晨两点，我终于把那个bug修好了，然后开始怀疑人生]]></title><link>https://blog.csdn.net/zijieduke/article/details/164109655</link><guid>https://blog.csdn.net/zijieduke/article/details/164109655</guid><author>zijieduke</author><pubDate>Thu, 27 Aug 2026 09:40:58 +0800</pubDate><description><![CDATA[点进去看，其实人家 Spring Cloud、K8s、各种中间件都用得很溜了，但字里行间透着一股焦虑——觉得技术更新太快，学了就忘，忘了再学，永远在追赶，永远觉得自己落后。刚入行的时候觉得自己在造东西，一行一行地垒，像搭积木一样，看着一个系统从空文件夹变成能跑的东西，那种成就感是真实的。然后这些"临时"就变成了"永久"，永久变成了"历史包袱"，历史包袱变成了"别动它，能跑就行"。第二天我怀疑是连接池不够，调了 HikariCP 的参数，加了监控埋点，结果第二天一看——还是超时，频率没变。]]></description><category></category></item></channel></rss>