rustls 小容量会话缓存存不住,检查插入后的淘汰条件
rustls 0.23.45 的 LimitedCache 在刚达到容量时就淘汰,容量为一的会话缓存可能始终为空。正式 0.23.46 已改为超过请求容量才淘汰;验证恢复还需复用配置并等到 ticket 到达。
TLS 连接一直能成功,重复连接却始终走完整握手。应用已经启用会话缓存,而且只连接同一个服务;若使用 rustls 0.23.45,并把缓存压到很小,可以检查是否刚插入就被淘汰。
这条边界下,ServerSessionMemoryCache::new(1) 留不住新条目;客户端缓存大小为 1 至 8 时,也会折算成一个服务名槽位并遇到相同问题。缓存配置存在、握手成功和后续真正恢复,是不同的检查项。
容量达到一,不该立刻删掉唯一条目
0.23.45 的 LimitedCache 在插入新键后,比较内部队列长度与分配容量;一旦相等就移除最旧键。容量为一时,刚写入的那个键也就是最旧键,随即被删除。
普通容量下可能只表现为少存一个条目,小容量则更明显。客户端的 ClientSessionMemoryCache 还会按每个服务最多八张 TLS 1.3 ticket 的模型,将传入 size 向上折算成服务名数量;不能把它简单理解成相同数量的独立服务名槽位。
正式 rustls 0.23.46 已保存请求的最大条目数,并在插入后仅当长度大于这个上限时淘汰。容量为一的缓存因此能够保留一个条目;这项变化同时覆盖直接插入与先取值再编辑的路径。
让实际依赖使用包含修正的版本
直接依赖 rustls 0.23 的项目,应在原有依赖管理中采用包含该修正、且符合应用兼容要求的正式版本。0.23.46 已于 2026 年 10 月 14 日发布,不需要为这项修正切到 0.24 的开发版本。
如果 rustls 由 HTTP、数据库或其他客户端库间接引入,应核对最终解析的包实例与 feature。锁文件里出现一份新 rustls,不代表实际建连的那份旧依赖也已替换;存在多个版本时要定位到对应调用链。
扩大旧版缓存可以改变触发条件,但没有修正旧淘汰规则,不适合当作精确容量保证。内存预算和服务名数量仍应按应用规模制定,不为掩盖一次不命中便无限增加缓存,也不需要关闭证书验证或降低 TLS 协议保护。
排除没有机会恢复的连接方式
升级后仍不命中,要先确认应用复用同一份长期配置及其 session store。每次连接都重新创建空缓存,无法保留上一次握手结果,这与插入淘汰不同。
TLS 1.3 的 NewSessionTicket 可以在握手完成后到达。只等握手完成就立刻丢弃连接、从不继续处理服务端数据,可能根本没把 ticket 存下来。服务端也需要实际允许恢复,并保留有效票据或会话状态;客户端缓存不可能替没有发出的 ticket 创造恢复机会。
在同一受控端点上,先让第一条连接正常处理握手后的协议数据,再新建第二条 TCP 连接,观察 rustls 的握手类型或既有 TLS 诊断是否显示恢复。不能把复用同一条 HTTP 长连接当作会话恢复,它甚至没有进行第二次 TLS 握手。
同时回查容量为一、多个服务名以及票据过期的情况。不要把 session 值的 Debug 内容写入日志来判断是否保存;会话材料可能包含秘密。只记录是否命中、握手类型和必要的数量信息即可。


