Trantor 升级 0.5.x
相关说明
- 因为 0.5.x 的版本中, Trantor 完成了用自身机制自举, 即使用 Trantor 的方式来跑 Trantor, 所以无论是底层的数据结构, 还是一些运行机制, 整体的改动都非常大. 所以本次升级会做一次特殊说明, 列举相关的注意事项和一些新增核心概念的说明.
- 不推荐使用交付控制台做资源调整, 不推荐使用交付控制台做资源调整, 不推荐使用交付控制台做资源调整. 交付控制台后续会对资源维护的功能做比较大的调整, 基本上资源的维护都会被屏蔽, 所以不推荐在使用交付控制台做研发资源的调整. 这种开发方式, 无论对于代码管理, 发布管理还是问题追溯, 都有很大的影响, 所以后续我们就会摒弃这种方式.
- 本次升级虽有较大的变化, 但对很多 API 包括使用方式都做了较高程度的兼容, 所以多数情况下是不需要做额外的适配工作, 但是有些 API 被标记为不推荐最好还是改一下, 后续可能会被删除. 其次就是资源 Key 的使用变化, 也做了兼容, 但是整体还是逐渐完成修改, 以便后续升级.
- 本次升级 0.5.x 版本时, 会对所有项目组以及使用方, 包括 Trantor 自己的研发环境, 都采用镜像式部署来运作. 本次升级完, 等稳定之后, Trantor 的后续的升级/部署等, 全部由项目组自行完成, 我们有完整的文档来说明, 版本的变化, 升级的步骤和部署的注意事项.
- 因为 Trantor 目前使用的项目组较多, 升级很难较快完成, 所以升级后的项目一定时间内, 在工具的使用上, 需要特殊处理, 主要集中在开发底座.
升级步骤
- 所有 Trantor 相关依赖升级至 0.5.0-SNAPSHOT, 注意模块间的依赖, 确保没有低版本的 Trantor 相关依赖, 否则会导致服务无法启动
- 将原有的资源 resources/trantor/resources 下的资源增加模块标识
- 如模块key 为 srm_order, 则路径变更为 resources/trantor/resources -> resources/trantor/resources/srm_order
- 所有原 resources/trantor/resources 下的资源统一移动至此, 比如 Action / view 等
- 如果使用本地模式, 切记在原本的模块路径上也加入模块 Key
- 升级完成之后, 确保依赖顺序, 确保依赖顺序, 确保依赖顺序, 依次重新发起 pipeline 编译发布, 当期版本的代注册机制还不完善, 为必规避一些问题, 最好保证按照模块依赖顺序启动
- 如果要本地启动, 将底座切换至 feature/bootstrap, 并且重启底座, 确保老的容器都被干掉
- 如果使用 Mock 模式进行开发, 可以在 base__user 表中, 维护一条数据, id 为1, isDeleted 为 0, 否则会出现爆栈的问题. 这个是因为 mock 模式当前用户 id为1, 插入数据时, 会获取当前用户作为 createdBy, 系统发现该用户不存在, 所以创建该用户, 这个用户的 createdBy 一样是当前用户, 所以就死循环了…
- 当出现 dictionary.module, model.module 不存在之类的, 这是因为 Trantor 的代注册机制还不完善, 当启动上层模块时, 所依赖的模块的信息, 可能还未注册, 所以导致被扩展的资源还不存在的问题. 如果是线上, 则保证启动顺序即可. 如果是本地, 所有依赖模块都启动一次, 或者将线上的 meta_store 开头的表数据都 dump 到本地.
- 如果模块启动时有设置 RECURSION_LOAD_MODEL 环境变量为 true,将其改为 false。 目前暂时不支持该参数。
- 如果遇到类似 “no such method meta_store_Module” 类似的DS报错,说明访问的底座还是旧版,把底座分支切换到 feature/bootstrap ,在清空旧版数据库数据之后重启底座。
- 如果打开交付控制台有空指针异常 看一下 meta_store__model 表里有没有值是 null 的记录 有的话删除。导致原因是有开启 RECURSION_LOAD_MODEL 的模块代注册了一些不完整的模型。
- 更新资源后重启服务,资源变更未生效时,检查 meta_store__module 表里的对应模块记录 installingVersion 有没有值,有的话设置成 NULL 后重启。
Trantor 的可扩展机制
背景
假定阅读至此至少有基本的 Trantor 相关概念. 最早的 Trantor 在资源机制上, 只区分了 代码 和 二开的内容, 即原来的 static 和 custom. 但是在实际研发过程中, 必然会碰到大量的标品调整工作, 越复杂的项目, 这部分工作量会越多, 多数项目的调整内容会超过50%. 在此情况下, 这部分内容全部以数据形式存在数据库中, 一是无版本管理, 持续研发, 升级迁移等过程, 会触发很多不可控因素, 二是在产品团队逐渐成熟的情况下, 可能会出现多层的标品, 比如底层的订单服务, 和上层的 o2o 订单模块, 加上用户定制的修改, 就至少有三层逻辑叠加了. 对于原本的两层划分支持度不够
因此, trantor 在原有的扩展机制上做了一些调整, 不在直接区分代码和二开, 而是提出一套新的可扩展可替换的机制来支撑.
基本概念
在 Trantor 新的机制中, 有几个核心资源分层:
- 模块: 很好理解, 就是模块, 业务自行根据需求划分, 比如
订单模块 - 主资源: 可扩展资源的绑定主体, 现在只有
模型和字典两个 - 可扩展资源: 主资源下的可扩展内容, 这个比较多, 以模型为例, 他的可扩展资源有如下几种:
- 模型配置
- 模型字段
- 模型字段组
- 模型索引
- 模型绑定的视图 (View)
- 模型绑定的行为 (Action)
这么列举出来就比较好理解了, 模块是业务逻辑上的划分, 而主资源一般是可扩展资源的绑定主题, 其自身是没有需要根据业务调整的. 而根据业务变化的, 都是可扩展资源.
可扩展资源本质上不仅会扩展, 还会出现一些调整性的覆盖, 某些特殊场景的功能屏蔽等等. 所以我们还要提供允许相同资源的替换, 以及资源的禁用. 为了处理上述特性, 我们需要各种资源的识别标识, 以用作资源的扩展绑定, 替换禁用等.
因此, 我们为不同的资源分层提供了相关的资源声明, 分别是:
- Key: 唯一标识, 很好理解
- resourceKey: 资源声明标识, 拥有相同 ResourceKey 的资源, 认为是同一类资源, 可以彼此之间替换, 但最多只能生效一个
- originalKey: 资源的原始Key, 比如类名, 字段名这种, 就是他自己的原始 key
他们在各层资源的是有所不同的:
- 模块:
- key: 模块只有 Key, 是模块的唯一标识
- 主资源:
- originalKey: 主资源的原名称, 如字典就是字典key, 模型默认是类名
- key: 主资源的唯一标识, 规则是主资源所属的模块Key + 该资源的 originalKey. 如 base 模块下的 User 模型, 他的 key 就是 base_User
- 可扩展资源, 这个是整个机制中最核心的概念, 会略有复杂:
- originalKey: 资源的原名称, 比如模型下的字段, 其字段的名字就是 originalKey. 比如 User 模型里的 password 字段, 他的 originalKey 就是 password.
- resourceKey: 资源的标识, 规则是主资源的key + 可扩展资源的 originalKey.
- 比如 base 模块里的 User 模型, 有一个 password 字段, 他的 resourceKey 就是 base_User_password.
- key: 唯一标识, 规则是可扩展资源所属模块的 key + 可扩展资源的 resourceKey.
- 比如 base 模块里的 User 模型, 有一个 password 字段, 他的 key 就是 base_base_User_password.
- 如果在 member 模块里, 扩展了 base 模块内的 User 模型, 增加了一个 membershipLevel 字段, 那么他的 key 就是 member_base_User_membershipLevel
- 如果同时在 member 模块里, 扩展了 base_User 的 password 字段, 比如修改了长度. 那么这个字段的 key 就是 member_base_User_password. 但是该字段的 resourceKey 仍然是 base_User_password, 所以我们可以通过配置, 让该扩展字段生效, 而使原模型的字段失效.
运行方式
基本概念大概介绍完了, 举个实际一些的场景和例子.
我们有很多基础服务, 比如订单, 用户, 商品等等, 这些模块会有基础的模型, 和相关的基本视图, 服务逻辑等. 同时, 我们也有很多标品团队, 比如 SRM, B2B, B2C 等等, 这些团队会基于基础服务, 做一些扩展, 调整, 以完成各自标准产品的业务功能. 最后, 我们真正实施的业务, 通常都是数个标品组成, 加上客户的定制需求, 组成一个完整的软件产品.
首先, Trantor 的扩展机制, 是可以有多层的, 如果有足够多的业务分层, 也是可以的. 因为我们的场景更多是上述的三层, 所以以此为例, 暂时没有画图, 所以可能比较难以理解一些…
以订单为例, 交易模块中, 肯定会有订单以及其相关的模型, 模型相关的基础字段, 以及相关的字典, 视图等等, 他们会是一个基本可用的核心服务. 比如订单这个模型, 会有一个字段, 是订单客户,订单金额, 和订单状态. 他们的 resourceKey 分别是 trade_Order_customer, trade_Order_price 和 trade_Order_orderStatus.
trade_Order_orderStatus 对应的字典是 trade_OrderStatus, 有一些基础的字典项, 比如 trade_OrderStatus_created, trade_OrderStatus_closed.
B2B 标品, 可能会组合订单以及其他基础服务, 也会对订单的基础服务做一些扩展和调整. 比如增加一些字段, 比如 trade_Order_supplier. 也会增加一些字典项, 比如 trade_OrderStatus_signContract. 同时, 也会增加/调整一些 View.
当我们去交付时, 比如 JJY_B2B, 我们会根据客户的需求, 在B2B以及其他标品之上, 增加一些扩展模型, 扩展字段, 字典, 字典项, 以及展现的视图等. 但是交付过程中, 可能会有一些标品的内容, 不符合客户期望, 所以我, 需要进行一些调整. 会新增一些属于 JJY_B2B 模块的资源, 这些资源可以与标品或者基础模块中资源的 resourceKey 相同, 从而替换掉相关逻辑. 比如 trade_Order_orderStatus, 本来叫订单状态, 在 jjy 的场景就可以将 Label 改为采购单状态, 并且新增很多跟jjy自身业务相关的字典项. 也可以禁用掉一些对其场景无用的字段, 或者是字典项, 也可以选择选择直接禁用, 比如 JJY 的场景不需要 trade_Order_customer, 可以直接将其禁用.
兼容调整
本次升级对原有的资源标识做了一定的调整, 新规则上面已经说明, 老规则实际上是 模块key + 资源 key, Trantor 在升级后, 也对这部分做了兼容, 会有一个 oldKey 以此规则拼接. 先有的查询逻辑是, 现根据 resourceKey 查询, 未查询到则尝试用 oldKey 查询, 有则返回. 如根据 resourceKey 有查询到资源, 则查看资源是否是系统生成的, 如果是, 会尝试用 oldKey 查询是否有老规则记录, 有则返回 oldKey 查询到的, 没有则返回 resourceKey 查询到的. 但交付控制台上做的修改内容, 会默认落到 custom 模块, 也就是说, 使用老的资源标识, 是无法被识别到可替换内容的, 因为 代码上报的资源key和二开资源所属的模块不一致, 所以 oldKey 也不一样. 但是 resourceKey 是一样的, 所以才需要在研发过程中, 逐渐将 oldKey 都替换成 resourceKey. 以便后续的功能扩展与替换裁切等.