会话保持时长每拉长一分钟,就意味着每一个活跃用户背后的空闲连接要多占用一分钟的内存、端口和文件描述符,当并发用户数过万时,这个"多占"会直接演变成连接资源耗尽,新用户连不上服务器,老用户频繁超时重连。很多运维团队把会话保持超时时间从5分钟改成30分钟,觉得只是让用户少登录几次,结果半夜告警电话打爆,一看连接数翻了四倍,后端Tomcat直接拒绝服务,这不是配置失误,是对连接资源账目没有概念。
会话保持时长设置过长会占用多少连接资源
会话保持的本质是让客户端和服务器之间的"记忆"在指定时间内不被释放,这个记忆存储在内存里,表现为一条条连接条目,连接条目不是免费的,它至少占据以下四类资源:
- 内存:每个TCP连接在内核态和用户态各有一份控制块(TCP Control Block),加上应用层会话对象,一个空闲连接大约消耗3-6KB内存,100万条空闲连接就是3GB到6GB。
- 端口号:四层负载均衡场景下,客户端IP和端口是四元组的一部分,来源端口只有65535个,会话保持时长拉长,同一客户端IP的端口释放变慢,端口耗尽的风险指数级上升。
- 文件描述符:每一条连接占用一个FD,默认进程限制通常是1024,生产环境即使调到65535,也经不起空闲连接累积。
- 后端连接槽位:Nginx或HAProxy转发到后端时,如果开启了keepalive,后端服务器也要为每个上游连接维护资源,会话保持时间越长,后端的半开连接和空闲连接越积越多。
一个换算公式值得记住:连接占用总量 ≈ 平均每秒新建连接数 × 会话保持时长(秒),如果网关每秒产生200个新会话,会话保持从300秒改成1800秒,同时刻存活连接数会从6万涨到36万,很多生产事故的根源不是流量暴涨,而是"会话保持时长设置过长占用连接资源"这个隐蔽膨胀过程。
四层和七层会话保持的消耗差异
四层(LVS、F5)会话保持只需要维护源IP和目的IP的映射关系,一个条目大约几十字节,相对节省,七层(Nginx、HAProxy)要保存Cookie、Session ID、用户上下文,一个条目动辄几百字节,加上应用层对象可能到KB级别。
行业共识认为:七层会话保持的资源开销是四层的5到10倍,所以如果只是做IP级别的粘滞,优先用四层;如果必须按用户维度保持会话,七层需要预留更大的内存和连接表空间。
空闲连接为什么比活跃连接更伤资源
活跃连接在收发数据,资源在被有效利用,空闲连接挂在超时链表上,定期被内核扫描,系统维护超时定时器也需要CPU开销,连接数越多,定时器轮询的消耗越大,有些系统使用时间轮或最小堆管理超时,连接数翻倍时,超时管理的CPU消耗虽然不是线性翻倍,但相当一部分性能损耗确实来自海量空闲条目的扫描和排序。

会话保持超时时间设置多少合适
给一个保守但实用的参考区间:
| 业务类型 | 推荐会话保持时长 | 说明 |
|---|---|---|
| 电商Web/登录态 | 5-15分钟 | 用户操作间隙短,超时后重新登录成本低 |
| API接口网关 | 30-120秒 | 接口调用密集,重连开销极小 |
| WebSocket/长连接推送 | 1-4小时 | 心跳机制本身在续约,不需要把超时设得极大 |
| 金融交易系统 | 3-5分钟 | 安全要求高,超时后重新验签更合理 |
| 内网OA系统 | 30分钟-1小时 | 办公场景操作停顿长,但并发量小,资源压力可接受 |
这个表不是拍脑袋,会话保持时长的底线是业务无感知断连,上限是可承受的连接资源预算,一个日活10万的网站,平均在线用户1万,如果每个用户每5分钟产生一个会话,那么150秒的保持时长就能覆盖绝大多数操作间隙,设置成2小时,不是更稳,是更费。
说一个常见的错误认知
有人觉得"会话保持时间越长,用户越流畅",实际操作中恰恰相反,会话保持时间过长,会话表里堆积大量已经离开用户的僵尸条目,新用户进来时查找会话表的耗时变长,甚至触发哈希冲突,响应变慢,用户重新登录一次的耗时是几百毫秒,但连接池耗尽导致的排队和超时可能持续几分钟,后者对用户体验的伤害大得多。
会话保持和负载均衡策略的取舍
如果后端只有两台服务器,为了没有粘滞策略的负载均衡器,把所有请求均匀分发,每个请求都重新认证,代价是认证接口承受大部分压力,会话保持用一个简单办法把压力分散到各后端节点,但前提是资源开销可控,业内专家指出,连接资源足够时,会话保持能显著降低后端认证压力;连接资源紧张时,优先缩短超时时间,而不是扩容机器,扩容解决的是吞吐瓶颈,不是资源浪费。
怎么判断当前会话保持时长是否过大
不用等告警,三个可验证的信号暴露问题:
- 执行
ss -s或netstat -ant | wc -l,统计服务器上的TCP连接数,如果空闲连接数(State为ESTABLISHED但无数据传输)是活跃连接数的5倍以上,大概率超时时间过长。 - 观察网关的内存曲线。内存持续缓慢上涨,不随流量高峰回落,说明超时链表里的条目只进不出。
- 查看后端应用线程栈。

大量线程阻塞在socketRead0
(Java应用常见)或epoll_wait上,等待一个永远不来的请求,这些线程实际上是空闲连接在占用。
逐步排查路径
第一步,按连接的生命周期检查,登录一台Nginx服务器,执行ss -tnp | grep nginx | awk '{print $1}' | sort | uniq -c,看到大量ESTABLISHED状态的连接停留时间超过阈值,就确认了问题方向。
第二步,检查负载均衡会话表,HAProxy可以看show table,Nginx Plus有/api/connections接口,开源OpenResty可以执行ngx.shared.session的size统计,查看表里条目数量和实际在线用户数的比值。条目数是实际用户数的3倍以上,说明僵尸会话太多。
第三步,做一次小规模压测,用100个虚拟用户持续访问,分别设置300秒和1800秒的会话保持时长,观察内存和连接数曲线,压测数据会告诉你具体差值,不用猜。
调优实操:把超时时间从"拍脑袋"变成"算出来"
四层负载均衡场景
LVS的persistence_timeout参数控制会话保持,先看当前值:
ipvsadm -L --persistent-conn
设置新值:
ipvsadm -E -t 192.168.1.10:80 -p 600
-p 600表示保持600秒。注意修改是原子的,不会中断已有连接,新连接立即按新值生效,改完后观察1小时,对比ipvsadm -L --stats里的连接数。
七层Nginx场景
Nginx原生没有内置会话保持,需要配upstream模块或第三方模块,使用ip_hash或sticky指令时,配合如下参数:
upstream backend {
sticky cookie srv_id expires=10m;
server 192.168.1.11:8080;
keepalive 32;
}
这里expires=10m是Cookie的有效期,就是会话保持时长的核心控制点,把它从2h改成10m,资源占用立竿见影地降下来。
如果是通过proxy_pass转发且依赖后端Session:
location / {
proxy_pass http://backend;
proxy_cookie_path / "/; HttpOnly; Max-Age=600";
}
Max-Age=600用Cookie的过期时间间接控制会话保持周期,改这里比改后端应用方便。
后端应用配合
Java环境中,Tomcat的maxKeepAliveRequests和connectionTimeout决定了单个空闲连接的存活时间,把connectionTimeout从默认的60秒或更长降到20秒以内,配合前端缩短会话保持时长,释放资源的效果最明显。
Spring Session场景下,设置server.servlet.session.timeout=10m,让应用层会话和连接层生命周期一致,否则应用层认为用户还在,连接层已经断开,用户下一次请求重新建连,依然占用资源。

WebLogic、WebSphere这些重型中间件,修改空闲连接超时在管理控制台的"连接池"面板里,建议每次只缩短15%到20%,观察一个业务周期再继续调。
会话保持时长的动态策略
更精细的做法是按接口维度区分,比如登录接口的会话保持设置长一点,支付接口出于安全考虑保持短一点,用OpenResty可以做到:
local session_time = ngx.var.request_uri:match("^/api/login") and 1800 or 300
用不同的URI匹配不同的超时策略,让长连接只停留在真正需要的业务上,静态资源完全不走会话保持,这一步就能砍掉相当一部分无效连接。
不能忽视的监控维度
调优之后,重点看三个指标:TIME_WAIT连接数、ESTABLISHED空闲连接平均时长、应用线程池活跃率。TIME_WAIT飙升通常是连接释放太频繁,空闲连接占内存是释放太慢,两者平衡点就是最优超时区间,建议在监控面板上把这几个指标和会话保持超时时间放在同一张图里,调整参数后能直接看到关联趋势。
会话保持时长和连接数关系常见问题
问:会话保持时长设置成24小时,是不是让用户完全不用重新登录,体验最好?
不是,24小时的会话保持时长会让网关和后端的连接表长期处于高水位状态,大部分用户操作间隔超过24小时,真正受益的只有极少活跃用户,体验最好的是让大多数操作在超时时间内完成,同时让超时后的重新认证成本足够低,登录态迁移到Redis或JWT后,重新认证的开销只有几十毫秒,完全没必要用24小时换一个感知不到的提升。
问:负载均衡会话保持超时时间怎么设置才能不丢登录态?
登录态和连接保持是两个层面,连接层的会话保持阈值只影响TCP连接或Cookie的存续,登录态由应用层Session管理,把应用层Session超时时间设为30分钟,连接层会话保持设为10分钟,这样即使连接断开,客户端重连后应用层依然能识别用户,不丢登录态,同时连接资源不会长期被占用,优先保证应用层Session的独立性,连接层的会话保持时间短于应用层。
问:nginx会话保持时间配置在哪几个参数?
Nginx原生有ip_hash和hash指令实现按IP或URL保持会话,它们不直接设置超时时间,而是依赖HTTP keepalive机制,核心参数是keepalive_timeout(默认75秒)和keepalive_requests(默认1000),使用第三方sticky模块时,通过expires参数控制Cookie有效期,单位支持秒、分钟、小时,如expires=15m,修改后执行nginx -t && nginx -s reload生效。