5G 核心网(5GC)相较 4G EPC 最根本的范式转变,是控制面全面采用服务化架构(Service Based Architecture, SBA)。在 SBA 中,AMF、SMF、PCF、UDM、AUSF、NEF、NRF 等 30 余类网络功能(NF)不再以点对点参考点的硬编码方式互联,而是各自对外暴露一组基于 HTTP/2 + JSON 的 RESTful 服务(SBI,Service Based Interface),由服务消费者在运行时动态发现并调用生产者。
这套"动态发现"能够成立,必须存在一个权威的、实时的、可订阅的服务注册中心——这就是 NRF(Network Repository Function)。NRF 在 SBA 中的地位,相当于微服务架构中的 Consul/Eureka,但又被 3GPP 标准赋予了通信网特有的能力:切片感知、PLMN 感知、NF Set 感知、OAuth2 授权服务器、跨运营商漫游发现等。
本文聚焦的具体机制是:NF 实例如何向 NRF 注册自身能力(NFProfile)、如何通过心跳保活、其他 NF 又如何按切片/DNN/PLMN 等条件精准发现目标 NF 并订阅其状态变化。这是 TS 23.502 第 4.17 条(NF Service Framework)与 TS 29.510(NRF Stage 3)共同定义的核心网最基础也最高频的信令链。任何一次 UE 注册、PDU 会话建立、策略决策,底层都要先跑一遍这套发现链。
NRF 中维护的最基本资源是 NFProfile(NF 档案),每个 NF 实例注册时上报一份,NRF 据此构建全局拓扑视图。NFProfile 定义在 TS 29.510 Section 6.1.6(数据类型 NFProfile),字段极为庞大(R18 已达 200+ 属性),但其骨架可归纳为下表。
| IE 名称 | 类型 | 含义 | 在发现/选择中的作用 |
|---|---|---|---|
nfInstanceId |
UUID (string) | NF 实例全局唯一标识,由 NF 自行生成并持久化 | 唯一寻址该实例的句柄 |
nfType |
enum | NF 类型:AMF/SMF/UPF/UDM/PCF/AUSF/NEF/NRF… | target-nf-type 过滤的基础 |
nfStatus |
enum | REGISTERED / SUSPENDED / UNDISCOVERABLE | 仅 REGISTERED 可被发现 |
heartBeatTimer |
integer(秒) | NRF 下发的期望心跳周期 | 心跳保活判活依据 |
fqdn |
string | NF 的全限定域名(如 amf01.mnc000.mcc460.5gc.mnc000.mcc460.3gppnetwork.org) | 服务端点解析 |
ipv4Addresses / ipv6Addresses |
array | NF 服务端点 IP | 直连 IP |
plmnList |
array(PlmnId) | 该 NF 服务的 PLMN | 漫游 target-plmn-list 过滤 |
sNssais |
array(Snssai) | 支持的网络切片(SST+SD) | 切片感知发现的核心 |
nfServices |
array(NFService) | 该实例提供的所有服务实例列表 | service-names 精确匹配 |
nfServiceList |
map | 以 serviceInstanceId 为键的服务映射 | R16 增量更新优化 |
nfProfileChangesSupportInd |
boolean | 声明本 NF 支持增量 Profile 更新 | 决定能否用 PATCH |
amfInfo / smfInfo / upfInfo / pcfInfo … |
object | 各 NF 类型的专属能力描述 | 选择算法的关键输入 |
nfSetId / smfSetId 等 |
string | 所属 NF Set 标识 | 无状态容灾选择 |
其中 smfInfo、upfInfo 这类专属 IE 信息量极大。例如 SmfInfo 中包含 sNssaiSmfInfoList(每个切片下支持的 DNN 列表、TAI 列表)、taiList、pgwFqdn 等;UpfInfo 中包含 sNssaiUpfInfoList、每个切片下的 dnnUpfInfoList(含 PDU Session Type 支持、DNAI 列表)。SMF 选择算法(TS 23.501 Section 6.3.3.2)正是基于这些字段做匹配。
下图用类图刻画 NFProfile 的结构骨架:
classDiagram
class NFProfile {
+nfInstanceId: UUID
+nfType: NFType
+nfStatus: NFStatus
+heartBeatTimer: int
+fqdn: string
+plmnList: PlmnId[]
+sNssais: Snssai[]
+nfProfileChangesSupportInd: bool
+nfServices: NFService[]
+smfInfo: SmfInfo
+amfInfo: AmfInfo
+upfInfo: UpfInfo
}
class NFService {
+serviceInstanceId: UUID
+serviceName: string
+versions: string[]
+scheme: string
+nfServiceStatus: NFServiceStatus
+fqdn: string
+ipEndPoints: IpEndPoint[]
}
class SmfInfo {
+sNssaiSmfInfoList: SNssaiSmfInfo[]
+taiList: Tai[]
+pgwFqdn: string
}
class UpfInfo {
+sNssaiUpfInfoList: SNssaiUpfInfo[]
}
NFProfile "1" *-- "0..*" NFService : nfServices
NFProfile "1" *-- "1" SmfInfo : smfInfo
NFProfile "1" *-- "1" UpfInfo : upfInfo
NF 启动后必须先向 NRF 自我介绍,否则在 SBA 中"不存在"。注册采用 HTTP PUT(幂等语义,URI 中携带 nfInstanceId,幂等保证 NF 重启可重复注册而不产生重复条目)。注册成功后,NRF 在响应体中返回 heartBeatTimer,NF 必须在该周期内发心跳续命;否则 NRF 标记为 SUSPENDED,从发现结果中剔除。这一软状态(soft state)机制是分布式注册中心的标准范式,目的是在 NF 异常崩溃(来不及发 DELETE 去注册)时能自动收敛,避免发现"已死的 NF"。
sequenceDiagram
participant NF as NF 实例 (如 SMF)
participant NRF as NRF
Note over NF: 1. 启动 / 重启
NF->>NRF: PUT /nnrf-nfm/v1/nf-instances/{nfInstanceId}
Note right of NF: Body: NFProfile<br/>nfType=SMF, nfStatus=REGISTERED,<br/>nfServices=[namf.../nsmf...],<br/>smfInfo={sNssaiSmfInfoList,...},<br/>nfProfileChangesSupportInd=true
NRF->>NRF: 校验 mTLS / OAuth2<br/>存储/覆盖 NFProfile
NRF-->>NF: 201 Created (或 200 OK)<br/>Body 含 heartBeatTimer=30
Note over NF,NRF: 2. 周期性心跳保活 (PUT 之前的心跳用 PATCH)
loop 每 heartBeatTimer 周期
NF->>NRF: PATCH /nnrf-nfm/v1/nf-instances/{nfInstanceId}
Note right of NF: Body: 空 或 nfProfileChangesInd=true 的增量
NRF-->>NRF: 刷新 lastHeartBeat 时间戳
alt 心跳正常
NRF-->>NF: 204 No Content
else NRF 欲调整周期
NRF-->>NF: 200 OK {heartBeatTimer: 60}
end
end
Note over NRF: 3. 心跳超时判活
NRF->>NRF: 超过 heartBeatTimer × 容忍系数 仍未收到心跳
NRF->>NRF: 将 nfStatus 置为 SUSPENDED<br/>发现查询不再返回该实例
NRF-->>NF: (异步) 触发已订阅者的 NFStatusNotify
第 1 步 — PUT 注册请求。URI /nnrf-nfm/v1/nf-instances/{nfInstanceId} 对应 TS 29.510 Section 5.2.2.2(NFRegister)。请求体是完整的 NFProfile JSON。注意几个关键字段:
nfStatus: "REGISTERED":明确声明可被发现状态;nfServices[]:列出本实例提供的每个 SBI 服务,如 SMF 会带 serviceName: "nsmf-pdusession"、scheme: "https"、versions: ["v1","v2"]、ipEndPoints;nfProfileChangesSupportInd: true:声明本 NF 支持增量更新特性(详见第五节),后续更新可用 PATCH 只传变化部分。来自真实 open5gs 抓包(sharetechnote 实录)的注册报文片段,完美印证上述结构:
[PUT] /nnrf-nfm/v1/nf-instances/0ab51768-ffcd-41ec-a11e-7954f71c156f
"nfStatus": "REGISTERED",
"nfServices": [{ "nfServiceStatus": "REGISTERED", ... }],
"nfProfileChangesSupportInd": true,
"heartBeatTimer": 10,
"nfProfileChangesInd": true
第 2 步 — NRF 响应。成功返回 201 Created(首次注册)或 200 OK(更新既有档案)。关键在于响应体携带 heartBeatTimer(单位秒),这是 NRF 下行指示给 NF 的续命周期。open5gs 默认 10 秒,商用网常见 30~60 秒。
第 3 步 — 心跳(Heart-Beat)。TS 29.510 Section 5.2.2.3.2 定义:NF 通过 PATCH /nf-instances/{nfInstanceId} 发心跳。正常情况下 NRF 返回 204 No Content;若 NRF 希望调整周期,则返回 200 OK 并在新 Body 中给出新的 heartBeatTimer,NF 必须遵从新值。
第 4 步 — 超时与 SUSPENDED。若 NRF 在 heartBeatTimer(含容忍裕量,通常实现为 1.5~3 倍)内未收到心跳,则将 nfStatus 改为 SUSPENDED,该实例不再出现在发现结果中,并异步通知所有订阅者。
NF 在调用某个服务前,需先发现"谁此刻能提供这个服务且满足我的约束"。发现采用 HTTP GET 携带查询参数(TS 29.510 Section 6.2,服务 Nnrf_NFDiscovery)。但纯拉模式(每次调用前都 GET)在高并发下会对 NRF 造成巨大压力,因此 3GPP 引入订阅/通知模式(Subscribe/Notify):消费者一次性订阅感兴趣的 NF 类型,当目标 NF 注册/状态变化时,NRF 主动推送通知,消费者本地缓存即可。两者结合,既保证实时性又分摊查询负载。
sequenceDiagram
participant AMF
participant NRF
participant SMF
Note over AMF: UE 请求建立 PDU 会话, AMF 需选择 SMF
AMF->>NRF: GET /nnrf-disc/v1/nf-instances<br/>?target-nf-type=SMF<br/>&requester-nf-type=AMF<br/>&service-names=nsmf-pdusession<br/>&target-plmn-list=460-00<br/>&sNssai=01-000001<br/>&dnn=internet
NRF-->>AMF: 200 OK<br/>Body: SearchResult=[NFProfile(SMF1),NFProfile(SMF2)]
Note over AMF: 本地缓存, 并订阅 SMF 变化
AMF->>NRF: POST /nnrf-nfm/v1/subscriptions<br/>{reqNfType:SMF, subCond,...,reqNfInstanceId,notifUri}
NRF-->>AMF: 201 Created {subscriptionId}
Note over SMF: 新 SMF 实例上线
SMF->>NRF: PUT /nf-instances/{smf3} (注册)
NRF->>NRF: 匹配 AMF 的订阅条件
NRF->>AMF: POST {notifUri} (NFStatusNotify)<br/>{nfInstance:SMF3, event:REGISTERED}
AMF-->>NRF: 204 No Content
Note over SMF: SMF 宕机, 心跳超时
NRF->>AMF: POST {notifUri} (NFStatusNotify)<br/>{nfInstance:SMF3, event:SUSPENDED}
AMF-->>NRF: 204 No Content
发现(Discovery)的查询参数直接决定返回哪些 NFProfile,是"精准选择"的第一道筛子(第二道筛子在消费者本地做选择算法)。
| 查询参数 | 作用 | 典型值 | 设计意图 |
|---|---|---|---|
target-nf-type |
要发现的目标 NF 类型(必填) | SMF / UDM / PCF | 限定范围,性能基线 |
requester-nf-type |
发起者 NF 类型 | AMF | 审计/授权,漫游场景使用 |
service-names |
目标 NF 必须提供的具体服务 | nsmf-pdusession | 精确到服务而非实例 |
target-plmn-list |
目标 PLMN | 460-00 | 漫游时锚定 HPLMN 的 UDM/PCF |
requester-plmn-list |
发起方 PLMN | 460-00 | 漫游授权校验 |
sNssai |
目标切片 | SST=01,SD=000001 | 切片感知发现核心 |
dnn |
数据网络名 | internet | SMF/UPF 按 DNN 选择 |
slice-info-request-for-pdu-session |
切片信息请求标志 | true | 触发 NRF 查 NSSF |
limit |
返回最大实例数 | 30 | 控制响应体大小、分页 |
requester-features |
发起方支持特性位图 | (hex) | 能力协商 |
target-nf-fqdn |
已知 FQDN 反查实例 | amf01... | SCP 代理场景 |
NRF 返回 200 OK,Body 为 SearchResult(即 NFProfile 数组)。消费者(如 AMF)拿到多个候选后,再依据选择算法(如 SMF 选择按 sNssaiSmfInfoList 匹配切片、按 dnn 匹配、按 taiList 匹配 UE 所在 TA、再负载均衡)挑出最终一个实例。注意:NRF 只负责"发现",不做"选择"——选择是消费者 NF 自己的逻辑(TS 23.501 Section 6.3)。
订阅用 Nnrf_NFManagement 的 NFStatusSubscribe(POST /subscriptions),通知用 NFStatusNotify(NRF 反向 POST 到消费者在订阅时填写的 notifUri)。事件类型包括:NF_REGISTERED、NF_PROFILE_CHANGED、NF_SUSPENDED、NF_DEREGISTERED。订阅时可设置 validityTime(订阅有效期,到期自动失效)、reqNfType(订阅目标类型)、subCond(订阅条件,如特定 PLMN/切片)。这一推拉结合的架构,使全网 NF 拓扑变更能在秒级传播。
R15 的 NFUpdate 用全量 PUT,每次心跳/状态变化都重传整个 NFProfile,对大 Profile(如带海量切片信息的 UPF)浪费带宽。R16 引入 nfProfileChangesSupportInd/nfProfileChangesInd 双标志位与 JSON Merge Patch(RFC 7396)机制:NF 注册时声明 nfProfileChangesSupportInd=true;后续 PATCH 时 Body 只含变化字段并置 nfProfileChangesInd=true,NRF 用 Merge Patch 语义合并。open5gs 抓包中两者同时为 true,正是启用了此优化。
NF 优雅下线时发 DELETE /nf-instances/{nfInstanceId}(TS 29.510 Section 5.2.2.4),NRF 返回 204 并向订阅者推送 NF_DEREGISTERED。非优雅下线则靠心跳超时收敛为 SUSPENDED。
容易被忽视的一点:NRF 同时承载 Nnrf_AccessToken 服务(TS 29.510 Section 5.3),扮演 OAuth2 授权服务器。任何 NF 在调用另一个 NF 的服务前,需先向 NRF POST /oauth2/token 凭 client 凭证(通常结合 mTLS 双向认证 NF 身份)换取 access token,再在后续 SBI 请求的 Authorization: Bearer <token> 头中携带。这样 5GC 的服务间调用天然具备身份认证 + 授权能力,NRF 既是目录又是签发令牌的 CA-like 角色。这也是为什么 SEPP(N32)跨运营商互联时,令牌校验是端到端安全的重要一环。
| 维度 | 5GC NRF (SBI) | DNS | 4G EPC 点对点参考点 |
|---|---|---|---|
| 解析粒度 | NF 实例 + 服务 + 切片 + DNN + 能力 | 域名 → IP | 固定网元 IP(配置) |
| 切片感知 | 原生支持(sNssai 过滤) | 不支持 | 不支持 |
| 状态感知 | 实时(心跳 + 通知) | 无(DNS 缓存) | 无 |
| 动态拓扑 | 实例弹性伸缩可即插即用 | 需 TTL 等待刷新 | 配置变更需人工 |
| 授权 | 内置 OAuth2 | 无 | 依赖网段/IP 白名单 |
| 单点风险 | NRF 集群化 + 多级 NRF(hNRF/vNRF) | DNS 任播 | 弱 |
NRF 选择自建而非直接用 DNS,根本原因是 5GC 需要切片与能力维度的细粒度、实时、可授权的发现,这些都是 DNS 不擅长的。
在核心网 SBI 接口(HTTP/2 over TLS,常见端口 443 或厂商自定义)抓包,按以下特征过滤:
http2.request.method == "PUT" 且 URI 匹配 /nnrf-nfm/v1/nf-instances/,Body 含 nfType、nfServices;http2.request.method == "PATCH" 周期性出现于同一 nfInstanceId,Body 通常极小或空;http2.request.method == "GET" 且 URI 以 /nnrf-disc/v1/nf-instances 开头,带 target-nf-type= 查询串;POST 到 notifUri(即消费方 NF 自己的服务端点),Body 含 event 字段。Wireshark 5.x 已内置 nfprofile 与 5G SBI 的 JSON 字段解析,可用 json.value == "SMF" 等过滤 NFProfile 内容。
heartBeatTimer 配置与实际心跳发送间隔。某商用网曾出现心跳间隔设为 90s 而 NRF 容忍仅 30s,导致 NF 反复"上线即掉线"。sNssai 与目标 SMF 的 sNssaiSmfInfoList 不匹配、或 target-plmn-list 写错。需对照目标 NF 实际注册的 NFProfile 逐项核对。notifUri 不可达(防火墙/NAT),或订阅 validityTime 已过期未续订。表现为调用超时后才重发现。target-plmn-list 指向的 PLMN 在对端 NRF 无注册。stateDiagram-v2
[*] --> UNREGISTERED : NF 未启动
UNREGISTERED --> REGISTERED : PUT 注册成功 (201)
REGISTERED --> REGISTERED : PATCH 心跳续命 (204)
REGISTERED --> SUSPENDED : 心跳超时
REGISTERED --> UNDISCOVERABLE : NF 主动临时隐身
SUSPENDED --> REGISTERED : PATCH 心跳恢复
SUSPENDED --> UNREGISTERED : 超时彻底清除 / DELETE
REGISTERED --> UNREGISTERED : DELETE 优雅去注册
UNDISCOVERABLE --> REGISTERED : PUT 恢复
只有 REGISTERED 状态的实例会出现在 Discovery 结果中;SUSPENDED 与 UNDISCOVERABLE 对发现不可见,但订阅通知仍会推送 NF_SUSPENDED 事件,让消费方及时清理本地缓存。
Q1:NRF 发现返回多个候选实例时,最终选哪一个? A:NRF 只负责"发现",不做"选择"。返回的 NFProfile 列表交给消费方 NF 自行运行选择算法。例如 AMF 选 SMF 依据 TS 23.501 Section 6.3.3.2:先按切片(sNssaiSmfInfoList)过滤,再按 DNN、按 UE 所在 TAI(taiList)过滤,最后在合格集合内负载均衡/亲和(如选择曾服务过该 UE 的 SMF、或同 NF Set 内成员)。
Q2:心跳(Heart-Beat)和 PUT 全量更新有什么区别?
A:心跳是轻量续命,用 PATCH 发空/极小 Body,目的仅是刷新 lastHeartBeat 时间戳,NRF 回 204。PUT 全量更新则会用整个新 NFProfile 覆盖档案。R16 后,只要双方支持 nfProfileChangesSupportInd,状态变更也应优先用 PATCH 增量(Merge Patch)而非全量 PUT,以省带宽。
Q3:为什么有时发现不到刚启动的 NF,要等几秒?
A:可能原因有三:(1) 该 NF 尚未完成 PUT 注册;(2) 消费方走的是本地缓存而非实时 GET,需等订阅通知到达才更新;(3) 经 SCP 代理时,SCP 与 NRF 间存在缓存刷新间隔。排错时应直接对 NRF 做 GET 实时发现,确认档案是否已存在且 nfStatus=REGISTERED。
Q4:NRF 和 SCP 是什么关系? A:NRF 是注册中心与授权服务器,SCP(Service Communication Proxy,TS 29.500/29.510)是通信代理。消费方可直连 NRF 发现并直连目标 NF,也可经 SCP——由 SCP 代为发现、代为取 token、代为转发甚至负载均衡(TS 29.500 Model C/D/E)。在 SCP 部署的网络里,NF 间不再有裸 NRF 调用,这对抓包排错是重要前提。
Q5:跨 PLMN 漫游时,VPLMN 的 AMF 如何发现 HPLMN 的 UDM/AUSF?
A:通过分级 NRF 体系。VPLMN 的 NRF(vNRF)收到带 target-plmn-list=HPLMN 的发现请求后,若本地无匹配,会经 N27 接口向 HPLMN 的 hNRF 转发查询(TS 29.510 Section 5.4),由 hNRF 返回 HPLMN 内的 UDM/AUSF 实例。这是 5G 漫游"Home-Routed"与"Local Breakout"架构成立的基础设施前提。
本文由「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 等场景全覆盖。
