5GC实践篇之BSF篇第3篇:BSF服务注册更新
作者:爱卫生
1 测试背景与用例简介
在前面的两篇文章中,我们分别剖析了BSF的"诞生"(服务注册)和"消失"(服务去注册)。本篇则关注BSF生命周期中另一个常见且重要的操作——服务注册更新(NF Update)。
在5GC的实际运营中,BSF的配置并不是一成不变的。运营商可能因为以下原因需要修改BSF的NFProfile:
- 扩大服务范围:新增BSF负责的IP地址段(如扩容用户、新增DNN);
《5G核心网原理与实践》实践篇 · BSF 网元功能
作者:爱卫生
在前面的两篇文章中,我们分别剖析了BSF的"诞生"(服务注册)和"消失"(服务去注册)。本篇则关注BSF生命周期中另一个常见且重要的操作——服务注册更新(NF Update)。
在5GC的实际运营中,BSF的配置并不是一成不变的。运营商可能因为以下原因需要修改BSF的NFProfile:
缩减服务范围:移除某些IP地址段(如网络优化、地址池回收);
服务能力变更:升级API版本、修改服务端口、增加新的服务能力;
网络拓扑调整:BSF迁移到新的IP地址或端口。
以上任何变更发生后,BSF都必须主动向NRF更新其NFProfile,确保NRF中存储的信息始终与BSF的实际配置一致。如果NFProfile未及时更新,可能导致:
PCF通过NRF发现到BSF时,使用了错误的IP地址或端口;
NRF无法将特定IP地址的查询请求正确路由到BSF(地址段信息过时);
新增的DNN对应的策略绑定请求无法被正确处理。
BSF服务注册更新是指BSF使用HTTP PUT方法,向NRF重新发送完整的NFProfile,以替换NRF中已有的旧NFProfile。这个操作对应SBI接口 Nnrf_NFManagement_NFUpdate。
注意,这里使用的是与初始注册相同的HTTP PUT方法和相同的URI格式。区别在于:
注册:nfInstanceID是新的,NRF创建新记录;
更新:nfInstanceID已存在,NRF覆盖旧记录。
本篇以一个典型的实际场景为例:运维人员在BSF上新增一个IPv6地址段,BSF自动向NRF发起NFProfile更新,将新的IPv6前缀范围同步到NRF中。
sequenceDiagram
participant OPS as 运维操作
participant BSF
participant NRF
Note over OPS, NRF: 运维人员在BSF上新增IPv6地址段配置
OPS->>BSF: 修改配置: 新增IPv6前缀范围
Note over BSF: BSF检测到配置变更
Note over BSF: 重构NFProfile
BSF->>NRF: PUT /nnrf-nfm/v1/nf-instances/{nfInstanceID}
Note right of BSF: 请求体含更新后的NFProfile:
Note right of BSF: 新增了ipv6PrefixRanges条目
NRF-->>NRF: 根据nfInstanceID查找已有NFProfile
NRF-->>NRF: 用新NFProfile覆盖旧记录
NRF-->>BSF: 200 OK
Note left of NRF: 响应体含NFRegistrationData:
Note left of NRF: heartBeatTimer
Note left of NRF: 更新后的NFProfile
flowchart LR
A["运维修改BSF配置"] --> B["BSF重构NFProfile"]
B --> C["PUT /nnrf-nfm/v1/nf-instances/nfInstanceID"]
C --> D["NRF查找已有NFProfile"]
D --> E["NRF用新Profile覆盖旧Profile"]
E --> F["NRF返回200 OK"]
F --> G["BSF更新完成"]
style A fill:#fff3e0,stroke:#e65100,stroke-width:2px
style G fill:#c8e6c9,stroke:#2e7d32,stroke-width:3px
验证NRF支持BSF发起的服务注册更新流程,确保BSF能够成功更新其在NRF中的NFProfile信息。
SA网络中BSF和NRF网元系统及操作维护台运行正常。
BSF已在NRF中成功完成初始服务注册。
服务化接口的信令监控、抓包分析工具准备就绪。
在BSF上修改会话绑定的IP地址段数据配置,增加BSF服务支持的IPv6地址段。
观察BSF和NRF之间的消息交互。
在NRF上查看BSF服务更新情况(对比更新前后的NFProfile)。
消息1(BSF -> NRF,PUT请求)检查项:
| 检查项 | 预期结果 |
|---|---|
| PUT消息的URI | {apiRoot}/nnrf-nfm/v1/nf-instances/{nfInstanceID},与实际环境一致 |
|---|---|
| NFProfile内容 | 与修改后的配置一致(包含新增的IPv6地址段) |
NFProfile详细字段检查:
| 属性 | 预期结果 |
|---|---|
| nfInstanceID | 与实际配置保持一致 |
| nfType | BSF |
| nfStatus | REGISTERED |
| serviceInstanceID | 与实际配置保持一致 |
| serviceName | nbsf_management |
| version | 与实际配置保持一致 |
| schema | http |
| ipEndPoints | nbsf_management的服务IP和Port |
| bsfInfo.ipv4AddressRanges | 提供服务的IPv4地址段(不变) |
| bsfInfo.ipv6PrefixRanges | 原有IPv6地址段 + 新增的IPv6地址段 |
消息2(NRF -> BSF,响应)检查项:
| 检查项 | 预期结果 |
|---|---|
| statusCode | 200 OK(注意:不是注册时的201 Created) |
| 头域 | 包含Location |
| Body | 包含NFRegistrationData(含heartBeatTimer和更新后的NFProfile) |
本测试的核心场景是:BSF已注册并运行,运维人员新增一个IPv6前缀范围后,BSF自动向NRF更新其NFProfile。
(注:为保护网络安全,以下log中的网元IP、NF Instance ID等敏感信息已做严格脱敏处理)
在发起更新之前,我们先通过NRF查询接口查看BSF当前的NFProfile,确认更新前的IPv6前缀范围配置:
更新前的IPv6PrefixRanges查询结果:
$ curl -X GET http://10.XX.XX.XX:31380/nnrf-nfm/v1/nf-instances/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX | python -mjson.tool
# 重点关注bsfInfo中的ipv6PrefixRanges字段:
"bsfInfo": {
"ipv6PrefixRanges": [
{
"start": "2a01:172:253::0/64",
"end": "2a01:172:253:ffff::0/64"
},
{
"start": "2a01:9:2::0/64",
"end": "2a01:9:2:ffff::0/64"
},
{
"start": "2a01:9:3::0/64",
"end": "2a01:9:3:ffff::0/64"
},
{
"start": "2a01:9:4::0/64",
"end": "2a01:9:4:ffff::0/64"
}
]
}
可以看到,更新前BSF注册了4条IPv6前缀范围。
运维人员在BSF上新增一条IPv6前缀范围:2b01:9:2::0/64 ~ 2b01:9:2:ffff::0/64。BSF检测到配置变更后,自动重构NFProfile并向NRF发起PUT更新请求。
sequenceDiagram
participant BSF
participant NRF
Note over BSF, NRF: Nnrf_NFManagement_NFUpdate
BSF->>NRF: PUT /nnrf-nfm/v1/nf-instances/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
Note right of BSF: 请求体(更新后的NFProfile):
Note right of BSF: nfInstanceID: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
Note right of BSF: nfType: BSF
Note right of BSF: nfStatus: REGISTERED
Note right of BSF: bsfInfo.ipv6PrefixRanges: 4条原有 + 1条新增
NRF-->>NRF: 查找nfInstanceID对应的已有记录
NRF-->>NRF: 用新NFProfile完全替换旧记录
NRF-->>BSF: 200 OK
Note left of NRF: 响应含NFRegistrationData
Note left of NRF: heartBeatTimer: XX秒
Note left of NRF: NFProfile: 更新后的完整Profile
信令抓包解析:
# 1. BSF -> NRF(发起NFProfile更新 PUT请求)
PUT /nnrf-nfm/v1/nf-instances/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX HTTP/1.1
Host: 10.XX.XX.XX:31380
Content-Type: application/json
JavaScript Object Notation: application/json
Object
# ===== NF基本信息 =====
Member Key: nfInstanceID
String value: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
# BSF的NF实例ID,与初始注册时一致
Member Key: nfType
String value: "BSF"
Member Key: nfStatus
String value: "REGISTERED"
Member Key: serviceInstanceID
String value: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
# ===== NF服务信息 =====
Member Key: nfServices
Array
Object
Member Key: serviceName
String value: "nbsf_management"
Member Key: scheme
String value: "http"
Member Key: ipEndPoints
Array
Object
Member Key: ipv4Address
String value: "10.XX.XX.XX"
Member Key: port
Number value: 8080
# ===== BSF特有信息(已更新) =====
Member Key: bsfInfo
Object
Member Key: ipv4AddressRanges
Array
Object
Member Key: start
String value: "10.XX.0.0"
Member Key: end
String value: "10.XX.255.255"
Member Key: ipv6PrefixRanges
Array
# --- 原有4条IPv6前缀 ---
Object
Member Key: start
String value: "2a01:172:253::0/64"
Member Key: end
String value: "2a01:172:253:ffff::0/64"
Object
Member Key: start
String value: "2a01:9:2::0/64"
Member Key: end
String value: "2a01:9:2:ffff::0/64"
Object
Member Key: start
String value: "2a01:9:3::0/64"
Member Key: end
String value: "2a01:9:3:ffff::0/64"
Object
Member Key: start
String value: "2a01:9:4::0/64"
Member Key: end
String value: "2a01:9:4:ffff::0/64"
# --- 新增第5条IPv6前缀 ---
Object
Member Key: start
String value: "2b01:9:2::0/64"
# 新增IPv6前缀起始地址
Member Key: end
String value: "2b01:9:2:ffff::0/64"
# 新增IPv6前缀结束地址
关键变化点:
| 字段 | 更新前 | 更新后 |
|---|---|---|
ipv6PrefixRanges条目数 |
4条 | 5条 |
|---|---|---|
| 新增条目 | 无 | 2b01:9:2::0/64 ~ 2b01:9:2:ffff::0/64 |
ipv4AddressRanges |
不变 | 不变 |
nfServices |
不变 | 不变 |
协议参考:根据3GPP TS 29.510 第6.1.6.2节,NF Profile更新使用与初始注册相同的PUT方法和URI。当NRF发现URI中的nfInstanceID已存在于本地数据库时,会执行更新操作而非新建。
NRF收到BSF的PUT更新请求后,执行以下操作:
查找已有记录:根据URI中的nfInstanceID在本地数据库中查找已注册的NFProfile;
替换NFProfile:用新的NFProfile完全替换旧的NFProfile(全量更新,非增量更新);
返回响应:向BSF返回200 OK(注意:不是注册时的201 Created),携带更新后的信息。
信令抓包解析:
# 2. NRF -> BSF(更新成功响应)
HTTP/1.1 200 OK
Location: http://10.XX.XX.XX:31380/nnrf-nfm/v1/nf-instances/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
Content-Type: application/json
JavaScript Object Notation: application/json
Object
Member Key: heartBeatTimer
Number value: XX
# 心跳定时器时长(秒)
Member Key: nfProfile
Object
# 返回更新后的完整NFProfile
Member Key: nfInstanceID
String value: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
Member Key: nfType
String value: "BSF"
Member Key: nfStatus
String value: "REGISTERED"
# ... 包含更新后的bsfInfo(5条IPv6前缀)
注册 vs 更新的响应码对比:
| 操作 | HTTP状态码 | 含义 |
|---|---|---|
| 首次注册 | 201 Created | 资源被创建 |
| 更新注册 | 200 OK | 资源被更新 |
协议参考:根据3GPP TS 29.510 第6.1.6.2节,NRF在执行NF Profile更新成功后返回200 OK,响应体包含
NFRegistrationData。heartBeatTimer字段可能会与初始注册时不同——NRF有权在每次更新时调整心跳周期。
更新成功后,我们再次通过NRF查询接口验证BSF的NFProfile是否已正确更新。
更新后的IPv6PrefixRanges查询结果:
$ curl -X GET http://10.XX.XX.XX:31380/nnrf-nfm/v1/nf-instances/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX | python -mjson.tool
# 重点关注bsfInfo中的ipv6PrefixRanges字段:
"bsfInfo": {
"ipv6PrefixRanges": [
{
"start": "2a01:172:253::0/64",
"end": "2a01:172:253:ffff::0/64"
},
{
"start": "2a01:9:2::0/64",
"end": "2a01:9:2:ffff::0/64"
},
{
"start": "2a01:9:3::0/64",
"end": "2a01:9:3:ffff::0/64"
},
{
"start": "2a01:9:4::0/64",
"end": "2a01:9:4:ffff::0/64"
},
{
"start": "2b01:9:2::0/64",
"end": "2b01:9:2:ffff::0/64"
}
]
}
可以看到,更新后BSF的ipv6PrefixRanges已从4条增加到5条,新增的第5条2b01:9:2::0/64已成功注册到NRF中。
更新前后对比:
flowchart TD
subgraph 更新前
A1["ipv6PrefixRanges: 4条"]
A2["2a01:172:253::0/64"]
A3["2a01:9:2::0/64"]
A4["2a01:9:3::0/64"]
A5["2a01:9:4::0/64"]
end
subgraph 更新后
B1["ipv6PrefixRanges: 5条"]
B2["2a01:172:253::0/64 - 不变"]
B3["2a01:9:2::0/64 - 不变"]
B4["2a01:9:3::0/64 - 不变"]
B5["2a01:9:4::0/64 - 不变"]
B6["2b01:9:2::0/64 - 新增"]
end
style B6 fill:#c8e6c9,stroke:#2e7d32,stroke-width:3px
在3GPP TS 29.510规范中,NF Profile更新有两种实现方式:
| 方式 | HTTP方法 | 说明 |
|---|---|---|
| 全量更新(Full Update) | PUT | 发送完整NFProfile,NRF完全替换旧记录 |
|---|---|---|
| 增量更新(Partial Update) | PATCH | 仅发送需要修改的字段,NRF合并更新 |
本测试中,BSF使用的是PUT全量更新方式——每次更新都发送完整的NFProfile,NRF用新Profile完全覆盖旧Profile。这种方式的优缺点:
全量更新(PUT)的优点:
实现简单,不需要复杂的字段级合并逻辑;
不会出现"旧字段残留"的问题;
天然幂等——多次发送相同请求结果一致。
全量更新(PUT)的缺点:
消息体较大,即使只修改一个字段也需要发送完整NFProfile;
网络带宽消耗较高,尤其当NFProfile包含大量地址段时。
增量更新(PATCH)的应用场景:
心跳检测就是使用PATCH方法进行增量更新的典型场景(将在第5篇详细讨论)。PATCH方法只修改特定字段(如nfStatus),不影响其他字段。
协议参考:根据3GPP TS 29.510 第6.1.6.2节,PUT方法用于NF Profile的全量更新(Full Update),NRF应使用新收到的NFProfile完全替换已有记录。PATCH方法用于部分更新(Partial Update),仅修改指定字段。
1) 更新期间的服务可用性
在BSF向NRF发送PUT更新请求的短暂时间内(通常几十毫秒),NRF中的NFProfile处于"旧版即将被新版替换"的过渡状态。在此期间,如果有其他NF通过NRF发现该BSF,可能看到的是旧版NFProfile。但在实际网络中,这个时间窗口极短,通常不会造成问题。
2) 更新不影响已有会话
BSF更新NFProfile(如新增IPv6地址段)不会影响已经建立的AF-PCF绑定关系。已有的绑定信息存储在BSF内部,与NRF中的NFProfile无关。NFProfile的作用仅是让其他NF能够发现和找到BSF。
3) 地址段重叠问题
新增的IPv6地址段不能与已有地址段重叠,否则NRF在进行服务发现匹配时可能返回多个BSF实例,导致结果不确定。运营商在配置新增地址段时需要仔细规划,避免地址段冲突。
正确的地址段配置:
BSF-1: 2a01:9:2::0/64 ~ 2a01:9:2:ffff::0/64
BSF-2: 2a01:9:5::0/64 ~ 2a01:9:5:ffff::0/64
→ 无重叠,NRF匹配结果唯一
错误的地址段配置:
BSF-1: 2a01:9:2::0/64 ~ 2a01:9:2:ffff::0/64
BSF-2: 2a01:9:2:8000::0/64 ~ 2a01:9:2:ffff::0/64
→ 有重叠,NRF可能返回两个BSF
4) 更新触发时机
BSF的NFProfile更新通常由以下事件触发:
| 触发事件 | 更新内容 |
|---|---|
| 运维修改IP地址段配置 | bsfInfo.ipv4AddressRanges/ipv6PrefixRanges |
| 运维修改DNN配置 | bsfInfo.dnnList |
| BSF API版本升级 | nfServices.versions |
| BSF IP/端口迁移 | nfServices.ipEndPoints |
| 负载均衡策略调整 | loadLevelAvg等负载信息 |
| 验证项 | 结果 | 说明 |
|---|---|---|
| BSF服务注册更新成功 | OK | NRF成功更新BSF的NFProfile |
| PUT消息URI正确 | OK | 格式为/nnrf-nfm/v1/nf-instances/{nfInstanceID} |
| NFProfile内容正确 | OK | 包含原有4条+新增1条IPv6前缀 |
| NRF返回200 OK | OK | 更新成功(区别于注册时的201 Created) |
| 更新前后对比验证 | OK | ipv6PrefixRanges从4条增加到5条 |
本测试用例完美通过。BSF在运维人员新增IPv6前缀范围后,通过Nnrf_NFManagement_NFUpdate服务(HTTP PUT)成功向NRF更新了自身的NFProfile。NRF返回200 OK确认更新成功。通过更新前后的NRF查询对比,确认新增的IPv6前缀2b01:9:2::0/64已成功注册到NRF中,且原有配置信息未被破坏。整个更新流程与3GPP TS 29.510和TS 29.551规范完全吻合。
协议参考汇总:
3GPP TS 29.510 第6.1.6.2节:NF Profile Update流程
3GPP TS 29.551:BSF Service-Based Interface,bsfInfo数据结构
关于作者:爱卫生,从事通信教学18年,出版过《5G核心网原理与实践》等4本专业书籍。学5G核心网、IMS,来51学通信就对了!知识星球:200+小时视频、3000+精华文章、1年答疑群。公众号/知识星球:51学通信,微信:gprshome201101