5G核心网采用服务化架构(Service-Based Architecture, SBA),所有网络功能(Network Function, NF)之间通过RESTful HTTP/2接口进行通信。在这一架构中,NRF(Network Repository Function) 扮演着"服务总线中枢"的角色——它维护着全网NF实例的实时注册表,提供NF发现、状态通知和授权三大核心能力。
没有NRF,5GC中任何两个NF之间都无法建立通信。AMF找不到SMF、SMF找不到PCF、UDM无法被定位——整个核心网将陷入瘫痪。因此,NRF的信令机制虽然看似简单,实则是5GC最关键的基础设施之一。
本文基于 3GPP TS 29.510 V18.x(NRF服务定义)和 TS 23.502 Section 4.17(SBA通用流程),对NRF的三大核心服务操作——注册管理、NF发现、状态订阅/通知——进行完整的信令拆解。
NRF对外暴露两个SBI服务:
| 服务名称 | 服务操作 | HTTP方法 | URI路径 | TS 29.510章节 |
|---|---|---|---|---|
| Nnrf_NFManagement | NFRegister | PUT | /nnrf-nfm/v1/nf-instances/{nfInstanceID} |
5.2.2.2 |
| NFUpdate(Heartbeat) | PATCH | 同上 | 5.2.2.3 | |
| NFDeregister | DELETE | 同上 | 5.2.2.4 | |
| StatusSubscribe | POST | /nnrf-nfm/v1/subscriptions |
5.2.2.5 | |
| StatusNotify | POST | {callbackUri} |
5.2.2.6 | |
| Nnrf_NFDiscovery | NFDiscover | GET | /nnrf-disc/v1/nf-instances |
5.3.2.2 |
graph TB
subgraph "NRF服务架构"
NRF["NRF<br/>网络存储功能"]
subgraph "Nnrf_NFManagement"
REG["NF注册/注销<br/>PUT/DELETE"]
HB["心跳更新<br/>PATCH"]
SUB["状态订阅<br/>POST"]
NTY["状态通知<br/>POST callback"]
end
subgraph "Nnrf_NFDiscovery"
DISC["NF发现<br/>GET"]
end
end
AMF -->|"注册/心跳"| REG
SMF -->|"注册/心跳"| REG
UDM -->|"注册/心跳"| REG
PCF -->|"注册/心跳"| REG
AUSF -->|"注册/心跳"| REG
AMF -->|"发现SMF"| DISC
SMF -->|"发现PCF"| DISC
SMF -->|"发现UDM"| DISC
AMF -->|"订阅SMF状态"| SUB
NTY -->|"通知AMF"| AMF
REG --> NRF
HB --> NRF
DISC --> NRF
SUB --> NRF
NTF --> NRF
sequenceDiagram
participant NF as NF实例<br/>(如AMF/SMF/UDM)
participant NRF as NRF
Note over NF,NRF: Step 1: NF启动,向NRF发起注册
NF->>NRF: PUT /nnrf-nfm/v1/nf-instances/{nfInstanceID}<br/>Content-Type: application/json<br/>Body: NFProfile (JSON)
Note over NRF: 验证NFProfile完整性<br/>检查NF授权<br/>存储NFProfile
NRF-->>NF: 201 Created<br/>Body: {nfInstanceId, nfStatus, heartBeatTimer}<br/>或 200 OK (更新已有注册)
Note over NF,NRF: Step 2: 周期性心跳
loop 每隔heartBeatTimer秒
NF->>NRF: PATCH /nnrf-nfm/v1/nf-instances/{nfInstanceID}<br/>Body: {load: xx} 或空JSON
NRF-->>NF: 200 OK
Note over NRF: 重置心跳计时器
end
Note over NRF: 心跳超时处理
Note over NRF: heartBeatTimer超时 × 2~3次<br/>→ 标记NF为SUSPENDED<br/>→ 通知所有订阅者
NF在注册时需要向NRF提交完整的NFProfile,这是NRF进行服务发现匹配的核心数据结构。以下是一个典型的AMF注册消息体(来自Open5GS实测抓包):
{
"nfInstanceId": "0ab51768-ffcd-41ec-a11e-7954f71c156f",
"nfType": "AMF",
"nfStatus": "REGISTERED",
"ipv4Addresses": ["127.0.0.5"],
"allowedNfTypes": ["SMF"],
"priority": 0,
"capacity": 100,
"load": 0,
"nfServices": [{
"serviceInstanceId": "0ab6167c-ffcd-41ec-a11e-7954f71c156f",
"serviceName": "namf-comm",
"versions": [{"apiVersionInUri": "v1", "apiFullVersion": "1.0.0"}],
"scheme": "http",
"nfServiceStatus": "REGISTERED",
"ipEndPoints": [{"ipv4Address": "127.0.0.5", "port": 7777}],
"allowedNfTypes": ["SMF"],
"priority": 0,
"capacity": 100,
"load": 0
}],
"nfProfileChangesSupportInd": true
}
| IE名称 | 类型 | 必选/可选 | 说明 | 用途 |
|---|---|---|---|---|
nfInstanceId |
UUID | 必选 | NF实例唯一标识 | 区分同一类型的不同NF实例 |
nfType |
Enum | 必选 | NF类型(AMF/SMF/UDM/PCF/AUSF/NSSF等) | 发现时的基本过滤条件 |
nfStatus |
Enum | 必选 | REGISTERED/SUSPENDED/UNDISCOVERABLE | 标识NF当前可用状态 |
heartBeatTimer |
Integer | NRF返回 | 心跳间隔(秒) | NRF告知NF下次心跳发送时间 |
plmnList |
List | 可选 | 支持的PLMN ID列表 | 跨PLMN发现过滤 |
sNssais |
List | 条件必选 | 支持的S-NSSAI列表 | 切片感知发现 |
dnnList |
List | 可选 | 支持的DNN列表 | SMF发现时用于DNN匹配 |
taiList |
List | 可选 | 服务TAI列表 | 地理区域匹配 |
taiRangeList |
List | 可选 | TAI范围(支持TAC范围) | 优化大规模TAI匹配 |
priority |
Uint16 | 可选 | 优先级(0最高) | 同条件多NF时的选择依据 |
capacity |
Uint16 | 可选 | 相对容量权重 | 负载分担计算因子 |
load |
Uint16 | 可选 | 当前负载(0-100) | 实时负载感知 |
nfServices |
List | 条件必选 | 暴露的服务列表 | 服务级发现 |
allowedNfTypes |
List | 可选 | 允许发现的NF类型 | 发现授权控制 |
fqdn |
String | 可选 | NF的FQDN | DNS解析或直接寻址 |
nfSetId |
String | 可选 | NF Set标识 | NF Set内的冗余管理 |
recoveryTime |
DateTime | 可选 | NF恢复时间戳 | 故障恢复检测 |
设计意图:NFProfile采用JSON结构而非扁平参数列表,是为了支持灵活的扩展——每种NF类型可以有自己特有的扩展字段(如smfInfo、amfInfo),而NRF无需理解每种NF的具体语义,只需按属性名做精确匹配过滤。
sequenceDiagram
participant AMF as AMF<br/>(服务消费者)
participant NRF as NRF
participant SMF as SMF<br/>(被发现的NF)
Note over AMF: UE发起PDU Session Establishment<br/>AMF需要选择SMF
AMF->>NRF: GET /nnrf-disc/v1/nf-instances?<br/>target-nf-type=SMF&<br/>requester-nf-type=AMF&<br/>target-plmn-list=46000&<br/>snssais=SST:1,SD:010203&<br/>dnn=internet&<br/>tai=460-00-000001&<br/>service-names=nsmf-pdusession
Note over NRF: 1. 验证请求者AMF是否被授权发现SMF<br/>2. 按target-nf-type过滤<br/>3. 按snssais匹配SMF支持的切片<br/>4. 按dnn匹配SMF支持的DNN<br/>5. 按tai匹配SMF服务区域<br/>6. 按priority/capacity/load排序
NRF-->>AMF: 200 OK<br/>Body: SearchResult {<br/> nfInstances: [{<br/> nfInstanceId: "smf-uuid-001",<br/> nfType: "SMF",<br/> fqdn: "smf1.mnc070.mcc460.3gppnetwork.org",<br/> ipv4Addresses: ["10.0.1.5"],<br/> nfServices: [{<br/> serviceName: "nsmf-pdusession",<br/> scheme: "https",<br/> apiPrefix: "smf1",<br/> ipEndPoints: [{ipv4Address: "10.0.1.5", port: 8443}]<br/> }]<br/> }]<br/>}
Note over AMF: 选择最优SMF实例
AMF->>SMF: POST /nsmf-pdusession/v1/sm-contexts<br/>(PDU Session Establishment)
NRF在执行发现查询时,按照以下优先级逐层过滤:
| 优先级 | 过滤参数 | 匹配规则 | 说明 |
|---|---|---|---|
| 1 | target-nf-type |
精确匹配 | 最基本条件,确定NF类型 |
| 2 | requester-nf-type + 授权 |
allowedNfTypes检查 | 安全层:确保请求者有权发现目标NF |
| 3 | target-plmn-list |
PLMN ID匹配 | 跨PLMN漫游场景的关键过滤 |
| 4 | snssais |
S-NSSAI精确匹配 | 切片感知选择的核心 |
| 5 | dnn |
DNN字符串匹配 | SMF发现的关键条件 |
| 6 | tai |
TAI精确匹配或范围匹配 | 地理区域筛选 |
| 7 | service-names |
服务名称匹配 | 服务级精细发现 |
| 8 | amf-region-id/amf-set-id |
AMF Set范围匹配 | AMF Set内的SMF亲和性选择 |
| 9 | preferred-locality |
数据中心位置偏好 | 边缘计算场景的拓扑亲近性 |
| 10 | max-payload-size |
响应体大小限制 | 大规模网络的分页控制 |
设计意图:NRF发现采用声明式查询而非命令式——消费者只需描述"我需要什么样的NF",由NRF负责匹配和排序。这种设计将选择逻辑集中在NRF,使得全网NF选择策略的变更只需修改NRF配置,而不需要修改每个NF的代码。
当NRF发现多个匹配的NF实例时,返回结果的排序依据以下公式(TS 23.501 Section 6.3.1):
选择分数 = f(priority, capacity, load)
| 参数 | 权重方向 | 说明 |
|---|---|---|
priority |
值越小越优先 | 0为最高优先级,用于主备场景 |
capacity |
值越大越优先 | 相对容量,用于加权轮询计算 |
load |
值越小越优先 | 当前负载百分比,0-100 |
典型选择策略: - 主备模式:priority不同,始终选priority最低的 - 负载分担模式:priority相同,按capacity比例加权轮询 - 最小负载模式:priority相同,选load最小的
sequenceDiagram
participant AMF as AMF<br/>(订阅者)
participant NRF as NRF
participant SMF as SMF<br/>(被监控的NF)
participant PCF as PCF<br/>(另一订阅者)
Note over AMF,NRF: Step 1: AMF订阅SMF状态变更
AMF->>NRF: POST /nnrf-nfm/v1/subscriptions<br/>Body: {<br/> "nfStatusNotificationUri": "https://amf1/callback",<br/> "subscrCond": {<br/> "nfType": "SMF"<br/> },<br/> "reqNotifEvents": ["NF_REGISTERED", "NF_DEREGISTERED"],<br/> "plmnId": {"mcc": "460", "mnc": "00"}<br/>}
NRF-->>AMF: 201 Created<br/>Body: {subscriptionId: "sub-001"}
Note over PCF,NRF: Step 2: PCF也订阅SMF状态变更
PCF->>NRF: POST /nnrf-nfm/v1/subscriptions<br/>(类似内容)
NRF-->>PCF: 201 Created {subscriptionId: "sub-002"}
Note over SMF,NRF: Step 3: 新SMF注册
SMF->>NRF: PUT /nnrf-nfm/v1/nf-instances/{smf-new-uuid}<br/>Body: {nfType: SMF, ...}
NRF-->>SMF: 201 Created
Note over NRF: Step 4: NRF通知所有订阅者
NRF->>AMF: POST https://amf1/callback<br/>Body: {<br/> "event": "NF_REGISTERED",<br/> "nfInstance": {完整SMF NFProfile}<br/>}
AMF-->>NRF: 204 No Content
NRF->>PCF: POST https://pcf1/callback<br/>(同样内容)
PCF-->>NRF: 204 No Content
Note over SMF,NRF: Step 5: SMF心跳超时,被隐式注销
Note over NRF: 心跳超时 × N次<br/>→ 标记NF为SUSPENDED
NRF->>AMF: POST https://amf1/callback<br/>Body: {<br/> "event": "NF_DEREGISTERED",<br/> "nfInstanceId": "smf-new-uuid"<br/>}
AMF-->>NRF: 204 No Content
subscrCond(订阅条件)支持以下匹配模式:
| 条件类型 | JSON结构 | 触发范围 |
|---|---|---|
| 按NF类型 | {"nfType": "SMF"} |
所有SMF实例的状态变更 |
| 按NF实例 | {"nfInstanceId": "uuid-xxx"} |
仅特定NF实例 |
| 按服务名称 | {"serviceName": "nsmf-pdusession"} |
提供指定服务的NF |
| 按NF类型+切片 | {"nfType": "SMF", "sNssais": [...]} |
支持特定切片的SMF |
| 按NF Set | {"nfSetId": "smf-set-1"} |
NF Set内的实例变更 |
| 事件 | 触发条件 | 通知内容 |
|---|---|---|
NF_REGISTERED |
新NF注册或已有NF更新Profile | 完整NFProfile |
NF_DEREGISTERED |
NF显式注销或心跳超时隐式注销 | nfInstanceId |
NF_PROFILE_CHANGED |
NF通过PATCH更新了Profile | 变更的属性(增量) |
设计意图:订阅-通知模式将"轮询"转变为"推送",大幅降低了NF之间获取对端状态的信令开销。一个AMF如果需要知道全网SMF的增减情况,无需反复查询NRF,只需一次订阅,后续所有SMF的上下线事件都会自动推送到AMF。
stateDiagram-v2
[*] --> REGISTERED: PUT NFRegister<br/>(nfStatus=REGISTERED)
REGISTERED --> REGISTERED: PATCH Heartbeat<br/>(心跳正常)
REGISTERED --> SUSPENDED: 心跳超时<br/>(heartBeatTimer × N)
REGISTERED --> UNDISCOVERABLE: PATCH<br/>(nfStatus=UNDISCOVERABLE)
SUSPENDED --> REGISTERED: PATCH Heartbeat<br/>(恢复心跳)
UNDISCOVERABLE --> REGISTERED: PATCH<br/>(nfStatus=REGISTERED)
REGISTERED --> [*]: DELETE NFDeregister<br/>(显式注销)
SUSPENDED --> [*]: NRF清理<br/>(超时清理)
根据TS 29.510 Section 5.2.2.2.3,心跳超时的处理如下:
heartBeatTimer值(通常10~30秒)heartBeatTimer到期前发送PATCH请求(心跳)heartBeatTimer到期后未收到心跳:
- 不立即注销,而是等待一个额外的宽限时间
- 宽限时间通常为heartBeatTimer的2~3倍SUSPENDED
- 向所有订阅该NF状态的消费者发送NF_DEREGISTERED通知
- 从发现查询结果中排除该NF实例| 阶段 | 计时器 | 超时动作 |
|---|---|---|
| 心跳窗口 | heartBeatTimer(首次由NRF分配) |
进入宽限期 |
| 宽限期 | heartBeatTimer × 2~3(实现相关) |
标记SUSPENDED,通知订阅者 |
| 清理期 | 实现相关(通常数分钟) | 从NRF存储中完全删除NF Profile |
3GPP R16引入了SCP(Service Communication Proxy),定义了四种通信模型:
| 模型 | NF→NRF | NF→NF | 发现方式 | 适用场景 |
|---|---|---|---|---|
| Model A | 直连 | 直连 | NF直接查NRF | 小型网络/实验室 |
| Model B | 直连 | 经SCP代理 | NF直接查NRF | 仅数据面代理 |
| Model C | 经SCP | 经SCP | NF直接查NRF | 完全代理但NF自行发现 |
| Model D | 经SCP | 经SCP | SCP代为发现(Delegated) | 大规模网络,NF无需知道NRF地址 |
Model D的核心优势:NF完全不感知NRF的存在,所有发现请求由SCP代为执行。NF只需向SCP发送请求并携带目标NF类型,SCP内部完成NRF查询、实例选择和请求转发。这极大简化了NF的实现复杂度。
在5GC抓包中识别NRF相关信令的关键特征:
| 操作 | HTTP方法 | URI特征 | 关键Header |
|---|---|---|---|
| NF注册 | PUT | 包含/nnrf-nfm/v1/nf-instances/ + UUID |
Content-Type: application/json |
| 心跳 | PATCH | 同上 | Body通常只有{"load": xx} |
| 发现 | GET | 包含/nnrf-disc/v1/nf-instances? + 查询参数 |
无Body |
| 订阅 | POST | 包含/nnrf-nfm/v1/subscriptions |
Content-Type: application/json |
| 通知 | POST | URI为NF注册的callbackUri | 由NRF主动发起 |
tcpdump/Wireshark过滤规则:
# 过滤NRF相关HTTP/2流量(假设NRF端口为8443)
tcp port 8443
# Wireshark HTTP/2过滤器
http2.headers.path contains "nnrf-nfm" or http2.headers.path contains "nnrf-disc"
| 故障现象 | 可能原因 | 排错步骤 |
|---|---|---|
| NF发现返回空结果 | NF未注册或已SUSPENDED | 1. 检查目标NF是否成功注册(GET /nnrf-nfm/v1/nf-instances/{uuid}) 2. 检查心跳是否正常 3. 检查发现请求的过滤参数是否与NF Profile匹配 |
| NF频繁被隐式注销 | 心跳发送间隔过长或网络抖动 | 1. 检查NF的heartBeatTimer配置2. 检查NF与NRF之间的网络连通性 3. 查看NRF日志中的心跳超时记录 |
| 发现返回的NF实例不可达 | NF Profile中的IP/FQDN过期 | 1. 验证NF Profile中的ipv4Addresses和fqdn是否可达2. 检查DNS解析是否正确 3. 检查防火墙/安全组规则 |
| 跨PLMN发现失败 | SEPP或NRF路由配置错误 | 1. 检查NRF间N27接口连通性 2. 检查 target-plmn-list参数3. 检查SEPP策略是否允许跨PLMN发现 |
| 订阅通知丢失 | callbackUri不可达 | 1. 检查订阅者的callbackUri是否可达 2. 检查NRF重传机制 3. 查看NRF通知发送日志 |
| ## 9. 完整信令流示例:AMF注册→SMF发现→PDU会话建立 |
sequenceDiagram
participant AMF as AMF
participant NRF as NRF
participant SMF as SMF
rect rgb(230, 245, 255)
Note over AMF,SMF: 阶段1: AMF启动注册
AMF->>NRF: PUT /nnrf-nfm/v1/nf-instances/{amf-uuid}<br/>{nfType:AMF, nfServices:[namf-comm], ...}
NRF-->>AMF: 201 Created {heartBeatTimer: 30}
end
rect rgb(230, 255, 230)
Note over AMF,SMF: 阶段2: SMF启动注册
SMF->>NRF: PUT /nnrf-nfm/v1/nf-instances/{smf-uuid}<br/>{nfType:SMF, sNssais:[SST:1], dnnList:[internet], ...}
NRF-->>SMF: 201 Created {heartBeatTimer: 30}
end
rect rgb(255, 245, 230)
Note over AMF,SMF: 阶段3: AMF订阅SMF状态
AMF->>NRF: POST /nnrf-nfm/v1/subscriptions<br/>{subscrCond:{nfType:SMF}, ...}
NRF-->>AMF: 201 Created {subscriptionId: sub-001}
end
rect rgb(255, 230, 230)
Note over AMF,SMF: 阶段4: UE触发PDU Session,AMF发现SMF
AMF->>NRF: GET /nnrf-disc/v1/nf-instances?<br/>target-nf-type=SMF&snssais=SST:1&dnn=internet
NRF-->>AMF: 200 OK {[smf-uuid, fqdn:smf1, ip:10.0.1.5]}
AMF->>SMF: POST /nsmf-pdusession/v1/sm-contexts
SMF-->>AMF: 201 Created {smContextRef}
end
rect rgb(240, 230, 255)
Note over AMF,SMF: 阶段5: 周期性心跳维持
loop 每30秒
AMF->>NRF: PATCH /nnrf-nfm/v1/nf-instances/{amf-uuid}<br/>{load: 25}
NRF-->>AMF: 200 OK
SMF->>NRF: PATCH /nnrf-nfm/v1/nf-instances/{smf-uuid}<br/>{load: 40}
NRF-->>SMF: 200 OK
end
end
Q1: NRF单点故障如何处理?
A: NRF本身需要高可用部署。业界通常采用以下方案: - 主备NRF:多个NRF实例共享后端数据库(如MongoDB/Redis),任一NRF实例故障不影响全局 - NRF分级:PLMN级NRF + 区域级NRF,分权管理 - NF本地缓存:NF缓存已发现的NF Profile(带TTL),即使NRF短暂不可用,已有的NF间通信不受影响 - 3GPP R18进一步增强了NRF的弹性机制,支持NRF间的状态同步
Q2: NF发现和DNS解析有什么区别?为什么不直接用DNS?
A: 二者定位完全不同: - DNS:只能做FQDN→IP的简单解析,无法感知NF的切片能力、负载状态、地理覆盖范围等属性 - NRF发现:基于多维度属性(S-NSSAI、DNN、TAI、负载、优先级等)的精确匹配和排序,是5G SBA的"智能服务总线" - 实际部署中,NRF发现的响应中可能包含FQDN,NF拿到FQDN后再通过DNS解析获取IP地址——二者是协作关系而非替代关系
Q3: heartBeatTimer设置多大合适?
A: 取决于网络规模和可靠性要求: - 小型网络(<100个NF):30~60秒,信令开销小 - 中型网络(100~1000个NF):10~30秒,平衡及时性和开销 - 大型网络(>1000个NF):5~10秒,需要快速感知NF故障 - 过短会导致NRF信令风暴,过长会导致故障NF长时间不被发现 - 实际配置还需考虑NF实例数量 × 心跳间隔 = NRF每秒需处理的心跳请求数
Q4: NRF发现中的授权机制如何工作?
A: 分为两层:
1. allowedNfTypes:NF在注册时声明自己允许被哪些NF类型发现。例如,AUSF注册时设置allowedNfTypes: ["AMF"],则只有AMF能发现该AUSF
2. OAuth 2.0:R16+要求NF在访问NRF时携带access token,NRF验证token中的scope和NF type是否匹配
3. 两层机制叠加——即使NF发送了发现请求,如果其类型不在目标NF的allowedNfTypes列表中,NRF也会返回空结果或拒绝
Q5: Model D中NF如何做到完全不感知NRF?
A: 在Model D(Indirect Communication with Delegated Discovery)中:
- NF只需知道SCP的地址
- NF向SCP发送请求时,在HTTP Header中携带3gpp-Sbi-Target-Nf-Type(如SMF)
- SCP收到请求后,内部向NRF发起发现查询,选择最优的SMF实例
- SCP将请求转发到选定的SMF,将响应返回给NF
- NF完全不知道SMF的实际地址和NRF的存在——这是大规模网络运营商最偏好的模式
本文由「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 等场景全覆盖。
