跳转到内容

Trantor 的定位

很多同学在使用 Trantor 的过程,或多或少都会有些问题,我们也有在收集各方所问过的问题, 使用 Trantor 的反馈等等。 Trantor 团队在 Review 这些问题,特别是一些看起很没有营养的问题的时候,经常会提出一个结论是这位同学没理解 Trantor 机制,很多时候类似问题就被放过去了, 归为已处理。 新同学在使用Trantor的时候,更多是根据Trantor使用指南上说的你这么做, 就能达到什么效果, 方式上没问题, 但是使用的同学想更进一步则会很难。 所以本文就是从概念到过程的,相对体系化的介绍一下 Trantor 的机制,尝试说明白,到底什么是 Trantor 机制, 我们又怎么来理解它。

Trantor 的定位

要理解一个东西是什么, 首先要了解的是, 他的定位是什么, 要解决的问题是什么。下面就是 Trantor 的定位:

Trantor 是一个中后台业务应用快速研发交付体系,同时也是公司大战略的可定制化 SaaS 平台的核心机制部分。

我们发现里面有很多关键字, 但其实最核心的关键词, 就三个, 分别是:

  • 中后台: 点明了 Trantor 的核心场景,选择中后台是因为其场景相对模式化, 模式化的相对好抽象。
  • 快速研发: Trantor 的核心需求, 就是通过场景抽象, 二开机制来整体提升我们的软件研发以及交付的效率。
  • SaaS 平台: 这个是未来的大战略,指明了 Trantor 未来的方向,这里暂不展开。

所以说回来, Trantor 最核心的需求, 还是软件行业万年不变的老台词, 提升研发效率。

研发效率

其实提升研发效率这条路, 一直在走, 我们目前使用的编程语言也好, 常用的框架也好, 本质上都是为了提升研发效率; 我们不再需要直接处理二进制指令, 因为有了汇编语言, 使用助记符对二进制指令做了抽象; 我们不再需要直接针对机器写程序, 因为有了操作系统, 提供了接口对硬件的操作做了抽象; 我们不再需要写很多重复性的代码, 因为有了业务模板, 通过固化重复代码的方式做了抽象; 我们不再需要写代码手动管理内存, 因为有了高级语言, 通过管理对象的生命周期做了抽象。 大家发现了么? 说自古以来可能有点过分, 但是基本也差不多, 就是计算机诞生以来, 软件的效率提升就没停过, 现在也没有停下脚步, 但是说回来基本上都是两个字:抽象。

抽象

下面官方一些的描述:

抽象: 从众多的具体事物中,抽取共同的、本质的属性,舍弃个别的、非本质的属性,从而形成概念。

重点:抽取共同的, 舍弃个别的。 回过头来再看 Trantor 的关键字中, 为什么会有一个中后台应用, 正式因为中后台有大量共同的, 可以被抽象的逻辑. 如果是一些界面各异, 逻辑迥然的产品, 本身可抽象的部分就不是很多, 相对效能提升的收益也不大。 Trantor 目前主要有两个层面的抽象,分别是研发和交付。

研发的抽象

研发的抽象就是指, 为了提升软件研发效率所做的抽象。Trantor 在研发方面的抽象也做了很多, 最核心的就是元信息的抽象。 当然, 元信息的抽象我们又分了一些不同的类型。

其中最核心的三个类型是:模型、视图、逻辑,这三种类型基本上就能满足基本的crud业务了。三者关系如下图所示,下面我们详细树下这3者的作用。 image-20220106145935679

模型

模型是指对于某个实际问题或客观事物、规律进行抽象后的一种形式化表达方式。

在 Trantor 的体系内,模型是描述了一个业务实体,以及该实体有那些属性字段和业务关系,相当于一个数据容器, 一个持久化的表结构。 大多数情况下,模型约等于一个实体类加一些注解。模型是 Trantor 体系的核心,同时,模型及模型间关系的定义既是对具体业务的设计和抽象,也是驱动由 Trantor 构建的中后台系统的约定。 我们可以看一个员工模型的例子: image-20220106145951536 image-20220106150013138 上面是在线员工定义,描述了一个员工所需要的属性,我们看看这个模型描述了哪些事情:

模型配置

基本信息包括模型名称、模型识别标识、描述、以及删除策略等特性。 字段配置包括:

  1. 每个字段上, 可以配置字段的名字,类型,是否可为空等等;
  2. 一些业务关系, 就是通过Link类型声明的字段, 比如 company 字段,就指明了该员工属于哪家公司;

其他一些特性包括,模型对应的表是否开启分表功能、字段组配置、索引配置等。

配置模型后Trantor会做些什么?

有了上述声明之后, 我们能做什么呢? 配置完模型、字段后, Trantor会做些什么呢?

  1. 首先,Trantor会生成一个对应的Java类,可以作为一个个数据的容器。
  2. 其次,因为每个字段都有类型声明,非空校验,关联关系等信息,Trantor就可以生成这个模型对应的数据库表结构。
  3. 最后,因为我们有字段的类型,字段的名称等之类的配置,Trantor也可以基于这些信息,生成这个模型对应的前端界面,至少标准的对这个模型增删改查是没问题的。

那么,Trantor是怎么做到的呢? 还是之前一直在聊的,性能提升的核心方式:抽象。 抽象可以让我们只编写变化的部分,共同的部分,全部被 Trantor 处理掉了。 现在,我们再来看一下数据库结构是怎么映射出来的:

  1. Trantor 抽象了 Java 常用数据类型对应的 Trantor 数据类型;
  2. Trantor 抽象了 Trantor 数据类型对应的数据库类型,所以不同字段映射到的数据库类型是什么;
  3. Trantor 抽象了模型以及字段上,对于数据库信息声明的方式。比如映射的数据库字段名,索引,是否可为空,字段长度等信息。
  4. 根据 Link等字段类型,Trantor 知道了模型之间的关系,无论是一对一、一对多、还是多对多,通过声明不同的字段类型即可。
  5. Trantor提供非常多的字段类型,如:Text、Int、Float、Date、Time、Currency(货币)、Boolean、Dictionary(字典)、Link(关联模型)、LinkMany(关联模型对多)、LookUp(反向关联)、LookUpMany、Image、Attachment(附件)、GeoArea(地理位置)等经常使用的字段类型。

模型、字段到表的映射

如上面模型的定义,在数据库中创建表的语句如下:

CREATE TABLE `erp__staff` (
`id` bigint(20) NOT NULL,
`createdAt` datetime NOT NULL COMMENT '创建时间 ',
`updatedAt` datetime NOT NULL COMMENT '更新时间 ',
`isDeleted` tinyint(4) NOT NULL DEFAULT 0,
`deletedAt` bigint(20) NOT NULL DEFAULT 0,
`CreatedBy` bigint(20) DEFAULT NULL COMMENT '创建人 ',
`UpdatedBy` bigint(20) DEFAULT NULL COMMENT '最后修改人 ',
`name` varchar(256) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '姓名',
`company` bigint(20) DEFAULT NULL COMMENT '所属公司',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

视图

视图是页面具体的展现形式,给用户最直观的产品体验。下面,我们看一个视图的例子:

  • 视图定义:
<?xml version="1.0" encoding="UTF-8"?>
<View menuView="true" type="List" forModel="erp_Staff" title="员工列表">
<Table model="erp_Staff" dataCondition="">
<Search>
<Fields>
<Field name="name"/>
<Field name="company"/>
</Fields>
</Search>
<Fields>
<Field name="name"/>
<Field name="company"/>
</Fields>
<RecordActions label="操作">
<Action label="详情" targetView="erp_Staff_StaffDetails"/>
<Action label="编辑" targetView="erp_Staff_StaffEdit"/>
<Action label="删除" after="Refresh" logicFunction="erp_StaffDeleteFunc" type="Delete" confirm="确定删除吗?"/>
</RecordActions>
<Actions>
<Action label="新建员工" targetView="erp_Staff_StaffCreate"/>
</Actions>
</Table>
</View>
  • 界面样式:

image-20220106150036501 我们可以看到,这个视图的内容非常少,没有写任何 Dom 或者样式,逻辑代码。只声明了一个

、 绑定模型、声明了那些字段用作搜索、那些字段用来展示、有那些 Action 操作。我们的模板只保留了变化部分,比如我们要展示的是什么模型,需要展示那些字段。其他非变化部分, 都被和
这样的标签所描述了。 至于这些字段需要怎么展示,以什么样的形式交互,校验逻辑以及提示等,都被 Trantor 处理了。 大致理解了模型的抽象之后,再看界面是如何映射出来的,就比较好理解了:

  1. Table 绑定了一个模型,而之前已经将字段的 Java 类型抽象成了 Trantor 的数据类型;
  2. Trantor 抽象的数据类型都有对应前端组件存在,会自动映射到前端界面控件,在搜索、展示、表单、列表中的行为会自适应、包括货币、附件、地理位置等复杂组件也一样;
  3. 字段上声明的字段名、是否非空以及其校验失败的提示,都会被抽取出来,变成界面上的字段标题,字段校验等;
  4. Link字段类型会让前端理解这是一个关联关系。所以相关的选择器,展示组件都会特殊处理;

逻辑

当我们定义完模型、视图后,接下来要考虑的是如何触发业务行为、如何获取视图数据等操作,这时候逻辑就登场了。作为Trantor数据交互重要一环,逻辑和视图的关系是:视图中可以为逻辑提供需要提交的业务数据,同时逻辑能够为视图加载需要展示的数据;逻辑与模型的关系是:逻辑能够通过模型获取模型数据,同时,逻辑又能够增加、修改、删除模型数据。 我们拿逻辑中的逻辑函数从定义到使用举例:

  • 页面逻辑函数定义:

image-20220106150059140

在页面定义逻辑函数后,Trantor会生成一个interface接口文件。

@Function(name = "create staff Function")
public interface StaffCreateFunc {
void execute(Staff staff);
}
  • 编写实现
@FunctionImpl(name = "create staff function impl")
public class StaffCreateFuncImpl implements StaffCreateFunc {
@Override
public void execute(Staff staff) {
DS.create(staff);
}
}
  • 使用逻辑

标签中定义 logicFunction=“erp_StaffCreateFunc”

<?xml version="1.0" encoding="UTF-8"?>
<View type="Form" forModel="erp_Staff" title="员工创建" >
<Form model="erp_Staff">
<Fields>
<Field name="name"/>
<Field name="company" label="所属公司"/>
</Fields>
<Actions>
<Action type="Submit" label="提交" after="GoBack" logicFunction="erp_StaffCreateFunc"/>
</Actions>
</Form>
</View>

从编写实现中可以看出,用户需要在实现类上配置@FunctionImpl注解,配置完成之后,Trantor会讲这个类加入到Spring容器中。 用户只需要声明logicFunction=“erp_StaffCreateFunc”即可,StaffCreateFunc为接口名称,在这里有java开发基础的同学应该可以看出来了,Trantor在逻辑这部分的实现机制是通过反射来调用的,其中入参由视图中的字段提供。 和传统的springboot写controller开发不同, Trantor可以从模型、视图中的字段定义,获取完整的接口入参。因此无需由前端写特定的请求接口,在一个后端人员定义视图后,基本功能几乎不需要前端参与,这一定程度上节省了开发资源,同时也节省了前后端联调成本。 上面描述的模型创建(修改、删除同理)行为。同时,逻辑函数也可以作为视图获取使用,道理也是一样的。

交付的抽象

研发的抽象可以提升我们在研发过程的效率,让我们用更少的代码表达更多的业务。但是我们在真正做软件交付过程中,更多的是在大软件上做修改,所以我们提供了一套二开机制来支撑。

资源化

上面触发逻辑调用的时候,Trantor只需要定义:logicFunction=“erp_StaffCreateFunc”,就能触发逻辑的调用。大家有没有想过,Trantor是如何设计的呢? 其实,在Trantor下,每个资源都有唯一对应的resourceKey,针对原始模块对应的资源key,只要在二开模块增加相同的资源key,然后使二开的资源key生效,而原模块的资源key失效即可。 上面的模型、视图、逻辑都是一种资源,Trantor的metastore模块会保存这些资源信息。

资源生效

image-20220106150112053

上图描述的是资源仓库的分层,最底层是标准产品Gaia,在往上是Gaia-App等应用,再往上就是交付层(Custom layer)。我们以上面的逻辑来举例: 在Gaia层,有一个创建StaffCreateFunc的实现GaiaStaffCreateFunc,Gaia-B2B有一个实现GaiaB2BStaffCreateFunc,甚至在Custom-layer 层也有对应的实现CustomStaffCreateFunc,当用户在视图中定义逻辑logicFunction=“erp_StaffCreateFunc”,Trantor又是如何找实现?

当用户打开一个页面时,这个页面会在请求头带有当前页面属于哪个资源仓库的标识Trantor-AppKey,

  • 当Trantor-AppKey=Gaia,则会找到 GaiaStaffCreateFunc
  • 当Trantor-AppKey=Gaia-B2B, 则会找到 GaiaB2BStaffCreateFunc
  • 当Trantor-AppKey=Custom layer, 则会找到 CustomStaffCreateFunc

但是,如果Trantor-AppKey=Custom layer,Custom layer却没有实现StaffCreateFunc呢?

Trantor将依次往父级资源仓库找,先在Gaia-B2B层,如果没有,则到Gaia层,如果Gaia层也没有, 因为 Custom layer(定制层) 只能单继承,但又得有最大的控制权限,所以会按依赖的App安装顺序,去找对应App链路里的实现,直到找到为止。

同样,该元数据的隔离机制也适用于不同App的业务数据隔离。 首先,所有业务数据都有一个 bizAppKey 字段,该字段的初始值为当前链路中的 Trantor-AppKey。 执行数据查找的时候,会自动追加 bizAppKey 的过滤逻辑, 具体规则如下:

  • 当Trantor-AppKey=Gaia: 不走 bizAppKey 过滤
  • 当Trantor-AppKey=Gaia-B2B: bizAppKey in (当前和祖先链路) or bizAppKey is null
  • 当Trantor-AppKey=Custom layer:bizAppKey in (当前和祖先链路 + 依赖的app链路) or bizAppKey is null

Trantor所使技术栈

分类技术栈
Console&WorkspaceTypeScript 、SCSS 、React 、Nusi
MetaStoreJava8 、Kotlin 、SpringBoot 、SpringCloud / Dubbo 、Nacos 、Maven
Gatewaynginx、Consul
DataStoreJava8 、SpringBoot 、GraphQL 、jOOQ 、Sharding-jdbc 、MySQL 、Redis 、ElasticSearch 、RocketMQ
DalaranJava8 、Kotlin 、SpringBoot 、Camel

Trantor发展历程

版本特性
0.1 ~0.12Trantor自举;确定模型、视图、行为等资源;确定多租户,多环境概念;
0.13~0.15增加制品、定制概念;增加分库分表配置;
0.16~0.19增加逻辑流、可编排服务、扩展点、触发器、业务上下文、调度服务、原声接口、缓存等资源。废弃行为菜单项等资源;
增加资源仓库概念,废弃制品、定制概念;
第一次尝试多App协同运行的基线产品、App、交付物三条链路研发过程
1.0~业务域、模型、视图、逻辑流、可编排服务、扩展点、触发器、业务上下文、调度服务、原声接口、缓存、消息、树形自定义数据源、业务维度、插件机制等资源在线化,在线资源立即生效。
取消资源上报。
全面迈进在线化编排元信息。

Trantor 1.0 与0.18 及之前的核心修改点

Trantor 1.0的产品方向

元信息在线:Trantor 1.0 逐步将开发者的详设搬到线上,以在线、可视的效果透出元信息。同时为公司规范资源生成过程。

立即运行生效:研发在线编排的视图、模型、逻辑定义等信息可立即在运行态生效,免去发布和上报动作,优化使用链路。

1.0升级内容

全面在线化

模型在线编排 提供模型资源的在线创建,将配置功能化,分步完成模型的创建 image-20220106150136332 image-20220106150155290 视图在线编排 提供xml编辑器,可在线创建视图,并提供mock数据真实还原视图使用场景 image-20220106150207891 逻辑流在线编排 提供逻辑流的在线编排,支持逻辑函数在线的声明定义,并可被流程编排。 image-20220106150222472 其他资源在线编排

  • 字典在线编排
  • 扩展点在线编排
  • 业务上下文在线编排
  • 触发器在线编排
  • 调度任务在线编排
  • 缓存在线编排
  • 消息在线编排
  • 树形数据源在线编排
  • 业务维度在线编排
  • 插件等资源在线编排

研发链路

资源规范化 取消线下上报,保证元数据一致性 ​

链路轻量化 两态合并(研发态和运行态合并),免去上报和发布过程,提交后资源即时在workspace生效

便捷灰度验证 支持多模块灰度实验,可按需分模块逐步验证在线化功能