- 博客(368)
- 资源 (4)
- 收藏
- 关注
原创 Go 实现指数退避重试:context 取消、抖动 jitter 与什么时候别重试
这段代码能跑,但它在生产上有几处会直接变成事故:失败时定长 sleep 1 秒重试三次,意味着任何一个下游抖动都会让本服务的 goroutine 至少占住 3 秒;调用方传进来的context被完全无视,上游已经超时取消了,这里还在闷头重试;更糟的是三个重试请求几乎同时到达——因为等待时长一样,和别人的重试也对齐,对端刚缓过来又被一波同步的请求打趴下。这篇把退避重试写成一个能进生产的工具函数,把每个决策都说清楚。
2026-09-25 09:05:42
167
原创 React 原生拖拽排序实战:用 HTML5 Drag and Drop 重排列表,状态同步与放置指示线
列表能不能拖一下调顺序」是后台系统里极其常见的一个需求:任务优先级、看板列、菜单项排序。第一反应通常是,但那个库已经停止维护,是社区接手的分支,包体积也不小。而对于「一个垂直列表内重排」这种单纯场景,用浏览器原生的 HTML5 拖拽 API 手写一遍大约六十行,没有依赖、行为可控,还顺带把拖拽事件的模型学明白。这篇从头写一个可用的拖拽列表,重点放在真正会出问题的地方:状态什么时候更新、拖拽过程中为什么拖拽图像是半透明残影、指示线怎么算、以及输入框和滚动这两类边界。
2026-09-25 09:04:27
273
原创 Python dataclasses 进阶:default_factory、__post_init__ 校验与 frozen 不可变的三个坑
求值一次,所有实例共享同一个对象。传。
2026-09-25 09:03:17
158
原创 Spring Boot 3.2 RestClient 实战:替代 RestTemplate 调外部接口,超时、连接池与错误处理
调外部接口的代码,大多数人是从起步的。写了几年之后会发现两个问题:一是在 Spring 6 里已经进入维护模式,官方文档明确写「未来可能被弃用」,只修 bug 不加新功能;二是想换成响应式的WebClient,又得把整个技术栈往 Reactor 上靠,一个同步的 CRUD 服务为此引入并不划算。RestClient。同步、阻塞、链式 API,底层默认用 JDK 的HttpClient,但可以换成 Apache HttpClient 或 OkHttp 拿到连接池能力。
2026-09-25 09:02:10
259
1
原创 Go 实现指数退避重试:context 取消、抖动 jitter 与什么时候别重试
调外部接口偶尔超时、数据库瞬断,第一反应是「重试一下」。但里塞个的写法,会在故障恢复的瞬间把成千上万个客户端同时唤醒,再次把刚缓过来的服务打垮——这就是「惊群」(thundering herd)。这篇从朴素重试一路改到生产可用:指数退避 + 抖动 + context 取消 + 幂等性判断。
2026-09-20 09:06:28
211
原创 Python dataclasses 进阶:default_factory、__post_init__ 校验与 frozen 不可变的三个坑
这个字段,只是修改了它指向的列表内部,所以 frozen 拦不住。真正想要深层不可变,得让字段本身就是不可变类型,比如用。但真上手写复杂对象时,三个地方特别容易翻车:给字段设可变默认值直接报错、想校验参数不知道写哪、以为。——一个购物车加了商品,另一个购物车也跟着有了。dataclass 干脆在定义时就报错,逼你用。与默认值的组合在旧版本有过一些边界问题,用之前在你的 Python 版本上跑一下测试。就把它覆盖了,前功尽弃。想在初始化后做校验或派生字段,正确的钩子是。——dataclass 生成的。
2026-09-20 09:05:08
148
原创 Spring Boot 3.2 RestClient 实战:替代 RestTemplate 调外部接口,超时、连接池与错误处理
调外部接口这件事,用了十年,但它的 API 冗长、异常处理反人类,而WebClient又强制你引入 WebFlux 一整套响应式栈,同步场景下水土不服。RestClient——同步、链式、基于和WebClient一样的底层,却不用你写一行响应式代码。这篇手把手把它配到生产可用。
2026-09-20 09:03:57
229
原创 Prometheus 用 histogram_quantile 算接口 P99 延迟:选错 bucket、跨实例聚合与为什么 P99 比实际低
监控面板上接口 P99 写着 80ms,可用户那边明明有大量 2 秒的慢请求。你去翻 histogram,发现最大的桶就是le="0.1",再往上全落进+Inf——P99 被死死顶在 100ms 出不来。这不是 Prometheus 算错,是 bucket 划分和聚合方式用错了。这篇把从头到尾捋清楚。
2026-09-20 09:02:32
166
原创 Go atomic.Pointer 实战:配置热更新无锁读、写时复制与和 atomic.Value 的取舍
服务跑着跑着要改配置:限流阈值、下游地址、开关灰度。重启大法当然能解决,但谁也不想为了改一个数字重启一遍集群。热更新的核心诉求其实很朴素——。新手第一反应是加。能用,但读多写少场景下,读锁本身的原子操作也是开销,QPS 高了会成瓶颈。这篇讲更优雅的做法:用 Go 1.19 引入的 atomic.Pointer[T]做无锁读、写时复制(copy-on-write)整体替换,以及它和老的到底怎么选。
2026-09-19 09:06:33
143
原创 Kubernetes Pod Security Admission 实战:baseline/restricted 级别与从废弃 PSP 平滑迁移
如果你还在集群里用 PodSecurityPolicy(PSP)做 Pod 安全管控,坏消息是:PSP 在 1.21 弃用、。升级集群那天,你所有依赖 PSP 的准入规则会静默失效,一堆本该被拦下的高危 Pod(特权容器、挂 hostPath、以 root 跑)会畅通无阻地跑起来。,从 1.25 起 GA、默认启用,不用装任何东西,给 Namespace 打几个 label 就能拦。这篇讲清三个级别怎么选、怎么平滑迁移、以及最容易被 restricted 卡住的那几个字段怎么改。
2026-09-19 09:05:09
173
原创 React 文件上传实战:预览 URL 回收、多文件逐个进度与拖拽放置区踩坑
文件上传看着简单,一个而已,可真写起来到处是坑:预览图内存越用越多、选同一个文件第二次不触发、多文件上传进度只能看总量、拖拽区域松手时浏览器直接把文件当新页面打开了。这篇把这些坑一个个填平,最后给你一个能直接抄进项目的上传组件。
2026-09-19 09:03:40
221
原创 Spring Boot 优雅停机实战:等在途请求处理完再退出,配合 K8s preStop 别丢请求
线上滚动发布时你有没有遇到过这种诡异现象:代码没改坏,监控却在每次发版的那几秒钟准时冒出一小撮 502 / 连接重置,业务方追过来问「刚才下单失败了几单」。你翻日志,发现请求打到了一个正在关闭的实例,进程已经把 HTTP 线程池干掉了,可这个请求才处理到一半。这不是偶发抖动,而是**默认的「立即停机」**在作祟。这篇文章手把手把它改成优雅停机,并讲清楚为什么光配 Spring Boot 还不够,得和 Kubernetes 的 preStop 配合才真正不丢请求。
2026-09-19 09:02:22
128
原创 Python sqlite3 实战:事务提交、参数化防注入、WAL 并发与 row_factory 取字典
Python 标准库自带sqlite3,不用装任何东西就能有一个完整的关系型数据库,做本地缓存、小工具、原型再合适不过。但正因为「拿来就用」,很多人踩了一堆坑:写了数据重启后没了、字符串拼 SQL 被注入、多进程一读一写就、查出来的行还得靠下标row[0]猜列。这篇把这几个高频问题一次讲透。
2026-09-18 09:06:59
141
原创 Nginx 配置 HTTPS + HTTP/2 实战:证书链补全、OCSP stapling、HSTS 与 SSL Labs A+ 调优
给站点配好 HTTPS,浏览器地址栏出现小锁头,很多人就以为搞定了。但拿去 SSL Labs(ssllabs.com/ssltest)一测,评分可能只有 B——证书链不全导致部分客户端报错、支持了早已被攻破的 TLS 1.0、握手慢得肉眼可见。这篇按「先能用、再安全、后提速」的顺序,把一份 Nginx HTTPS 配置从「有锁头」调到 SSL Labs A+,每一项都讲清楚为什么。
2026-09-18 09:05:29
189
原创 Java ThreadLocal 一进线程池就丢了:上下文透传的坑与三种正确姿势
很多项目用存「当前请求的用户 id」「traceId」「租户信息」这类上下文,在同一个线程里随处get()就能拿到,很方便。但只要业务里出现一次,你就会发现:子任务里拿到的是null,或者更诡异——。日志里 traceId 串了、权限校验用错了租户,排查半天摸不着头脑。这篇讲清楚为什么会丢、为什么会串,以及三种从简单到工业级的修法。
2026-09-18 09:03:59
167
原创 React 原生拖拽排序实战:用 HTML5 Drag and Drop 重排列表,状态同步与放置指示线
想给一个列表加「拖拽排序」,很多人第一反应是装react-dnd或dnd-kit。但如果只是重排一个几十项的列表,引入一整个库既加包体又要学一套 API。其实浏览器原生的 HTML5 Drag and Drop 就够用了,难点不在 API 本身,而在——拖起来能动、松手数据却没变,或者放到哪里没有视觉提示,用户完全不知道会插到哪。这篇就把这两个坑填平。
2026-09-18 09:02:29
206
原创 Python abc 抽象基类实战:用 ABC + abstractmethod 强制子类实现接口,以及和 Protocol 怎么选
用abc改写,让「没实现」在实例化时......# 仍然忘了实现 load现在直接抛TypeError,明确告诉你「抽象方法 load 没实现」。s = MemoryStorage() # OK,两个抽象方法都实现了继承ABC(或用)让这个类具备「抽象类」能力。用装饰的方法是「抽象方法」,子类必须全部实现才能实例化。Storage()会直接报同样的TypeError。
2026-09-17 09:11:27
172
原创 Nginx 限流实战:limit_req 漏桶、limit_conn 连接数与 burst/nodelay 到底怎么配
默认限流拒绝返回 503。http {# 被限流时返回 429 而不是 503server {
2026-09-17 09:09:53
174
原创 Java 文本块实战:多行 JSON/SQL 告别满屏转义,尾部空格与缩进剥离的坑
在 Java 里写一段多行 SQL 或者一坨 JSON 字符串,是很多人心里的痛。传统写法满屏都是\n\"和这段代码有几个明显的问题:每个双引号都要转义,每行末尾要手动拼\n,字符串边界靠连接。字段一多,漏个逗号、漏个引号就是运行时才发现的 bug。Java 15 正式落地的**文本块(Text Block)**就是来治这个病的。这篇讲清楚它怎么用、缩进是怎么被剥离的,以及几个真会踩的坑。
2026-09-17 09:08:18
93
原创 Go context.AfterFunc 实战(Go 1.21):context 一取消就自动跑清理,告别手写 goroutine 监听 Done
写 Go 服务时,你大概率写过这样一段代码:开一个 goroutine 死等ctx.Done(),一旦 context 被取消就去做收尾——关连接、退订阅、删临时文件。写多了你会发现这套模板到处复制粘贴,还容易漏掉细节:context 早就取消了你才注册怎么办?任务提前正常结束了,那个监听 goroutine 还挂着不就泄漏了?Go 1.21 加了个专门收拾这类场景。这篇就把它讲透:能干什么、怎么用、stop的返回值到底代表什么,以及三个真实会踩的坑。
2026-09-17 09:05:08
219
原创 Java Arrays.asList 与 List.of 踩坑:add 抛异常、基本类型数组变一个元素、视图联动改原数组
和是 Java 里把一堆元素快速塞进 List 的两个「一行党」写法,天天有人用。但它们返回的 List 和你出来的完全不是一回事,踩起坑来还特别隐蔽——代码编译通过、单测跑一半也正常,直到线上某个分支走到add,一个把请求打挂。这篇把这两个方法最常见的三个坑一次讲透,并给出正确写法。
2026-09-16 09:07:34
258
原创 Go 子 goroutine 里 panic 会直接崩溃整个程序:为什么 main 的 recover 兜不住,每个协程都要自己 defer recover
线上跑得好好的 Go 服务,突然整个进程挂了,日志里就一行panic: ...加一堆栈,重启后又正常。查了半天发现:是某个后台 goroutine 里一个空指针解引用 panic 了。奇怪的是,main函数外面明明包了,为什么没兜住?这篇把原理、复现和正确兜底姿势讲清楚。
2026-09-16 09:06:14
189
原创 Kubernetes 用 kubectl port-forward 和 proxy 调试集群内服务:两者区别、断连自动重连与为什么别用在生产
线上排查时经常遇到这种局面:一个服务只在集群内部通过 ClusterIP 暴露,没有 Ingress、也没配 NodePort,你想从本地电脑连上去看看它到底通不通、返回什么。开个临时 LoadBalancer 太重,让运维加条 Ingress 规则又太慢。这时候和就是最顺手的两把「隧道」工具。但很多人用起来一头雾水:两个命令都能访问集群内部,到底有什么区别?为什么 port-forward 跑一会儿就断?为什么有人说它不能用在生产?这篇一次讲透。
2026-09-16 09:04:24
141
原创 React 全选复选框的 indeterminate 半选状态实战:受控写法、useRef 设置与树形级联勾选
做后台管理系统时,几乎都会遇到「表头一个全选框,下面一排行选择框」的需求。看起来简单,真写起来会卡在一个地方:当只勾选了部分行时,全选框应该显示成「半选」那个横杠状态(不是打勾,也不是空),用户一看就知道「选了但没选全」。很多人第一反应是给全选框加个,结果发现根本没有那条横杠。因为这个东西,你没法通过 JSX 的属性直接写上去。这篇就把这个坑连同树形级联一起讲清楚。
2026-09-16 09:02:54
172
原创 Docker 网络实战:bridge/host/none/自定义网络、容器互通与端口映射踩坑
自己建一个 bridge 网络,把相关容器都接上去。Docker 会在自定义网络里提供内置 DNS# 1. 建一个自定义网络# 2. 两个容器都接到这个网络# 3. web 里直接用容器名 db 连数据库,Docker 自动解析成 db 的当前 IPdocker exec -it web ping db # 通!现在 web 容器里连数据库就写db:3306,不用管 IP 是多少、重建后变不变,Docker DNS 自动跟踪。这是多容器互通的标准做法。
2026-09-15 09:08:35
137
原创 Python 用 zipfile 读写压缩包实战:流式解压不爆内存、防 Zip Slip 路径穿越攻击
处理用户上传的 zip、批量打包导出文件、解压第三方数据包——zipfile是绕不开的标准库。但两个坑几乎人人踩过:一个是read()一把把整个大文件读进内存,几百 MB 的压缩项直接把服务干 OOM;另一个更危险,直接用extractall解压不可信的 zip,一个构造好的压缩包能把文件写到/etc/或者你的项目源码目录里,这就是 Zip Slip 路径穿越漏洞。这篇把zipfile的正确姿势讲清楚:怎么读、怎么写、怎么流式处理不爆内存,以及解压不可信压缩包时必须做的安全防护。
2026-09-15 09:07:02
135
原创 Java 正则实战:Pattern 预编译复用、命名分组、replaceAll 回调与灾难性回溯
一段校验手机号的代码,压测时 CPU 突然飙到 100%,线程栈全卡在上。查了半天,元凶是一个看起来人畜无害的正则,遇到某个特定输入后陷入了「灾难性回溯」,单次匹配跑了几十秒。正则用不好,轻则性能白白浪费,重则被一个精心构造的字符串打到服务不可用(ReDoS)。这篇不讲正则语法基础,只讲 Java 里用PatternMatcher时那些真正影响性能和正确性的点:为什么必须预编译、命名分组怎么让代码可读、replaceAll如何做动态替换,以及灾难性回溯的成因与规避。
2026-09-15 09:05:22
168
原创 用 Zustand 做 React 全局状态管理:告别 Context 重渲染,3 个实战模式与持久化
组件层级一深,状态就开始满天飞。一个登录用户信息,从顶层App一路 props 传到七层之下的头像组件,中间六层压根用不上它,只是「过路」。你想到用 Context 收口,结果发现另一个坑:Context 里随便一个字段变了,所有订阅这个 Context 的组件——哪怕它只读了另一个不相干的字段——全部跟着重渲染。列表一长,输入框都开始卡。Redux 能解决重渲染,但要写 action、reducer、dispatch、connect,一个简单的计数器都得铺三个文件。
2026-09-15 09:03:21
219
原创 Python 的 __call__ 实战:让实例像函数一样被调用,做带状态计数器、缓存器与可配置策略
obj(...)触发的是类的__call__,不是实例属性里那个同名函数。给实例动态塞一个是不生效class A:passa = A()a.__call__ = lambda: "hi" # 塞到实例上# a() # TypeError: 'A' object is not callable —— 特殊方法只从类上查找__call____len__这些都只在类型上查找,不看实例字典。要让实例可调用,__call__必须定义在类里。
2026-09-14 09:10:47
162
原创 Java Jackson 实战:@JsonProperty、忽略 null、LocalDateTime 格式化与循环引用炸栈的解法
只要你写 Spring Boot,Jackson 就在背后默默给你做 JSON 序列化。平时没感觉,直到某天接口返回的时间变成一串,或者返回体里塞满一堆null字段,或者双向关联的两个实体互相引用直接把栈撑爆报。这些都是 Jackson 的经典坑。这篇把最高频的四类问题一次讲清,给出能直接抄的配置。
2026-09-14 09:09:34
185
原创 Go 1.22 标准库路由增强:net/http ServeMux 支持方法匹配与路径参数,还要不要 gin/chi
在 Go 1.22 之前,只要项目稍微上点规模,几乎没人直接用net/http的ServeMux。原因很实际:它不认 HTTP 方法(GET/POST 都进同一个 handler,你得自己在里面),也不支持路径参数(这种得自己切字符串)。于是大家一上来就或者 chi、gorilla/mux。Go 1.22 把这两个最痛的缺口补上了。这篇带你把新语法过一遍,并且给个明确结论:什么项目现在可以扔掉第三方路由,什么项目还是老实用框架。
2026-09-14 09:08:19
183
原创 Next.js 15 after() 实战:响应返回后再跑日志、埋点与发通知,不拖慢接口
你大概率写过这样的代码:用户提交了一个表单,你先写数据库,然后顺手记一条审计日志、发个埋点、给管理员推条通知,最后才把结果返回给用户。功能没问题,但用户明明数据已经存好了,却要多等那两三百毫秒——因为埋点接口慢、通知服务偶尔抽风,全算进了这次请求的耗时里。。Next.js 15 正式把after()提上来解决这个问题:让你注册一段「响应发出去之后再执行」的逻辑。这篇就把它讲透。
2026-09-14 09:05:20
52
原创 Go 用 json.Decoder 流式解析大 JSON:边读边处理不爆内存
线上有个日志导出接口,返回一个包含几十万条记录的 JSON 数组,几百 MB。你用一读,内存直接飙上去,容器 OOMKilled。Unmarshal要求先把JSON 读进内存的[]byte,再反序列化成一个完整的大切片——数据多大,内存就要多大,峰值还翻倍。解法是的流式解析:边从io.Reader读,边逐个元素解码处理,处理完就丢,内存只留当前这一条。这篇讲清Decoder的三种用法,以及大文件场景怎么用Token()逐元素解析。
2026-09-13 09:06:22
185
原创 Nginx location 匹配优先级实战:=、^~、正则谁先命中,附 try_files 兜底
而正则的优先级默认高于普通前缀,除非普通前缀用了。
2026-09-13 09:05:06
221
原创 Java Collectors.groupingBy 进阶:多级分组、下游收集器与统计聚合一次搞定
把订单按城市分组」——一行就能做。但真实需求往往是:「按城市分组,每组再按月份分组,统计每个月的总金额」。这时候如果你还在groupingBy之后套一堆forEach手动累加,代码就会迅速失控。groupingBy的威力全在它的——下游收集器(downstream collector)。搞懂它,一次流式操作就能做完多级分组 + 聚合统计,不用中间变量,也不用手写循环。这篇把最常用也最容易踩坑的几种组合讲透。
2026-09-13 09:03:50
256
原创 Python 多级排序实战:混合升降序、None 值与 itemgetter 提速
有一批订单数据要排序:先按客户等级从高到低,等级相同再按下单金额从高到低,金额也相同就按下单时间从早到晚。听上去简单,但真上手你会发现 根本满足不了——因为「时间」那一级是升序,其它两级是降序, 是全局开关,没法只对某一级生效。这篇就把多级排序里最容易踩的几个坑一次讲清:多字段怎么排、升降序怎么混、 值怎么办、以及为什么 比 又快又清楚。初学者常见的第一反应是排两次:这段代码其实是对的,但很多人不知道它为什么对,也不知道它的边界。它能工作,靠的是 Python 排序的一个关键性质:稳定排序(stab
2026-09-13 09:02:41
153
原创 React 用原生 Constraint Validation API 做表单校验:不装库优雅提示必填、格式与自定义规则
—四步就能不装库做出体面的表单校验。
2026-09-12 09:07:02
119
原创 Python secrets 模块实战:安全生成 token/验证码/密码,以及为什么别再用 random
线上出过一个真实的安全事故:某个系统用生成 6 位短信验证码,攻击者拿几百条历史验证码喂进去,推算出random的内部状态,之后能提前算出下一个验证码,直接绕过短信登录。根因就一句话:random。凡是「猜中了会出事」的场景——token、密码、验证码、重置链接——都必须用secrets。这篇讲清楚secrets怎么用、每个函数对应什么真实场景,以及random到底为什么不能用。
2026-09-12 09:05:30
206
原创 Go 的 iota 实战:一个标识符生成枚举、位掩码与跳值常量
写 Go 定义一组状态码,很多人会这么来:数字一个个手写,加一个新状态就得在中间插值、后面全部改。更糟的是哪天有人把 误写成 2 和 撞了,编译器一声不吭。Go 早就给了你一个专门干这事的工具:。但 的行为有几个「反直觉」的点,用不好会生成一串错误常量。这篇把它彻底讲透。 是一个预声明标识符,只在 块里有意义。它的值等于「当前常量声明所在的行相对于 const 块第一行的偏移」,从 0 开始,每换一行 +1。关键点:iota 数的是「行」,不是「用到 iota 的次数」。这是第一个容易搞错的地方
2026-09-12 09:04:02
68
原创 Java NIO ByteBuffer 实战:flip/clear/compact 三个绕晕人的方法与 position/limit 心智模型
第一次用ByteBuffer读网络数据的人,几乎都会栽在同一个地方:明明把数据put进去了,get出来却是一堆 0;或者从Channel读完准备解析,结果返回 0,什么都没读到。翻 API 文档看到flip()clear()compact()三个方法,注释写得云里雾里,越看越懵。问题的根源不在这三个方法,而在于你没建立起positionlimitcapacity这三个指针的心智模型。把这个模型搞清楚,三个方法就是它的自然推论,再也不用死记。
2026-09-12 09:02:34
236
Vue3快速上手(Vue3学习笔记)
2022-07-11
DICOM 中文版介绍,分为三部分三个PDF文件
2023-11-25
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅