HttpAsyncClient中Keep-Alive连接复用原理与排坑指南
Keep-Alive 在 HttpAsyncClient 里的实现一直是很多同学用异步 HTTP 客户端时最容易绕晕的点。同步的 HttpClient 连接复用好理解请求结束连接放回池子就完事但到了异步场景连接是 NIO 事件驱动的、归还时机是回调里决定的、复用决策还牵扯到响应体有没有读完稍不留神连接就“复而不用”甚至“直接泄漏”。这篇不聊虚的直接拆 HttpAsyncClient 的连接复用链路顺带把连接池参数、过期清理、线上排坑的方法都讲透。1. Keep-Alive 连接复用的完整链路从创建到归还1.1 连接池按“目标路由”分桶是关键HttpAsyncClient 连接复用的最小粒度不是“任意连接”而是“到同一个目标的连接”。这个目标在内部用 HttpRoute 表示由 scheme、host、port 三个要素组成。连接池并不是一个大池子而是一组按 route 分桶的小队列访问http://a.com只会从 a.com 的桶里拿连接不会去用 b.com 的连接。这个设计的理由很直接TCP 连接是端到端的一条连接到 b.com 的连接物理上不可能发起到 a.com 的请求复用也没有意义。schemehttp/https决定是否走 TLShost 决定目标地址port 决定目标端口这样分桶之后连接池就能很自然地对每个目标做独立控制。线上经常遇到“一个服务连接被打满、其他服务完全空闲”的情况本质就是两个 route 的桶一满一闲而不是整个池子的问题。HttpAsyncClient 的 PoolingAsyncClientConnectionManager 内部维护着这个分桶结构每个桶有自己的空闲队列、租约队列和等待队列锁的粒度也控制到 route 级别避免全局锁竞争拖垮高并发场景。1.2 连接生命周期里最关键的是“归还”决策一条连接在 HttpAsyncClient 里大致走五个阶段创建、租借、使用、归还、空闲回收。前四个都在请求链路内完成最后一个由后台清理逻辑负责。创建阶段连接池发现目标 route 没有可用连接且未达到 maxPerRoute 上限时异步发起 TCP 连接和 TLS 握手。注意这里的“异步发起”不是同步阻塞的 connect而是通过事件驱动的方式注册 connect 回调连接建立完成后才会进入可用状态。租借阶段请求执行时向连接池申请一条连接。如果桶里有空闲连接直接复用返回如果没有并且还没到上限就现场建一条如果已经到上限请求会进入 pending 队列等别人归还。使用阶段请求发出去、响应读回来这个阶段连接被某线程独占其他请求不能碰。归还阶段这是连接复用是否生效的真正分水岭。请求结束后连接管理器要判断这条连接是否还能回池子复用。判断标准就是 HTTP 协议语义如果响应读取过程中发生了连接异常、读到 EOF、或者服务端明确返回Connection: close这条连接的物理状态已经不可靠必须直接 close 掉不能放回池里只有完整读完响应、双方都暗示可以持久连接时连接才被标记为可复用归还到空闲队列。这个判断逻辑由 ConnectionReuseStrategy 承担HttpAsyncClient 默认使用 DefaultConnectionReuseStrategy。1.3 异步模型下复用一个连接需要多长的“等待”异步客户端最迷惑的一点是连接到底什么时候回池同步代码里方法返回连接自动归还异步场景里请求发起后方法立即返回连接归还发生在回调执行完、响应处理完之后。HttpAsyncClient 的 execute 方法接受 FutureCallbackcompleted 回调里拿到 HttpResponse。这个 response 对象背后绑定的就是那条正在使用中的连接。只有你处理完响应体消费完 inputStream 或者显式 close连接才会被通知放回池子。如果回调里拿到 response 后既没读实体也没 close连接被长期占用下一个请求就只能走新建连接Keep-Alive 形同虚设。这一点在异步模型里比同步更容易踩坑。同步代码几乎每个教程都教你把 response 放在 try-with-resources 里关闭异步回调里的关闭却经常被忽略。我曾在一个项目中排查过一段时间内 ESTABLISHED 连接数直线上升、pending 队列不断堆积的情况最后定位到就是回调里忘记关闭 response导致连接租出去就不还直到触发连接池上限。2. 决定连接复用的核心组件与参数配置2.1 ConnectionReuseStrategy哪些响应允许回到池里刚才说过归还决策由 ConnectionReuseStrategy 做这里展开讲它的判断逻辑。给一条连接做健康检查总结下来是三步协议版本是否为 HTTP/1.1 或显式支持 keep-alive响应中是否出现Connection: close响应实体是否被完整消费前两步是“能不能复用”的语义判断第三步是“物理上还能不能用”的完整性判断。如果服务端返回Connection: close策略直接认为这条连接不能再复用。即使你消费完实体连接管理器也会在归还时选择 close。如果响应实体没有完整读完连接上还残留未读的响应数据那这条连接无论如何不能再给下一个请求用否则下一个请求读到的就是残留字节协议状态会完全错乱。Connection: keep-alive和Connection: close的处理在异步里还有一个特殊性连接池复用的是 TCP 连接本身而 HTTP/1.1 默认就是持久连接所以请求头即使不显式写 keep-aliveHttpAsyncClient 也会默认可复用。只有显式带了 close 或者服务端返回 close复用才会被切断。这也是很多人以为需要手动加 Header 让连接复用其实完全没必要。2.2 TTL、空闲回收、ValidateAfterInactivity 三兄弟服务端不会让你一条连接永远占着接入层软件普遍会设置空闲超时通常 60 秒到 120 秒。如果客户端不知情还在复用一条已经被服务端关闭的连接下一次请求就会偶发失败。所以 HttpAsyncClient 提供了三个配套机制ConnectionTimeToLive连接的绝对存活时间到期后即使空闲连接池也会废弃EvictIdleConnections定时清理空闲超过指定时长的连接ValidateAfterInactivity租借连接时发现连接空闲超过这个阈值先校验再使用这三个参数解决的是不同维度的问题。TTL 解决的是“连接活得太久中间经过的网络设备早已不认它”的问题空闲清理解决的是“服务端已经超时断开客户端空闲列表里却还躺着死连接”的问题ValidateAfterInactivity 解决的是“取出一条连接时它可能已经断了要不要先验证一下”的问题。构建客户端时可以这样设置CloseableHttpAsyncClient client HttpAsyncClients.custom() .evictExpiredConnections() .evictIdleConnections(30, TimeUnit.SECONDS) .setConnectionTimeToLive(120, TimeUnit.SECONDS) .build();实际使用中这三个要配合着设不要只开一个。TTL 设太短会导致连接反复重建失去复用意义空闲清理设太频繁会额外消耗扫描开销。比较稳的组合是TTL 略大于服务端空闲超时比如服务端 60 秒客户端 TTL 120 秒空闲连接清理每 30 秒扫一次ValidateAfterInactivity 设 2 秒左右。这样连接既不会长期闲置在客户端也不会活成一个“僵尸连接”。2.3 maxTotal / maxPerRoute别拍脑袋设要有推导很多同学用连接池喜欢随手设一个超大 maxTotal结果性能没上去服务端先被打挂。连接池的容量本质上由并发请求数、单请求占用连接时长、以及目标服务的容量共同决定。连接池有两个维度maxTotal 是全局连接总数上限defaultMaxPerRoute 是每个 route 的配额也就是每个目标主机最多多少条连接两者不等价。比如 maxTotal 设 200defaultMaxPerRoute 设 50那就最多和 4 个不同目标保持连接第五个目标永远等可用连接。这个细节特别容易在生产环境里栽跟头明明 maxTotal 很大新接了一个下游服务请求却大量 pending。一个简单的估算逻辑目标服务的 QPS 是 1000单请求平均耗时 80ms那同一时刻在途请求大约是1000 * 0.08 80条maxPerRoute 可以按这个数的 1.5 到 2 倍设置预留峰值波动空间。如果走到 HTTS 并且有 TLS 握手成本每条连接复用的价值更高同理 maxPerRoute 不宜过小。但注意maxPerRoute 不是越大越好目标服务端也有自己的连接数上限和线程池处理能力设太大只会把压力全部引到下游。3. 实操验证写个小 Demo 观察 keep-alive 是否生效3.1 依赖和启动代码先贴出最小可运行的项目依赖基于 httpasyncclient 4.1.xdependency groupIdorg.apache.httpcomponents/groupId artifactIdhttpasyncclient/artifactId version4.1.5/version /dependency然后写一个能通过连接池统计信息观察复用的 Demo。为了能看到连接池内部状态建议自己创建 PoolingAsyncClientConnectionManager 传给 Builder而不是用 HttpAsyncClients.createDefault()PoolingAsyncClientConnectionManager connManager new PoolingAsyncClientConnectionManager(); connManager.setMaxTotal(50); connManager.setDefaultMaxPerRoute(10); CloseableHttpAsyncClient client HttpAsyncClients.custom() .setConnectionManager(connManager) .evictExpiredConnections() .evictIdleConnections(30, TimeUnit.SECONDS) .setConnectionTimeToLive(120, TimeUnit.SECONDS) .build(); client.start(); for (int i 0; i 5; i) { HttpGet get new HttpGet(https://api.example.com/data); client.execute(get, new FutureCallbackHttpResponse() { Override public void completed(HttpResponse response) { try { // 必须消费实体连接才能被标记为可复用 String body EntityUtils.toString(response.getEntity()); if (body.length() 0) { System.out.println(body ok); } } catch (IOException e) { e.printStackTrace(); } finally { try { response.close(); } catch (IOException ignored) { } } } Override public void failed(Exception ex) { ex.printStackTrace(); } Override public void cancelled() { System.out.println(cancelled); } }); PoolStats stats connManager.getTotalStats(); System.out.println(leased stats.getLeased() , available stats.getAvailable() , pending stats.getPending() , max stats.getMax()); Thread.sleep(1000); } client.close();这段代码连续发 5 个请求到同一个目标。如果一切正常你会看到 first 请求之后 available 变为 1后续请求的租借过程直接复用了这条 available 连接leased 始终只有 1而不是反复从 0 涨到 1。3.2 从 PoolStats 判断连接是否被复用PoolStats 四个字段分别代表leased当前被租走正在使用的连接数available空闲可用、随时可以复用的连接数pending等待可用连接的排队请求数max上限判断复用的技巧很简单如果每个请求完成后 available 都归 0说明连接没用完就被关了要检查是不是响应体没消费、服务端返回了 Connection: close、或者连接过期清理太快。如果 available 稳定在 1 以上说明连接真的被放回池子并能被下一个请求复用。还可以按 route 看单目标的状态便于判断多个下游哪一个连接紧张HttpHost target new HttpHost(api.example.com, 443, https); PoolStats routeStats connManager.getStats(target);3.3 开启 wire 日志和抓包确认连接池统计是内部视角要确认协议层面的 keep-alive还得开 wire 日志。HttpClient 的 wire 日志会打印原始 HTTP 头和部分报文配置 logback 或 log4j 时把org.apache.http.wire调到 DEBUG# 日志配置示例 logger nameorg.apache.http.wire levelDEBUG打开后能明确看到请求头带有Connection: keep-aliveHTTP/1.1 即使不写默认也是持久连接响应头如果带回Connection: keep-alive说明服务端也认可复用。如果看到响应头是Connection: close那就别指望连接复用了直接从服务端配置入手。之外也可以用 tcpdump 确认 TCP 层行为。连续发两个请求观察客户端到服务端的 TCP 流如果只发生一次三次握手说明第二个请求复用了第一个请求的连接如果出现两次三次握手说明连接没有被复用。抓包时注意不要开 HTTP/2Demo 用的是 HTTP/1.1抓起来很直观。4. 线上问题的定位与处理实录4.1 偶发 Connection reset服务端先关了客户端还在用最经典的线上故障服务稳了一个月某天开始每日偶发几条 Connection reset重试一下又好了。这个问题的成因通常就是服务端空闲超时提前关掉了连接客户端不知道还在复用。接入层常见的空闲超时配置在 60 秒左右。假设客户端 TTL 设的是永久、空闲清理也没有启用客户端连接池里躺着一条空闲了 70 秒的连接下一个请求来直接把它租出去。此时服务端那边的 socket 早已关闭客户端一写数据TCP 就会收到 RST表现就是 Connection reset。这种问题的处理顺序很明确先确认服务端的 keepalive_timeout 和客户端的 TTL、空闲清理时间是否匹配客户端 TTL 建议比服务端空闲超时大 20% 到 50%确保连接不是“主动断给服务端看”开启 evictIdleConnections让池子里不要残留长时间休眠的连接适当设置 ValidateAfterInactivity取连接时发现空闲过久就先验证换季变天的故障点其实是这个“空闲连接已经失效但池子不知道”。把 idle 清理和 TTL 打开后这类偶发 reset 会大幅减少但不会完全消失。极端情况下还得在业务侧加一层重试对幂等请求做一次自动重试就能兜底。4.2 连接池被打满请求大量 pending另一个高频故障是 pending 暴涨。现象下游服务 QPS 并不高但客户端侧大量请求在等待连接线程池后面堆了成百上千的任务。这种场景下先看 PoolStats 的 leased 是否长期维持在 max。如果 leased 贴近 max基本可以断定是连接泄漏或响应处理太慢连接被长时间占用。排查顺序检查回调里 response 是否关闭检查响应实体是否被完整消费如果做的是流式转发确保最终 read 到 EOF检查下游服务的响应时间是否有慢查询连接被慢响应占住检查 maxPerRoute 是否设置得当特别是新增了下游域名时有没有对应扩容常见误区是直接调大 maxTotal。如果问题是连接泄漏调大只是延长爆炸时间如果问题是慢响应占连接调大连接池把压力转移到下游 TPS 上也不一定健康。合理做法是先把响应关闭和实体消费检查干净再根据单请求耗时、目标 QPS 重新估算容量。4.3 定位手段日志、统计与 netstat 三板斧线上排查 HttpAsyncClient 连接问题我通常按“一看日志二看统计三看握手”的顺序来一看日志。开启 org.apache.http 的 INFO 或 DEBUG 日志重点看有没有Connection closed、Connection discarded之类的线索。同时看服务端访问日志如果同一个客户端 IP 反复出现新 TCP 连接那基本说明客户端在做连接重建而不是复用。二看统计。在客户端定时打印 PoolStats把 leased、available、pending 做成监控曲线。连接数曲线和 QPS 曲线对照能很快看出是否存在连接数不随请求结束回落的异常形态。三看握手。在客户端或服务端抓包统计单位时间内 TCP 握手次数。Keep-Alive 正常情况下 1 个请求和 1000 个请求的握手次数应该都差不多只取决于连接池里有多少条稳定连接如果握手次数跟着请求量线性增长复用一定没有生效。实测中三板斧用完90% 的问题都能定位到原因。剩下 10% 多数是对端网络设备、防火墙空闲超时这类外部因素这些要靠 TTL 和重试来兜。5. 快速自查表症状、原因与处理建议现象可能原因排查方向处理建议available 始终为 0响应体未消费或 response 未 close检查 FutureCallback 中实体处理消费完 Entity 或显式 close response偶发 Connection reset服务端空闲超时先断开连接与对端确认 keepalive_timeout设置 TTL、开启空闲清理和连接校验连接数不断上涨连接泄漏租借后未归还打印 PoolStats 看 leased 曲线检查所有异常路径下的 closepending 大量堆积maxPerRoute 过小或连接占用过久统计单请求耗时、在途请求数按 RT 和 QPS 重算连接池容量新增下游域名后 pending 暴涨只调大了 maxTotal 没调 defaultMaxPerRoute检查 route 级统计通过 setMaxPerRoute 单独扩容抓包发现反复三次握手连接根本没复用开启 wire 日志看 Connection 头确认没有显式 close检查代理和网关行为这张表是我在实际项目中沉淀下来的“快速排障目录”每次遇到 HttpAsyncClient 问题先对照症状基本上几分钟内就能锁定大概方向后面再细查日志和代码就有据可循。6. 使用 HttpAsyncClient 后我养成的三个习惯第一所有异步回调里的 response 必须放进 finally 里关闭这是死规矩。哪怕业务逻辑再复杂、异常分支再多关闭动作一定要包得住。踩过一次连接池打满的坑之后我现在的代码里凡是出现 FutureCallback 的地方close 一定在 finally 块里。第二连接池参数必须面向对端服务设置而不是只面向客户端。连接能否复用很多时候由服务端的空闲超时决定客户端一味延长 TTL 没有意义。我现在每接入一个下游第一件事就是问清楚对端的 keepalive 超时时间再定客户端的 TTL 和空闲清理参数。第三上线前一定跑一次“复用验证”。不需要复杂的压测用上面那个统计 available 的 Demo 发几个请求看 available 能不能稳定为 1。再抓一下包看有没有重复握手。这两步通过连接复用才算是真的生效。HttpAsyncClient 的连接复用机制从代码层面看是一套连接池和策略的组合但从运行层面看它的健康程度严重依赖使用方的每一个细节响应体吃干净、连接按时还、超时配置合理、监控指标可见。把这些习惯固定下来Keep-Alive 从理论到实践就真正闭环了。

相关新闻

排队机叫号系统源码拆解:Java Swing+MySQL与状态机设计

排队机叫号系统源码拆解:Java Swing+MySQL与状态机设计

简介:一套完整可运行的排队机叫号系统源代码,面向C#初学者及叫号系统设计人员,提供从数据库操作到界面显示、硬件调用的全流程参考。项目经历多年实际客户使用,运行稳定,作者开放源码供学习交流,并提示勿直…

2026/10/17 9:03:30 阅读更多 →
Linux内核数据结构读书笔记:链表、kfifo与红黑树的设计之道

Linux内核数据结构读书笔记:链表、kfifo与红黑树的设计之道

读书这件事,最怕的就是“看完了”和“看懂了”之间隔着一条巨大的鸿沟。我当初第一次翻《Linux内核设计与实现》的内核数据结构这一章时,觉得挺简单——链表不就是指针指来指去,队列不就是先进先出,哈希表不就是数组加链表嘛。可等…

2026/10/17 9:03:30 阅读更多 →
Java电商爬虫实战源码:反爬绕过+多解析器+MySQL落库

Java电商爬虫实战源码:反爬绕过+多解析器+MySQL落库

简介:本资源是一套完整的Java爬虫项目实战源码,面向具备Java基础的开发者及数据采集方向学习者,旨在帮助掌握网络数据抓取的核心技术与工程实践能力。压缩包共1959个文件,涵盖200个Java源文件(含MovieIndex、TypeCaseH…

2026/10/17 9:03:30 阅读更多 →

最新新闻

单目相机加平面镜实现低成本三维重建:镜像虚拟多视角采集与3DGS实践

单目相机加平面镜实现低成本三维重建:镜像虚拟多视角采集与3DGS实践

搞三维视觉的朋友估计都遇到过这种尴尬:明明只需要重建一个小物件或一片室内场景,手里却只有一台普通相机。买一套多相机阵列?成本直接起飞。手持环绕拍一圈?又容易丢特征、糊成一片。我自己前阵子在某实验室折腾一个代号叫“某跨…

2026/10/17 11:53:35 阅读更多 →
Agent RL新架构重塑强化学习:从学动作到学推理,训练逻辑全面升级

Agent RL新架构重塑强化学习:从学动作到学推理,训练逻辑全面升级

Agent RL这个词最近在圈子里密集出现,如果你还停留在“强化学习打游戏、跑仿真、调DQN”的老印象,那接下来要聊的内容可能会彻底刷新你的认知。我最近几个月一直在跟进这个方向,也亲手搭了几套不同规格的训练流程,最大的感受是&am…

2026/10/17 11:53:35 阅读更多 →
基于混合专家模型MoE的Agent长程记忆架构设计与实操

基于混合专家模型MoE的Agent长程记忆架构设计与实操

1. 从一篇中稿论文说起:Agent长程记忆到底卡在哪Agent(智能体)这个概念这两年已经被说烂了,但真正动手做过长程任务的人都知道,最让人头疼的从来不是模型会不会调用工具,而是它记不住。你让它跑一个跨越几十…

2026/10/17 11:53:35 阅读更多 →
监控视角工地工程车辆检测数据集VOC+YOLO格式实战解析

监控视角工地工程车辆检测数据集VOC+YOLO格式实战解析

做工地智慧安监的朋友应该都有同感:模型在测试集上跑得再漂亮,一挂到现场监控上就原形毕露。尤其是工程车辆检测,通用数据集里大多是自动驾驶视角的平视照片,换成工地固定点位摄像头的俯视监控画面,角度一变、距离一变…

2026/10/17 11:53:35 阅读更多 →
SQL注入自动化实战:Less-16双引号闭合与布尔盲注脚本详解

SQL注入自动化实战:Less-16双引号闭合与布尔盲注脚本详解

sqli-labs整套靶场我前前后后刷过两遍,Less-16属于那种看着不难、上手就卡住的关卡。前面几关要么是字符型注入能直接回显,要么是报错信息直接摆在页面上,到了Less-16突然变成POST登录框,没有回显点,也不输出数据库报错…

2026/10/17 11:53:35 阅读更多 →
RAG知识库问答系统搭建指南:原理、代码与调优

RAG知识库问答系统搭建指南:原理、代码与调优

先聊一个常被问起的问题:大模型知识更新慢、还容易一本正经地胡编,这种情况怎么破?业界给出的主流答案就是RAG(Retrieval-Augmented Generation,检索增强生成)。RAG的核心思路并不玄乎——给大模型外挂一个…

2026/10/17 11:52:35 阅读更多 →

日新闻

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

简介:《DeepSeek使用方法.pdf》是一份面向DeepSeek入门及进阶用户的完整使用指南,重点围绕V3与R1两款模型的能力差异与适用场景展开,帮助读者根据任务类型与成本选择合适的模型。资源共1个PDF文件,压缩包大小约311KB,篇…

2026/10/17 0:00:25 阅读更多 →
200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

简介:这是一份聚焦DeepSeek提示词优化的《200Deepseek润色指令》PDF文档,共收录两百余条可直接套用的润色指令,涵盖语法修正、风格统一、逻辑梳理、表达精炼等维度,并针对商务写作、学术论文、广告文案等场景给出差异化建议。文档…

2026/10/17 0:00:25 阅读更多 →
OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

简介:本资源是一份基于OpenCV的本科课程设计完整报告,面向计算机视觉初学者、图像处理学习者及高校通信/信息类专业学生,解决物体智能计数与检测结果结构化记录的实际问题。项目覆盖图像预处理、轮廓检测、边界框绘制、轨迹栏交互式参数调节、…

2026/10/17 0:00:25 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/16 21:35:51 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/17 1:44:59 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/16 15:04:24 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 21:54:38 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 3:49:43 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 14:23:36 阅读更多 →