首页 › ims › IMS会话定时器刷新机制拆解

IMS会话定时器(Session Timer)刷新与失活检测机制深度拆解

一、为什么需要 Session Timer:SIP 状态悬挂的"清道夫"

在 IMS/VoNR 体系中,一条语音呼叫的本质是一个 SIP dialog(会话),它由 Call-ID、From-tag、To-tag 三元组唯一标识,并沿路在 UE、P-CSCF、S-CSCF、SBC/IBCF、对端 UE 之间维护着大量的状态机与媒体资源(IPSec SA、RTP 端口、QoS 承载、计费会话)。

问题在于:SIP 是基于事务(transaction)驱动的协议,会话一旦建立,只要双方不主动发 BYE,dialog 就会无限期存在。 但现实中的失败模式往往是"静默失败"——

这些情况下,网络侧的 SIP 状态无人清理,媒体面 RTP 停流但会话条目悬挂,直接导致端口资源泄漏、错路由、计费超长("幽灵通话"),以及最经典的现网投诉——"通话到第 30 分钟准时断"。

3GPP TS 24.229(《IP multimedia call control protocol based on SIP and SDP》)在 IMS 会话控制中强制要求支持 RFC 4028 定义的 SIP Session Timer 扩展,并依赖它作为会话失活检测的最终兜底机制。其一致性测试规范 TS 34.229-5 第 7.28~7.34 节专门为 5GS 下的会话定时器行为设计了 7 组测试用例(MO/MT、远端支持/不支持/不发 Session-Expires、谁做 refresher 等)。

本文基于 RFC 4028 原文与 3GPP TS 24.229 / TS 34.229-5,逐消息、逐 IE 拆解这套协商-刷新-超时终止的完整信令机制。

二、三个核心 IE 与一个响应码

Session Timer 的全部控制信息,集中在三个 SIP 头域和一个响应码上:

头域 / 响应码 出现位置 含义 取值约束(RFC 4028 §4/§5/§6)
Session-Expires INVITE/UPDATE 请求及对应 2xx 响应 会话最大存活时长(delta-seconds) 绝对下限 90s;推荐 1800s(30 分钟);可携带 ;refresher=uac/uas 子参数
Min-SE INVITE/UPDATE 请求;仅 422 响应中携带 该端可接受的最小会话时长 ≥90s;缺省即 90s;响应中只能出现在 422
refresher Session-Expires 的子参数 指定由谁发起周期性刷新 uac(主叫方刷新)/ uas(被叫方刷新)
422 Session Interval Too Small UAS 或代理拒绝请求时 请求的 Session-Expires 低于本端 Min-SE 必须携带 Min-SE 告知门槛

设计要点解读:

  1. 为什么下限是 90 秒? RFC 4028 §4 明确解释:90 秒略大于 SIP 事务在超时重传情况下的最坏耗时(约 T1×64≈32s 的两倍)。这样保证刷新方能在 会话过半(halfpoint) 时发起一次刷新,且该事务有充裕时间在会话过期前正常完成。
  2. 为什么推荐 30 分钟? 因为统计上 95% 的电话通话时长短于 30 分钟。过短的 SE 会带来"刷新风暴"与双方同时发起 re-INVITE 的 glare(碰撞) 问题,损伤网络。
  3. Min-SE 只在 422 中出现,这是协议级别的硬约束(Table 1 中 422 列为 m=mandatory)。它在请求中是"我的底线",在 422 中是"我拒绝你的理由"。

三、完整信令时序:协商 → 422 重试 → 过半刷新 → 超时 BYE

下面给出一条典型 MO VoNR 呼叫中,主叫 UE 与被叫之间完整的 Session Timer 协商与中段刷新流程(P-CSCF/S-CSCF 为路由节点,亦参与 Min-SE 校验):

sequenceDiagram
    participant UE as 主叫 UE (UAC)
    participant PC as P-CSCF
    participant SC as S-CSCF
    participant TE as 被叫 UE (UAS)
    Note over UE,TE: 阶段1:会话建立与SE协商
    UE->>PC: INVITE<br/>Session-Expires:1200;refresher=uac<br/>Min-SE:90, Supported:timer
    Note right of PC: 本地Min-SE=1800<br/>1200 < 1800 → 拒绝
    PC-->>UE: 422 Session Interval Too Small<br/>(Min-SE:1800)
    UE->>PC: ACK
    UE->>PC: INVITE<br/>Session-Expires:1800, Min-SE:90
    PC->>SC: INVITE (透传 SE:1800)
    SC->>TE: INVITE
    TE-->>UE: 183 Session Progress (早期媒体/编解码协商)
    TE-->>PC: 200 OK<br/>Session-Expires:1800;refresher=uac<br/>Require:timer
    PC-->>UE: 200 OK
    UE->>TE: ACK
    Note over UE,TE: 阶段2:会话已建立,SE=1800s<br/>UE为refresher,过半(900s)刷新
    Note right of UE: 900s 后发起刷新
    UE->>TE: re-INVITE / UPDATE<br/>(Session-Expires:1800)
    TE-->>UE: 200 OK (Session-Expires:1800)
    UE->>TE: ACK
    Note over UE,TE: 过期点延长至本次2xx之后+1800s
    Note over UE,TE: 阶段3:刷新失败/超时 → 终止
    alt 刷新请求无响应或收到 481/408
        UE->>TE: BYE (会话失活,主动清理)
    else 过期前从未收到刷新请求
        TE->>UE: BYE (对端过期清理)
    end

关键 IE 逐消息解析:

① 初始 INVITE——Supported: timer 是会话定时器能力的"广告位",任何支持 timer 的 UA 必须在除 ACK 外的每个请求里都带上(RFC 4028 §7.1)。UE 若希望自己做刷新方,就在 Session-Expires:1200;refresher=uac 中明确;若希望强制对端支持,可加 Require: timer。

② 422 重试——这是 Session Timer 最具特色的协商环节。P-CSCF(或路径上任意代理、或 UAS)发现 1200 < 本地Min-SE(1800),回 422 并 必须 带上自己的 Min-SE:1800。UE 收到后,按 RFC 4028 §7.3:取"所有收到的 422 中最大的 Min-SE"作为下限,重新构造 INVITE。TS 34.229-5 第 7.28 节的测试用例就构造了 连续两次 422(Min-SE:1860 → 1920) 的重试链,验证 UE 最终以 Session-Expires:1920, refresher=uac 完成建立——这条测试线完美刻画了现网中代理逐级抬高门槛的真实场景。

③ 2xx 响应绑定 refresher——最终 200 OK 中的 Session-Expires:1800;refresher=uac 是 绑定(binding) 的:双方依据此值确定"谁刷新、何时过期"。注意 UAS 在 2xx 里只能 减小或保持 SE(不得增大),且不得低于请求中的 Min-SE(或 90s)。

④ 过半刷新——RFC 4028 §9 推荐 refresher 在 会话时长过半(900s) 时发起 re-INVITE/UPDATE。只有 2xx 响应才能延长过期点——这是核心不变式。即使刷新请求被 422 拒绝(对端临时抬高了 Min-SE),原过期点不变,UE 仍须在该过期点前重发刷新请求。

⑤ 终止逻辑——两条独立的失活路径:refresher 发出刷新后一直收不到响应(或收到 408/481)→ refresher 发 BYE;非刷新方在过期点前始终没收到任何刷新请求 → 非刷新方发 BYE。这种双向兜底确保了无论谁先失联,会话最终都会被释放。

四、refresher 角色协商算法:RFC 4028 Table 2 精解

谁来做 refresher,不是写死的,而是在会话建立时由 UAS 依据 UAC 能力 + UAC 是否已表态 决定的。RFC 4028 §9 给出了决定性的决策表(Table 2):

flowchart TD
    A[收到的 INVITE 中 Supported 含 timer?] -->|否 UAC不支持| R1[refresher = uas<br/>网络/被叫侧负责刷新]
    A -->|是 UAC支持| B[INVITE 是否带 refresher 参数?]
    B -->|未带 不表态| R2[UAS 自行决定<br/>uas 或 uac]
    B -->|带 refresher=uac| R3[refresher = uac<br/>UAS 不可推翻]
    B -->|带 refresher=uas| R4[refresher = uas<br/>UAS 不可推翻]
    R1 --> RE[2xx 中 Session-Expires<br/>绑定 refresher 参数]
    R2 --> RE
    R3 --> RE
    R4 --> RE
    RE --> REQ{refresher == uac ?}
    REQ -->|是| F1[2xx 必须带 Require:timer<br/>强制UAC处理响应]
    REQ -->|否且UAC支持| F2[2xx 应带 Require:timer<br/>SHOULD 级别]

三条铁律(RFC 4028 §9):

  1. UAS 不能推翻 UAC 已表态的角色。 若 UAC 写了 refresher=uac,UAS 只能接受 uac,反之亦然。这是"先到先得"的能力声明机制。
  2. 当 UAC 支持但未表态时,UAS 拥有选择权。 这给被叫网络一个灵活点——例如被叫是 PSTN 网关时,MGCF 可指定由更可靠的 IP 侧做刷新。
  3. 当 UAC 完全不支持 timer 时,refresher 必为 uas。 这正是 IMS 中 P-CSCF 强制启用会话定时器的理论依据——UE 不支持,网络来兜底。

Require: timer 的作用是确保响应被对端正确处理:refresher=uac 时是 MUST(因为 UAC 必须从 2xx 里知道"轮到我刷新了"),refresher=uas 且 UAC 支持时是 SHOULD(因为 UAC 虽不刷新,但要负责在收不到刷新时发 BYE)。

IMS 工程意义:P-CSCF 几乎总是路径上第一个"懂事"的 SIP 代理。当 UE(尤其老式终端)不支持 timer 时,P-CSCF 会在 2xx 中插入 Session-Expires;refresher=uas 并由自己周期性向对端发起 re-INVITE。一旦 UE 静默失联,P-CSCF 的刷新请求超时,便主动发 BYE,把悬挂的会话连同计费、媒体面一起清掉。

五、会话状态转换:从建立到超时终止

Session Timer 在每个 UA 内部维护一份状态:session interval(时长)+ session expiration(绝对过期时刻)+ refresher 身份,且绑定到具体 dialog。

stateDiagram-v2
    [*] --> 协商中: 发送/接收 INVITE
    协商中 --> 协商中: 422 → 调整SE后重发INVITE
    协商中 --> 协商中: 422重试循环
    协商中 --> 已建立: 收到/发出2xx含Session-Expires
    协商中 --> [*]: 2xx无Session-Expires → 不启用定时器
    已建立 --> 刷新中: 过半SE,refresher发re-INVITE/UPDATE
    刷新中 --> 已建立: 2xx响应(过期点向后延展)
    刷新中 --> 终止: 481/408/无响应 → refresher发BYE
    已建立 --> 终止: 过期前未收到刷新 → 非刷新方发BYE
    已建立 --> 终止: 任意一方主动BYE
    终止 --> [*]: 释放dialog/媒体/承载

两条最易被忽视的状态规则:

六、横向对比:Session Timer 与其他周期性机制

IMS 中有多个"周期性保活"机制,初学者极易混淆。下表厘清它们的边界:

机制 作用对象 触发条件 失效后果 典型周期 规范
SIP Session Timer SIP dialog(单次呼叫会话) refresher 在过半 SE 时发 re-INVITE/UPDATE 任一方发 BYE,呼叫释放 1800s RFC 4028 / TS 24.229
IMS 注册周期 IMS 注册(用户在网状态) 网络下发的 P-CSCF 定时器到期,UE 周期重注册 S-CSCF 去注册,用户整体下线 ~3600s TS 24.229 / TS 23.228
NAT/OPTIONS keepalive NAT 绑定(中间盒端口映射) 周期发空 OPTIONS 或 CRLF NAT 表项老化,信令不通 20~30s 工程实践(RFC 6223)
RTP 媒体保活 RTP 媒体流连通性 周期发空 RTP/舒适噪声包 媒体面误判停流,触发媒体检测 15~30s TS 26.114

关键区分:注册保活管"用户在不在线",Session Timer 管"这一通电话还活着没"。一个用户可同时有 1 个注册 + N 个并行会话,每个会话独立跑自己的 Session Timer。注册过期会触发 S-CSCF 清理该用户所有会话(这也是 HiCellTek 掉话诊断树里"IMS 注册过期 → S-CSCF 释放会话"的来源),但这是注册层行为,与会话定时器本身的超时是两条独立路径。

七、抓包识别与排错实战

7.1 如何在 Wireshark 中识别 Session Timer 流程

用 Wireshark 过滤 SIP,按以下特征定位:

  1. 建立阶段:sip.Session-Expires 或显示过滤器 sip.Header contains "Session-Expires"。看 INVITE 与 2xx 中 SE 值是否一致、refresher 取值。
  2. 422 协商:sip.Status-Code == 422,展开响应看 Min-SE 值——这是排查"为什么 SE 被改"的关键证据。
  3. 中段刷新:会话建立后数百秒出现的 re-INVITE 或 UPDATE,且其 CSeq 序号递增、Session-Expires 续期,即为刷新请求。
  4. 超时 BYE:sip.Method == "BYE",结合时间戳判断是否恰好在 SE 过期点附近,并在 Reason 头或前序 408/481 中寻找线索。

7.2 三大经典故障与排错思路

故障一:通话到第 30 分钟准时断(最经典)。 telecomHall 论坛反复出现的案例:VoLTE 呼叫固定在 30 分钟断。根因即 Session Timer。排查路径:抓包确认 SE 值(多为 1800s)→ 确认刷新请求是否在 ~900s 准时发出 → 检查刷新请求是否被对端拒绝(常见于 NAT 老化导致刷新请求到不了被叫,或被 SBC 因 SDP 不变而丢弃)。若刷新请求根本没发,则检查 refresher 角色判定——可能双方都误以为对方是 refresher("双方都不刷新"),到期双双发 BYE。

故障二:refresher 不匹配 / 双方都不刷新。 违反 Table 2 的实现会导致:UAC 写了 refresher=uac,但 UAS 错误地改成 uas 并把自己设为非刷新方;或一方当 uas、一方当 uac 的理解不一致。结果双方都"等对方刷新",SE 到期一起发 BYE。排错:逐跳对比 INVITE 与 2xx 中的 Session-Expires 头,确认 refresher 参数未被中间代理擅自篡改(P-CSCF/SBC 改写 SE 是合规的,但改 refresher 角色需遵循 Table 2)。

故障三:422 死循环。 若 UAC 的 Session-Expires 永远低于路径上某节点的 Min-SE,且该节点在每次重试中不断抬高 Min-SE,会陷入 INVITE→422→INVITE→422 的死循环(TS 34.229-5 §7.28 测试链即模拟此)。规范要求 UAC 取"所有 422 中最大的 Min-SE"且 Min-SE 有 90s 下限、SE 有推荐 1800s,正常应能收敛。死循环通常是某 SBC 的 Min-SE 配置异常(如设成天文数字)或 UAC 实现未正确取最大值。Sansay TAC 文档记录的"408 refresh failure"也常源于刷新请求本身被中间设备超时丢弃。

八、常见问题

Q1:Session Timer 和 precondition、PRACK 是一回事吗? A:完全不同。precondition(RFC 3312)解决的是"资源/QoS 就绪前不响铃"的本地/远端资源确认,靠 183+PRACK 传递 SDP 状态属性;PRACK(RFC 3262, 100rel)解决临时响应的可靠传输。Session Timer(RFC 4028)解决的是"会话存活的周期性确认与失活清理"。三者都借助 re-INVITE/UPDATE 这类 mid-dialog 请求,但目标各异,可叠加使用。

Q2:refresher=uac 和 uas,网络通常希望谁做? A:在 IMS 中,网络(P-CSCF/SBC)倾向于自己做 refresher(即对 UE 而言是 uas 角色),以便在 UE 静默失联时由网络主动检测并清理。但若 UE 能力强且省电敏感,也可让 UE 做 uac 刷新。最终取决于 Table 2 的协商结果与运营商策略。

Q3:刷新请求里 SDP 不变(纯保活),为什么还要做完整 offer/answer? A:因为 re-INVITE/UPDATE 本质是会话修改请求,规范要求其按正常 offer/answer 流程处理。为避免媒体重协商抖动,刷新请求通常发送与当前会话一致的 SDP("no-op" offer),对端回一致 answer。一些 SBC 会识别这种无变化的刷新并做快速处理。

Q4:会话过期后发的 BYE,与正常挂断 BYE 在信令上有区别吗? A:方法都是 BYE,但超时触发的 BYE 常携带 Reason 头(如 Reason:SIP;cause=408 或 cause=200;text="Session Timer Expires"),且在时间上严格出现在 SE 过期点附近,前序通常有失败/无响应的刷新请求记录。抓包时按时间轴对齐即可区分。

Q5:5G VoNR 与 VoLTE 在 Session Timer 上有差异吗? A:信令机制完全一致(都跑在 IMS SIP 层)。差异在承载:VoNR 的语音承载是 5QI=1 的 5GS PDU 会话,RLF 后无线恢复更快,但若 UE 真正失联,P-CSCF 的 Session Timer 仍是最终兜底。5G 侧 TS 34.229-5 §7.28~7.34 的测试用例就是专门为 5GS 场景设计的。

参考来源

  1. RFC 4028: Session Timers in the Session Initiation Protocol (SIP) — Donovan & Rosenberg, IETF Standards Track,§4 Session-Expires、§5 Min-SE、§6 422、§9 Table 2 UAS refresher 协商算法
  2. 3GPP TS 24.229 — IP multimedia call control protocol based on SIP and SDP — IMS 会话控制中强制支持 RFC 4028 会话定时器
  3. 3GPP TS 34.229-5 — IMS Client conformance (5GS) — §7.28~7.34 Session Timer 一致性测试用例(MO/MT、422 重试链 1860→1920、TS 24.167 Session_Timer_Support)
  4. Cisco — Troubleshoot Session Refresh on CUBE — CUBE 侧刷新失败与 refresher 行为实战排错
  5. telecomHall — VoLTE calls dropping after 30 minutes — 经典 30 分钟掉话社区诊断,印证 SE=1800s 兜底释放

本文由「51学通信」技术团队出品。51学通信由通信行业18年老兵爱卫生(微信ID: gprshome201101)维护,聚焦5G/6G核心网、3GPP标准解读、通信前沿技术深度分析。 出版作品有《5G核心网原理与实践》《IMS原理与实践》等4本通信专业书籍。知识星球「51学通信」提供深度技术答疑和行业洞察。

[!tip] 51学通信知识星球 星主:爱卫生(微信:gprshome201101)——公众号「51学通信」创办者,19 年通信行业运维与讲师经验,著有《GPRS网络信令实例详解》《EPC原理与实践》《5G核心网原理与实践》三本纸质书(各大电商平台有售)。 星球定位:深耕 5G 核心网、IMS、NFV/AI、云原生等 ICT 领域,主打运维岗位与信令分析。 当前规模:5200 篇主题 / 990 个回答,198 元/年。 加入福利:加入星球后请加爱卫生微信,拉您进知识星球年度陪伴与答疑群——不限量回复您的各种问题,另有群内分享。 AI 加持:51学通信知识星球已作为 skill 接入 WorkBuddy,使用 deepseek-4-flash 在海量星球帖子中精准找贴、找视频、找 FAQ 和案例,做总结、找文档和 PPT 等场景全覆盖。

51学通信知识星球海报-扫码加入