网络资源管理系统落地:资源分层、存量管理与共享服务
简介:《中国移动综合网络资源管理系统技术规范通用功能分册》是一份面向通信运营商网络资源管理、运维支撑及系统建设人员的正式企业标准文档,可用于理解综合网络资源管理系统的功能架构与实施要求。内容围绕系统定位、总体目标与建设原则展开,并细化资源模型管理、资源命名、数据质量、批量导入导出、空间/物理/逻辑/业务资源存量管理、资源拓扑、调配与分析展现等通用功能,同时涉及资源数据共享服务和技术功能要求,适合从事网管系统规划、需求分析、开发测试与运维的人员查阅对标。压缩包内共1个doc文件,约1.03MB,便于本地检索与归档。目前已有306人学习,可作为梳理资源管理系统功能边界、编写需求文档或设计模块时的参考依据。
1. 综合网络资源管理系统技术规范通用功能分册:先看四个功能域,别急着建表
综合网络资源管理系统技术规范通用功能分册最容易被当成一张功能清单,翻完架构图就丢给开发建表,后面接口联调才发现命名、质量、拓扑口径全对不上。它真正值钱的地方,是把资源模型、存量管理、应用功能和共享服务划成四个功能域,并给出可验收的通用功能边界。这份分册适合做资源管理平台的产品经理、数据建模人员和后端接口开发,也适合正在做运维支撑系统改造的团队拿来当需求基线。它不教你某个厂商产品怎么点,而是告诉你一类系统必须有哪些能力、哪些边界不能拍脑袋。先看功能域之间的关系,再决定表怎么拆,比一上来画菜单靠谱。
2. 资源分层落到表结构:空间、物理、逻辑、业务四层怎么拆
2.1 先冻结资源模型,再谈功能菜单
综合网络资源管理系统技术里最容易返工的一步,是把功能菜单当成需求主体。菜单可以后加,资源模型一旦被业务字段污染,后面每接一个专业网络就要改一次表。通用功能分册把资源分成空间、物理、逻辑、业务四层,这个分法不是学术分类,而是为了把“装在哪、是什么设备、怎么连接、承载什么业务”拆成可独立维护的对象。空间资源负责地域容器和逻辑区域,物理资源负责有形的设备、端口、缆线,逻辑资源负责子网、网元、逻辑连接、时隙和码号,业务资源负责产品实例与业务实例。四层之间用引用关系串起来,而不是把所有字段塞进一张大表。
我一般会先做一次模型冻结评审,把每层资源的主键、唯一编码、父级关系、生命周期字段和状态字段定下来。冻结不是永远不改,而是明确“新增字段走模板扩展,不改主表语义”。这一步不做,后面批量导入和共享接口都会变成黑匣子:同一张设备表里既有空间归属,又有业务占用,查询时谁也说不清一行数据到底代表什么。选型上,关系型数据库适合做资源主数据,扩展属性用模板表或JSON字段承载,拓扑关系单独建边表,机历单独建快照表。这样做的好处是主数据稳定,扩展字段不会把核心查询拖慢。
资源分层的落地可以用一张统一主表加分层子表的方式。统一主表只保留跨层共用的字段,分层子表放专业字段。下面这段SQL是一个可抄作业的起点,字段名可以按团队习惯改,但约束逻辑建议保留。
CREATE TABLE res_resource ( resource_id VARCHAR(64) PRIMARY KEY, resource_type VARCHAR(32) NOT NULL, -- location/physical/logical/service resource_name VARCHAR(256) NOT NULL, resource_code VARCHAR(128) NOT NULL, parent_id VARCHAR(64), lifecycle_stage VARCHAR(16) NOT NULL, -- plan/build/active/retire status VARCHAR(16) NOT NULL, -- free/occupied/fault template_id VARCHAR(64), updated_at TIMESTAMP NOT NULL, UNIQUE (resource_type, resource_code) ); CREATE INDEX idx_res_parent ON res_resource(parent_id); CREATE INDEX idx_res_type_status ON res_resource(resource_type, status);这段SQL的逻辑说明:resource_type限定四层资源,避免同一张表出现无法归类的对象;resource_code在同类资源内唯一,跨类可以重复但必须带类型查询;parent_id表达空间包含、拓扑承载或业务归属,具体含义由resource_type决定;lifecycle_stage对应规划、建设、在网、退网四个阶段,后面做资源预警和机历都靠它;status只表达当前占用或故障状态,不承担生命周期语义。参数上,resource_id建议用全局唯一ID,不要用自增数字暴露给外部接口;resource_code是业务编码,长度要预留专业网扩展;template_id为空表示使用默认模板,非空时去模板表取扩展属性。
2.2 四层资源的表结构拆法
空间资源、物理资源、逻辑资源、业务资源的字段差异很大,但关系模式可以统一成“主表 + 关系表 + 扩展表”。空间资源重点在层级,物理资源重点在位置和端口,逻辑资源重点在两端连接,业务资源重点在引用关系。下面这张表是我在建模会上常用的对照表,用来防止开发把四层字段混在一起。
| 资源层 | 典型对象 | 主键建议 | 关键关系字段 | 常见误用 |
|---|---|---|---|---|
| 空间资源 | 区域、局站、机房、机房平面 | resource_id | parent_id、geo_code | 把机房平面坐标塞进设备表 |
| 物理资源 | 设备、机框、端口、缆线 | resource_id | location_id、endpoint_a、endpoint_b | 用设备表同时承载逻辑连接 |
| 逻辑资源 | 子网、网元、逻辑连接、时隙、码号 | resource_id | endpoint_a、endpoint_b、subnet_id | 把逻辑端口当物理端口统计 |
| 业务资源 | 产品实例、业务实例、资源占用关系 | service_id | resource_ref、customer_ref | 业务状态和资源状态共用一套字典 |
表里最后一列是血泪经验:很多团队为了省事,把“占用状态”做成一张全局字典,结果物理端口的空闲、逻辑时隙的可用、业务实例的在服全挤在一个字段里,报表口径天天吵架。更稳的做法是每层有自己的状态机,跨层只做引用,不共享状态字典。空间资源可以少一点状态,物理资源关心在网、库存、故障,逻辑资源关心空闲、预占、占用,业务资源关心开通、变更、退网。状态机分开以后,接口传参也不会出现“同一个status=1在不同模块含义不同”的翻车现场。
分层子表不需要一上来铺全。可以先建res_location、res_physical、res_logical、res_service四张子表,只放该层特有的字段,其余共用字段留在主表。子表主键直接引用主表resource_id,查询时用主表过滤类型,再按需join子表。这样既不会出现宽表字段爆炸,也不会让每层资源各建一套完全独立的编码体系。批量导入时先写主表拿ID,再写子表,事务边界按“单条资源”控制,不要把一万条资源塞进一个大事务。
2.3 资源模板和扩展字段的边界
资源模板管理是通用功能分册里很实用的一个设计:把通用规则和属性分离出来,入库时通过参数化配置快速形成资源实例。落地时不要把模板理解成“动态建表”。动态建表在资源类系统里维护成本很高,查询优化也难做。更常见的做法是模板表加属性表,属性表用行存方式记录扩展字段,关键字段再冗余到主表或子表做索引。
template_code: physical_device_default resource_type: physical required_fields: - resource_name - resource_code - location_id - vendor_type optional_fields: - model - sn - install_date field_rules: resource_code: pattern: "{domain}-{location}-{type}-{seq}" seq_width: 6 case: upper lifecycle_stage: enum: [plan, build, active, retire]这段YAML是模板配置的示意,不是某厂商产品的固定格式。required_fields放入库必须校验的字段,optional_fields放可后补的字段;pattern里的占位符要和命名服务一致,seq_width决定流水号补零位数,case统一大小写,避免同一编码出现大小写两个版本;lifecycle_stage的枚举值要和主表约束一致。模板配置完成后,批量导入先按模板做字段级校验,再做跨表业务校验。模板不是越灵活越好,扩展字段超过二十个以后,查询和报表会明显变慢,这时候要考虑把高频扩展字段提升为子表字段。
提示:资源模型冻结评审的输出不要只写会议纪要,至少落一份字段字典和一份状态机表,后面接口联调时直接拿这两份东西对,比翻聊天记录可靠。
3. 存量管理可执行步骤:命名规则、批量导入和拓扑关系怎么落地
3.1 命名规则先于数据导入
存量管理是资源管理系统的核心功能域,空间、物理、逻辑、业务四类资源的维护都绕不开编码。很多项目先做导入工具,导入到一半发现编码重复、大小写不一致、历史数据带空格,最后只能停库清洗。通用功能分册把资源命名管理放在系统基础维护里,顺序是对的:命名规则先定,编码生成服务先上,批量导入再接进来。命名规则要覆盖专业域、地域、资源类型、流水号四个基本段,冲突策略要明确是拒绝、跳过还是重生成。我一般会把冲突策略设为拒绝,导入报告里直接给出冲突行号,不让脏数据静默通过。
naming_rule: rule_code: res_code_default pattern: "{domain}-{location}-{type}-{seq}" segments: domain: source: resource_domain enum: [core, access, transport, data] location: source: location_code max_length: 8 type: source: resource_type_code max_length: 6 seq: source: sequence width: 6 conflict_policy: reject normalize: trim: true upper_case: true remove_spaces: true这段配置说明:pattern是编码骨架,段之间用固定分隔符,避免后期解析靠猜;domain和type用枚举限制,防止自由文本把编码撑爆;location限制长度,因为地域编码通常有固定规范;seq由序列服务生成,宽度不足补零;conflict_policy设为reject时,导入任务遇到重复编码直接失败并输出冲突清单,适合主数据入库;如果做历史数据迁移,可以临时改成skip,但迁移完成后必须切回reject。normalize里的去空格和转大写看着琐碎,实际能消掉大量“看起来一样、查出来两条”的问题。
命名服务最好独立成一个接口,不要让每个导入脚本自己拼字符串。接口入参给domain、location、type和可选seq,出参给resource_code和rule_version。规则版本要记录到资源主表,后面规则调整时能知道哪些数据是按旧规则生成的。命名规则变更不要直接改历史编码,新增资源走新规则,历史资源保留原编码并在机历里记一笔规则版本,否则外部系统按编码关联会断。
3.2 批量导入模板的字段顺序
批量数据导入导出是基础维护里的高频功能,也是翻车高发区。导入模板的字段顺序不是小事:先放类型和编码,再放名称和父级,再放位置和状态,最后放扩展字段。这样导入程序可以先做类型校验,再做编码唯一性校验,再做父级存在性校验,失败时能按阶段定位。下面这张表是我常用的最小导入字段集,实际项目可以按专业扩展,但前六列建议保留。
| 列序 | 字段 | 必填 | 校验动作 | 失败处理 |
|---|---|---|---|---|
| 1 | resource_type | 是 | 枚举校验 | 整行拒绝 |
| 2 | resource_code | 是 | 命名规则、唯一性 | 输出冲突清单 |
| 3 | resource_name | 是 | 长度、空值 | 整行拒绝 |
| 4 | parent_code | 否 | 父级存在、层级合法 | 挂起待补 |
| 5 | location_code | 物理资源必填 | 空间资源存在 | 整行拒绝 |
| 6 | lifecycle_stage | 是 | 状态机合法 | 整行拒绝 |
| 7 | status | 是 | 字典合法 | 整行拒绝 |
| 8 | template_code | 否 | 模板存在 | 使用默认模板 |
| 9 | effective_time | 否 | 时间格式 | 整行拒绝 |
导入流程建议拆成三步:预检、正式导入、结果对账。预检只读不写,输出错误行和警告行;正式导入按批次提交,每批五百到一千条,批次太大回滚慢,批次太小事务开销高;结果对账把成功数、失败数、跳过数和冲突编码落一张导入批次表。预检阶段要特别关注父级关系,因为空间资源和逻辑资源经常出现“子资源先到、父资源后到”的情况。遇到父级不存在时不要直接丢数据,可以进挂起表,等父级导入后再补关系。挂起表要有超时清理策略,否则挂起数据会变成新的脏数据源。
3.3 拓扑关系和机历怎么写才不丢
资源拓扑管理不是画一张好看的图,而是把资源之间的承载、连接、归属关系变成可查询的边。拓扑关系建议单独建边表,不要在主表里塞parent_id就完事。parent_id适合表达树形包含,比如区域包含机房、机房包含机架;逻辑连接、物理连接这类多对多关系要用边表,记录from_id、to_id、relation_type和有效时间。机历管理则要记录变更前后快照,不能只记“谁在什么时候改了什么字段”。只记结果不记快照,后面排查业务影响范围时没有后悔药。
CREATE TABLE res_topology_edge ( edge_id VARCHAR(64) PRIMARY KEY, from_id VARCHAR(64) NOT NULL, to_id VARCHAR(64) NOT NULL, relation_type VARCHAR(32) NOT NULL, -- contain/connect/carry effective_time TIMESTAMP NOT NULL, expire_time TIMESTAMP, status VARCHAR(16) NOT NULL ); CREATE TABLE res_history ( history_id VARCHAR(64) PRIMARY KEY, resource_id VARCHAR(64) NOT NULL, change_type VARCHAR(32) NOT NULL, before_snapshot JSON, after_snapshot JSON, operator_id VARCHAR(64) NOT NULL, change_time TIMESTAMP NOT NULL, ticket_id VARCHAR(64) );边表的逻辑说明:relation_type至少区分包含、连接、承载三类,不要把三种关系混在一个字段里;effective_time和expire_time表达关系的有效期,退网或割接时不要物理删除边,而是置失效时间;status用于标记当前有效或历史有效。机历表的逻辑说明:before_snapshot和after_snapshot存变更前后的关键字段JSON,不要存全表大字段,只存会影响业务判断的字段;operator_id和ticket_id用于追溯操作来源;change_type区分创建、修改、割接、退网。参数上,快照JSON的字段集要固定,不能这次存五个字段下次存二十个,否则回溯脚本没法统一解析。
4. 资源应用与共享服务:调配、分析、展现和接口参数怎么设计
4.1 应用功能不是菜单堆叠,先定资源状态机
资源应用功能域包括调配类、分析类、展现类和其他类应用。很多系统把应用做成菜单堆叠,点进去全是查询页,真正要调配时状态对不上。问题出在应用功能没有和资源状态机绑定。资源配置、资源调度、资源割接这些调配类应用,本质上是推动资源从一个状态合法迁移到另一个状态。状态机不定,应用越多越乱。通用功能分册把资源配置、调度、割接放在资源应用里,把存量管理放在核心功能域,落地时要把“存量状态”和“流程状态”分开:存量状态描述资源当前能不能用,流程状态描述工单走到哪一步。
下面这张状态迁移民表可以作为调配类应用的校验基线。表里的状态是示意,实际项目可以按专业扩展,但迁移方向要明确。
| 当前状态 | 允许动作 | 目标状态 | 校验点 |
|---|---|---|---|
free | 预占 | reserved | 资源在网、无故障、无未闭环工单 |
reserved | 开通 | occupied | 业务实例存在、配置下发成功 |
occupied | 故障 | fault | 告警关联到资源 |
fault | 恢复 | occupied | 告警清除、巡检通过 |
occupied | 退网 | free | 业务解绑、机历记录完整 |
plan | 建设完成 | active | 验收单、资源编码已生成 |
这张表的价值在于把“能不能点按钮”变成“状态允不允许”。资源调度请求进来时,先查资源状态,再查流程状态,两个都合法才允许创建调度任务。资源割接则要多一步影响范围分析:割接前把待割接资源、业务占用信息、影响客户范围导出,割接中做资源封锁,割接后解封锁并发布数据。割接影响范围分析不要只查直接连接,至少查两层承载关系,否则容易漏掉上层业务。
4.2 共享服务接口的四个必填参数
资源数据共享服务是综合资源管理系统和外部系统之间的边界。服务开通类、故障支撑类、备品备件类、资产信息类应用都来取资源数据,如果接口没有统一契约,每个调用方各写一套解析逻辑,后面改字段就是灾难。我一般要求共享接口至少带四个必填参数:request_id、version、operation、resource_type。request_id用于幂等和对账,version用于接口版本隔离,operation表达查询、预占、开通、释放等动作,resource_type限定资源层。下面这段JSON是请求报文的示意,字段不追求大而全,先把契约骨架定住。
{ "request_id": "req-demo-0001", "version": "v1", "operation": "resource.reserve", "resource_type": "logical", "payload": { "resource_code": "LOG-DEMO-000001", "service_id": "svc-demo-001", "effective_time": "2024-05-29T10:00:00+08:00" }, "callback_topic": "resource.reserve.callback" }报文说明:request_id由调用方生成,服务端要建唯一索引,重复请求直接返回首次结果,避免重复预占;version用于灰度升级,不同版本可以并存一段时间;operation用点号分隔的动词短语,服务端按操作路由到不同校验逻辑;resource_type让服务端先定位资源层,再查对应子表;payload里放业务字段,resource_code和service_id是调配类接口最常用的关联键;callback_topic用于异步回传,不写真实地址,避免环境绑定。参数上,effective_time要带时区,跨系统时间不一致会导致预占提前或延后生效。
共享服务还要做对账。服务开通类接口关注“资源预占结果”和“开通结果”,故障支撑类接口关注“资源定位信息”和“告警关联关系”,备品备件类接口关注“库存资源”和“替换关系”。不同调用方的时效要求不同,接口层面不要用同一个超时时间。查询类接口可以短超时加快失败,调配类接口要长超时并支持异步回调。对账任务按request_id和resource_code双维度比对,发现单边数据时先冻结资源状态,再人工核查,不要让不一致继续扩散。
4.3 服务开通与故障支撑的差异
服务开通和故障支撑都调资源共享服务,但数据粒度和回滚要求完全不同。服务开通要拿到可分配的资源实例,关注预占、开通、释放,回滚时要能释放预占并恢复资源状态;故障支撑要拿到资源定位和承载关系,关注快速查询和影响范围,回滚要求低但查询时效要求高。落地时建议拆两套接口视图,不要用一个万能接口硬扛。下面这张对比表可以用来和调用方对齐预期。
| 维度 | 服务开通类 | 故障支撑类 |
|---|---|---|
| 主要动作 | 预占、开通、释放 | 查询定位、查承载、查影响 |
| 数据粒度 | 资源实例级 | 资源实例加拓扑关系 |
| 时效 | 可异步,允许分钟级 | 尽量同步,秒级返回 |
| 一致性 | 强一致,失败要回滚 | 最终一致,允许短暂缓存 |
| 关键参数 | request_id、service_id | alarm_id、resource_code |
| 对账重点 | 预占与开通结果 | 告警与资源关联关系 |
这张表不是让你照抄,而是提醒接口设计时先问调用方要什么。服务开通接口如果返回一堆拓扑关系,调用方用不上还增加解析负担;故障支撑接口如果只返回资源ID不返回位置和承载,排障人员还得二次查询。共享服务的边界清楚,后面应用功能才不会互相甩锅。
5. 避坑与排查:通用功能分册落地时最容易翻车的五件事
5.1 五个高频踩坑记录
第一件,只建功能菜单不建资源模型。现象是系统上线三个月,设备表加了二十多个扩展字段,查询越来越慢,接口字段天天变。原因是项目组把通用功能分册当菜单清单,先做页面后做模型,字段跟着页面走。解决方法是先做模型冻结评审,主表只留跨层共用字段,扩展字段走模板表,新增字段必须说明查询场景和索引方案,评审不通过不进开发。
第二件,命名规则后补。现象是批量导入时编码重复、大小写混用、前后空格导致同一资源出现两条记录。原因是导入工具先上线,命名服务后补,历史数据没有统一清洗。解决方法是命名服务先于导入工具上线,导入前强制走normalize和conflict_policy: reject,历史数据先跑一遍清洗脚本,冲突清单人工确认后再入库。命名规则版本要写进资源主表,后面规则调整不影响历史编码。
第三件,批量导入只做格式校验不做业务校验。现象是导入成功率很高,但拓扑查询出现大量孤儿节点,业务开通时找不到父级机房。原因是导入程序只校验必填和类型,没有校验父级存在性和层级合法性。解决方法是导入分预检和正式导入两段,预检阶段做父级存在、层级深度、状态机合法、模板存在四类校验,父级缺失的数据进挂起表,父级补齐后再补关系。挂起表要有超时清理,避免变成新的脏数据。
第四件,共享接口没有幂等和版本。现象是服务开通系统重试一次,资源被预占两次,释放时只释放了一条,另一条一直占用。原因是接口只按resource_code做校验,没有request_id唯一约束,也没有版本字段做灰度。解决方法是服务端对request_id建唯一索引,重复请求返回首次结果;接口带version,新旧版本并行一段时间;调配类操作记录操作流水,释放时按流水回滚,不按当前状态猜。
第五件,机历只记结果不记快照。现象是割接后业务不通,排查时只知道资源被改过,不知道改前是什么状态,恢复只能靠猜。原因是机历表只记了变更类型和操作人,没有存变更前后快照。解决方法是机历表存关键字段快照,快照字段集固定,变更类型区分创建、修改、割接、退网;割接类变更必须带工单号,回滚时按快照恢复并再记一条机历。机历不是审计日志的附属品,它是资源回溯的后悔药。
5.2 排查顺序与回滚边界
资源类系统出问题,排查顺序比工具更重要。我一般按“数据质量、命名编码、拓扑关系、共享接口、应用状态”五层往下查。先跑数据质量规则,看空编码、重复编码、孤儿父级、非法生命周期;再看命名服务日志,确认最近有没有规则变更或序列跳号;然后查拓扑边表,看关系是否失效、是否有环;接着查共享接口的request_id流水,确认有没有重复请求或单边成功;最后查应用状态机,看资源状态和流程状态是否打架。这个顺序的好处是先排除主数据问题,再查接口和流程,避免在应用层反复试错。
回滚边界要提前定。命名规则变更不回滚历史编码,只回滚新规则开关;批量导入失败按批次回滚,已成功的批次保留,失败批次输出错误清单;共享接口失败按request_id回滚预占,不回滚已开通的业务;割接回滚按机历快照恢复,恢复前先冻结相关资源,恢复后再解冻结。回滚动作本身也要记机历,否则二次回滚时没有依据。资源类系统的回滚不是“一键撤销”,而是“按流水和快照逐步恢复”,边界清楚才不会越滚越乱。
6. 把规范变成验收清单:数据质量核查与接口联调的进阶用法
6.1 验收清单怎么定阈值
通用功能分册给了功能边界,验收时要把它转成可量化的检查项。我习惯在上线前拉一张清单,每项都有阈值和责任人,不达标不签字。资源模型冻结以字段字典评审通过为准;命名冲突率按导入批次统计,主数据入库要求为零;拓扑孤儿率按资源类型统计,物理资源和逻辑资源要低于千分之一;机历完整率按变更流水统计,割接类变更要求百分之百;接口幂等命中率按request_id重复请求统计,重复请求必须返回首次结果。阈值不是拍脑袋,先跑一周试运行拿基线,再按基线收紧。
6.2 质量核查SQL和接口对账
质量核查不用等报表平台,直接跑SQL最快。下面这段SQL按资源类型统计空编码和孤儿父级,适合每天定时跑,结果落质量报告表。
SELECT resource_type, COUNT(*) AS total, SUM(CASE WHEN resource_code IS NULL OR resource_code = '' THEN 1 ELSE 0 END) AS empty_code, SUM(CASE WHEN parent_id IS NOT NULL AND parent_id NOT IN (SELECT resource_id FROM res_resource) THEN 1 ELSE 0 END) AS orphan_parent FROM res_resource GROUP BY resource_type;这段SQL的逻辑说明:empty_code统计空编码,主数据表出现空编码基本可以判定导入校验漏了;orphan_parent统计父级不存在的数据,子查询用主表自身做存在性判断,数据量大时建议给parent_id建索引或改成左连接。参数上,resource_type分组方便按层定位问题,定时任务可以把结果写入res_quality_report,连续三天上涨就触发告警。
接口联调时,我强制用request_id做对账:调用方发一个请求,服务端落一条流水,回调再落一条结果,三方按request_id对齐。对不上的先冻结资源,再查调用方重试逻辑和服务端幂等索引。从那以后我每次做资源类项目,上线前都强制跑一遍质量核查SQL,再拿接口流水对一遍request_id,不给自己留“应该没问题”的侥幸。希望帮到你。
本文还有配套的精品资源,点击获取