好的,我们继续沿着3GPP TS 29.673的规范文本,从第六章的基础通信规则,深入到API资源的具体定义。这是对第六章的第二部分深度解析,我们将开始绘制Nucmf_UECapabilityManagement API的“藏宝图”。

深度解析 3GPP TS 29.673:6.1.3 API Resources (Part 2 - 字典资源模型与集合操作)

本文技术原理深度参考了3GPP TS 29.673 V18.4.0 (2024-06) Release 18规范中,第六章“API Definitions”的核心部分,重点解读6.1.3.1节(Overview)和6.1.3.2节(Resource: Dictionary Entries)。本文旨在为读者呈现Nucmf_UECapabilityManagement API的完整资源地图,并深度剖析其最重要的资源——字典条目集合(/dic-entries)的查询(GET)与创建(POST)操作。

引言:从“语法”到“词汇”——绘制API的资源地图

在上一篇文章中,我们掌握了与UCMF沟通的“语法规则”:我们知道了必须使用HTTP/2协议,数据要用JSON和multipart格式封装,URI地址遵循统一的结构。现在,是时候学习这门语言的“核心词汇”了——API资源(Resources)。

API资源是服务化接口的核心,它们是我们可以操作的具体“名词”。第六章的6.1.3节,就像是UCMF这座信息大厦的建筑蓝图,它清晰地标示出了每一个功能房间(资源)的位置、门牌号(URI),以及我们可以在每个房间里做什么(HTTP方法)。

作为构建5G核心网的工程师,我们现在手持这份蓝图,准备对UCMF最重要的一个区域——“字典条目档案馆(/dic-entries)”进行一次全面的勘查。我们将学习如何在这座档案馆里,通过标准的HTTP操作,实现我们在第五章学到的Resolve(查询案卷)和Assign(建立新案卷)两大核心功能。


1. 解读第6.1.3.1章 Overview (API资源概览) - UCMF的“楼层索引”

本节为我们提供了整个API的顶层视图,通过一张结构图和一张总览表,让我们对UCMF提供的所有资源及其支持的操作一目了然。

1.1 资源URI结构图剖析

规范中的“Figure 6.1.3.1-1: Resource URI structure of the Nucmf_UECapabilityManagement API”是我们的API导航地图。

如下文所述,规范原文中的“Figure 6.1.3.1-1”清晰地描绘了API的层次结构:

  • 根节点: {apiRoot}/nucmf-ucm/<apiVersion>,这是所有资源的统一入口,我们在上一章已经详细解读过。
  • 两大主分支: 从根节点延伸出两个主要的分支,代表了UCMF的两大核心资源集合:
    • /dic-entries: 字典条目集合。这是UCMF最核心的数据资源,代表了整个“能力字典”。
    • /subscriptions: 订阅集合。这代表了所有由NF消费者创建的订阅关系。
  • 叶子节点: 每个主分支下又可以访问具体的单个资源:
    • /{dicEntryId}: 代表一个单个的、具体的字典条目。
    • /{subscriptionId}: 代表一个单个的、具体的订阅。

这张图告诉我们,UCMF的API设计遵循了清晰的“集合-成员”的RESTful模式,结构非常规整,易于理解和使用。

1.2 资源与方法总览表剖析

Table 6.1.3.1-1: Resources and methods overview”是这张地图的“图例”,它将资源、HTTP方法和我们在第五章学到的服务操作完美地对应了起来。

Resource nameResource URIHTTP method or custom operationDescription
Dictionary Entries collection/dic-entriesPOSTNucmf_UECapabilityManagement_Assign
GETNucmf_UECapabilityManagement_Resolve
Individual Dictionary Entry/dic-entries/{dicEntryId}GETNucmf_UECapabilityManagement_Resolve
Subscriptions collection/subscriptionsPOSTNucmf_UECapabilityManagement_Subscribe
Individual subscription/subscriptions/{subscriptionId}DELETENucmf_UECapabilityManagement_Unsubscribe

这张表是连接“功能逻辑”与“协议实现”的桥梁,我们必须深刻理解每一行:

  • POST /dic-entries: 在字典条目集合上执行POST操作,其功能正是我们熟悉的Assign(分配新ID)。
  • GET /dic-entries: 在字典条目集合上执行GET操作,这是Resolve(解析ID)的第一种模式,即通过查询参数来筛选。
  • GET /dic-entries/{dicEntryId}: 在单个字典条目上执行GET,这是Resolve的第二种模式,通过唯一标识直接获取。
  • POST /subscriptions: 在订阅集合上执行POST,实现了Subscribe(创建新订阅)功能。
  • DELETE /subscriptions/{subscriptionId}: 在单个订阅上执行DELETE,实现了Unsubscribe(删除订阅)功能。

有了这份总览,我们就可以开始逐一深入每个资源的细节了。


2. 解读第6.1.3.2章 Resource: Dictionary Entries (字典条目集合资源)

这是UCMF API中最核心、最繁忙的资源端点。所有能力的查询和创建都始于此。

2.1 6.1.3.2.1 Description (资源描述)

3GPP TS 29.673 - 6.1.3.2.1 Description

This resource represents the collection of the individual dictionary entries created in the UCMF, where each individual dictionary entry includes the mapping information between UE Radio Capability ID and UE Radio Access Capability Information, Type Allocation Code and Software version of a PEI.

这段描述强调,/dic-entries代表的是所有字典条目的集合(collection)。它是一个容器,而不是单个条目。每个条目内部则包含了ID、能力信息、TAC码和软件版本等丰富的映射信息。

2.2 6.1.3.2.2 Resource Definition (资源定义)

Resource URI: {apiRoot}/nucmf-ucm/<apiVersion>/dic-entries

这里明确了该资源的完整URI。规范还通过 Table 6.1.3.2.2-1 指出,其中的apiRootapiVersion变量的定义遵循6.1.1节的规定。

2.3 6.1.3.2.3 Resource Standard Methods (资源标准方法)

本节详细定义了可以在/dic-entries这个集合资源上执行的标准HTTP方法。

GET 方法 (实现Resolve操作)

这是实现“按ue-radio-capa-id解析能力”功能的具体协议。

  • URI查询参数: Table 6.1.3.2.3.1-1: URI query parameters supported by the GET method on this resource 是实现精确查询的关键。
NameData typePCardinalityDescriptionApplicability
ue-radio-capa-idUeRadioCapIdM1PLMN assigned or Manufacturer assigned UE Radio Capability ID used to retrieve a dictionary entry.
rac-formatRacFormatC0..1Coding format in which UE Radio Access Capability Information needs to be provided. See the clause 6.1.6.3.4.
supported-featuresSupportedFeatu resC0..1This IE shall be present if at least one feature defined in clause 6.1.8 is supported.

参数深度剖析:

  • ue-radio-capa-id (M, Mandatory): 必须携带。这就是AMF从UE收到的那个能力ID。一个真实的请求URL会是 .../dic-entries?ue-radio-capa-id=some-id-string

  • rac-format (C, Conditional): 条件可选RacFormat是一个枚举类型,可能的值为"5GS""EPS"。AMF可以用这个参数明确告诉UCMF:“我只对这份能力的5G部分感兴趣,请只返回5G的能力信息给我”。这可以减少不必要的数据传输,尤其是在纯5G场景下。

  • supported-features: 用于特性协商,允许客户端(AMF)声明自己支持的、由本规范定义的额外特性,以便服务器(UCMF)能够返回兼容的响应。

  • 响应体 (Response Body): Table 6.1.3.2.3.1-3: Data structures supported by the GET Response Body on this resource 定义了所有可能的返回结果。

Data typePCardinalityResponse codesDescription
DicEntryDataM1200 OKThe response body contains a dictionary entry that is matching the querying parameter.
RedirectResponseO0..1307 Temporary RedirectTemporary redirection.
RedirectResponseO0..1308 Permanent RedirectPermanent redirection.
ProblemDetailsO0..1400 Bad RequestThe response body contains the error reason of the request message.
ProblemDetailsO0..1404 Not FoundThe “cause” attribute may be used to indicate… NO_DICTIONARY_ENTRY_FOUND

响应深度剖析:

  • 200 OK: 查询成功。响应体是一个DicEntryData对象,其中包含了完整的映射信息。这就是Resolve操作的Happy Path。
  • 404 Not Found: 查询失败,字典里没有这个ID。响应体是一个ProblemDetails对象,其cause字段会被设置为NO_DICTIONARY_ENTRY_FOUND,提供了精确的、机器可读的失败原因。
  • 307/308 Redirect: 用于UCMF集群内部的请求转发,我们在前文已有提及。
POST 方法 (实现Assign操作)

这是实现“为新能力分配ID”功能的具体协议。

  • 请求体 (Request Body): Table 6.1.3.2.3.2-2: Data structures supported by the POST Request Body on this resource 定义了请求体的内容。
Data typePCardinalityDescription
DicEntryCreateDataM1Contains UE Radio Access Capability Information and type Allocation Code.

请求体必须是一个DicEntryCreateData对象。我们知道,这个对象通过multipart机制,既包含了TAC码等JSON元数据,也引用了二进制的能力信息。

  • 响应体 (Response Body): Table 6.1.3.2.3.2-3: Data structures supported by the POST Response Body on this resource 定义了Assign操作的返回结果。
Data typePCardinalityResponse codesDescription
DicEntryCreatedDataM1201 CreatedThe response body contains the assigned UE Radio Capability ID.
RedirectResponseO0..1307 Temporary RedirectTemporary redirection.
RedirectResponseO0..1308 Permanent RedirectPermanent redirection.
ProblemDetailsO0..1400 Bad RequestThe response body contains the error reason of the request message.

响应深度剖析:

  • 201 Created: “造词”成功。这是最重要的成功响应。响应体是一个DicEntryCreatedData对象,其中包含了UCMF新分配的(或复用的)那个PLMN-assigned ID。同时,HTTP响应头中必须包含Location头,指向新创建资源的确切URI。
  • 400 Bad Request: 请求格式错误,例如DicEntryCreateData对象不完整。
  • 307/308 Redirect: 同样支持重定向。

总结

通过对Nucmf_UECapabilityManagement API资源地图的初步探索,并聚焦于其核心——/dic-entries集合资源,我们已经将抽象的功能逻辑转化为了具体、可实现的协议交互。

  1. 清晰的资源模型: UCMF API围绕“字典条目”和“订阅”两大核心资源集合构建,结构层次分明,完全符合RESTful设计哲学。

  2. 方法与功能的精确映射: GET /dic-entriesPOST /dic-entries这两个API端点,分别精确地实现了ResolveAssign这两大核心服务操作。HTTP方法的语义与业务操作的意图高度一致。

  3. 详尽的接口契约: 规范通过一系列精确的表格,定义了每个操作的URI参数、请求体结构、所有可能的响应码以及对应的响应体结构。这为不同厂商之间的互联互通提供了坚实的、无歧义的基础。

我们已经学会了如何与UCMF的“字典档案馆”进行交互,包括如何按ID查询案卷,以及如何提交新材料创建案卷。在下一篇文章中,我们将继续沿着这张API地图前进,探索如何访问一个单个的、具体的字典条目资源(/dic-entries/{dicEntryId}),并开始对“订阅档案馆(/subscriptions)”的探索。


FAQ

Q1:GET /dic-entriesGET /dic-entries/{dicEntryId} 有什么本质区别? A1:本质区别在于查询的目标和方式GET /dic-entries是在整个集合中进行查询/筛选,你需要通过?ue-radio-capa-id=...这样的查询参数来告诉服务器你的筛选条件。而GET /dic-entries/{dicEntryId}是直接获取一个已知标识符的单个资源,它的ID (dicEntryId) 已经包含在URL路径中,代表了一个精确的、唯一的资源地址。

Q2:在GET /dic-entries时,为什么不把ue-radio-capa-id也作为路径的一部分,比如GET /dic-entries/ue-radio-capa-id/{id} A2:这是RESTful API设计的一个重要原则。路径(Path)通常用来表示资源的层级和唯一标识。而ue-radio-capa-id并不是字典条目这个资源的唯一主键(主键是dicEntryId),它只是资源的一个属性。使用查询参数(Query Parameter)来进行过滤、排序、分页等操作,是针对资源集合的标准做法。这种设计使得API更加灵活,未来如果需要增加按TAC码查询,只需增加一个新的查询参数?tac=...即可,而无需改变URI的路径结构。

Q3:查询参数supported-features具体是做什么用的? A3:supported-features是3GPP SBA中通用的特性协商机制。随着规范的演进(例如从Release 18到Release 19),可能会引入一些新的、可选的API特性。客户端(如AMF)可以通过这个参数告诉服务器(UCMF):“我支持这些新特性(例如特性A、B)”。UCMF看到后,如果它也支持,就可以在响应中启用这些新特性。如果客户端没有声明,UCMF就会以最基础、向后兼容的方式返回响应。这保证了不同版本NF之间的平滑互通。

Q4:为什么POST /dic-entries在发现能力信息已存在时,仍然返回201 Created A4:这是一种被称为“幂等的POST”或“upsert”的设计模式。客户端的意图是“确保一个代表此能力信息的资源在服务器上存在,并返回其信息”。服务器成功地满足了这个意图,无论它是通过“创建”还是“查找现有”的方式。因此,返回201 Created并附上该资源的Location头,被认为是对这个意图最准确的响应。它统一了成功路径的返回码,简化了客户端的处理逻辑。

Q5:作为开发者,我应该如何处理307 Temporary Redirect308 Permanent Redirect A5:- 对于307 Temporary Redirect: 客户端应该立即Location头中提供的新URI,使用与原始请求完全相同的HTTP方法和请求体,重新发送一次请求。但客户端不应该更新自己本地存储的该服务的地址。下次再有同类请求,还是应该先访问原始地址。

  • 对于308 Permanent Redirect: 客户端的行为与307类似,也是立即用相同的方法和内容重定向到新地址。但关键区别在于,客户端应该更新自己本地的配置或缓存,将该服务的地址永久性地修改为Location头中的新地址。未来的所有请求都应该直接发往这个新地址。