Oracle 会话因 VPN 掉线?检查 keepalive 各层
安静的数据信工作可能比空闲的网络流活得更久。按正确顺序检查套接字开关、内核默认值和 Oracle Net 设置。
二十五分钟有用的数据信工作几乎不产生任何输出,而从路径上每台设备看,这个流都处于空闲状态。被回收的恰恰就是空闲状态。事后的报告总是同一个形状:查询在跑,然后会话消失了,结果从未到达。
四项检查决定一个安静的会话能否存活,它们从套接字往外走。请按顺序做,因为每一项都假定上一层在尽职。
哪条流会安静下来
真正要紧的是承载数据信流量的那条连接,它由自己的地址和端口标识。别的任何东西都不会刷新它。发往网关的 ping、来自同一主机的第二条 SQL 连接,以及隧道自身的信跳,都是独立的流,在每台跟踪它们的设备上各有独立状态。
ss -tio dst 10.60.4.20
sysctl net.ipv4.tcp_keepalive_time net.ipv4.tcp_keepalive_intvl net.ipv4.tcp_keepalive_probes
套接字列表会显示活动连接的定时器和队列状态,比可达性测试更有信息量。sysctl 的值是内核关于 keepalive 行为的默认值,下一节会解释为什么它们可能永远不适用于你的会话。从不触发的默认值与根本没有默认值无法区分。
记下连接使用的地址、端口和接口。当会话死掉时,正是这些细节让你能去问正确的设备它做了什么,而不是去问网络当时是否通。
空闲策略是到期还是限额
两种策略会产生同样的症状,却需要相反的应对。空闲超时会移除本可被合格流量刷新的状态,而 keepalive 可以阻止这一点。绝对会话限额会在固定时长后移除流,与活动无关,任何 keepalive 都改变不了。
去问每个中间设备的拥有者,它实现的是哪一种。防火墙、NAT 设备、负载均衡器和云网关都可能保存状态,它们不必彼此一致。最窄的那个决定了你必须击败的期限。
这个区分也告诉你何时停止调参。如果策略是绝对限额,正确的解法是更短的工作单元、可续跑的任务或获批的例外,下面的检查只会确认 keepalive 没有带来任何改变。
Linux 默认值背后的套接字开关
keepalive 是按套接字选择的。内核默认值描述的是套接字启用该机制之后探测的行为,它们并不会为已有连接启用它。从不请求它的应用得不到任何探测,无论 sysctl 的值怎么说。
所以只把数值调高,对数据信客户端毫无改变。必须由客户端库或应用来启用该机制;在协议栈提供按连接控制的地方,范围受限的设置胜过影响无关服务的全主机改动。
到第一次探测的间隔也不是查询超时。健康的连接在探测之间保持安静,死掉的对方会按探测间隔与次数被识别。把这三个值读成一个超时,就会得到要么太晚、要么太急地发现故障的设置。它们管的是检测,不是应用的耐心。
EXPIRE_TIME 是数据信设置,不是网络修复
Oracle Net 提供自己的存活机制,它配置在进程实际生效的配置文件里,而不是某个碰巧同名的任意文件。该值以分钟表示。
SQLNET.EXPIRE_TIME = 5
它的主要用途是服务端发现死连接;在支持增强模型的平台上,它还会为这些连接调整 TCP keepalive 行为。这是有用的性质:数据信层可以安排探测,而不必要求客户端应用改动。
上面的示例值是针对假定期限协调出来的选择,不是建议。有文档的一般指引是更长的间隔,正确的数字取决于所安装的实现、你能接受的探测开销以及路径上实际的刷新规则。把设置放进相关进程读取的配置文件,并确认进程已经采纳。Oracle 在其参数参考中记录了配置文件位置和检测行为。
测试那段安静间隔,然后规划恢复
让一条新的、被允许的连接走完一段比你要击败的期限更长的安静期,并观察存活流量与应用结果。不要抓取你并不需要的载荷内容;定时器与连接状态就能回答这个问题。
ss -tio dst 10.60.4.20
# after the quiet interval, same command
ls -l "$ORACLE_HOME/network/admin/sqlnet.ora"
如果会话仍然消失,那期限属于某个你还没问过的设备,或者策略本身就是绝对限额。如果它活了下来,记下是哪一层变了,好让下一次安静操作不再重复调查。
最后,想清楚连接真的断开时会发生什么,因为存活检查只是降低频率,从不消除可能性。在重新提交之前,先确认数据信操作已记录的结果:丢失回复并不能证明工作是否已提交。凡是要扛住合上笔记本或重启隧道的,由服务端持有且结果持久的任务才是更强的设计,keepalive 不是调度器。