0. 整体架构
一图胜千言:
整体横向分成前台、渲染、后台三个部分,底层抽象出了数据和服务部分。按照使用者的视角(使用者又分为低代码平台使用者和通过低代码平台搭建出来的业务应用的实际用户)分别来看:
- 在低代码平台创建一个租户,可以让平台知道是哪个业务在用;
- 在租户下创建应用,可以有多个,一般来说,一个应用指代一种业务场景或者模块;
- 基于应用创建页面,应用中往往会有多个页面,如首页、列表页、详情页等,并建立页面之间的关联关系;
- 绘制具体页面,页面往往有多种控件构成,如图片、输入框、按钮、标签等等,为页面填充与后端接口的交互逻辑;
- 预览页面,没问题后将设计信息提交并保存到后台通用数据;
- 后台服务集成通用服务,通过租户、应用拿到页面的设计信息与填充信息;
- 通过前台定制的渲染引擎,将设计信息、填充信息、权限信息完整的渲染并呈现给用户。
下面会围绕着前台、数据重点展开。
1. 前台部分
类似宜搭,支持原生组件和自定义组件,控件支持属性定制以及事件定义。网上这类组件拖动定义页面的实现有很多,原理大同小异,即元素控件化,布局模板化,最大限度的降低前端页面的生成门槛,目标使非前端背景甚至非技术背景的用户也能够上手使用。
前台部分分为设计态和运行态,因此前端的工作集中在支持多类控件画板以及渲染引擎上。上图呈现的是设计态,使用者通过拖动控件构建页面,点击保存,将设计信息保存到后台;设计信息是经过特殊设计的一种结构化的数据结构,渲染引擎可以方便使用,快速组装页面骨架并填充对应的信息。
2. 数据部分
介绍一下数据选型的一些测试,供大家参考:
测试基准
测试机器:2C4G centos
MongoDB version: 2.6.12
数据库构造
> show dbs admin (empty) local 0.078GB mcompanydb 5.951GB mtestdb 0.078GB > show collections company relations system.indexes users > db.users.count() 4307780> db.company.count() 23> db.relations.count() 4307780
空间占用:单位M
db.users.stats(1024*1024) { "ns" : "mcompanydb.users", "count" : 4307780, "size" : 2037, "avgObjSize" : 496, "storageSize" : 2763, "numExtents" : 21, "nindexes" : 2, "lastExtentSize" : 721, "paddingFactor" : 1, "systemFlags" : 1, "userFlags" : 1, "totalIndexSize" : 294, "indexSizes" : { "_id_" : 133, "address_1_cid_-1" : 161 }, "ok" : 1}
ns: 集合的命名空间,可以理解为集合名称
count: 集合中的文档总数
size: 集合中数据占用空间大小,不包括索引 ,单位为字节
avgObjSize: 平均对像占用的空间大小
storageSize: 给整个集合分配的存储空间,当删除集合中的文档时,这个值不会降
numExtents: 连续分配的数据块
nindexes: 索引个数,每个集合至少有一个 _id 索引。
lastExtentSize: 最近分配的块的大小
paddingFactor: 存储空间冗余系数,1.0表示没有冗余,1.5表示50%的冗余空间,有了冗余空间,可以让后续引发size增加的操作更快(不会导致重新分配磁盘空间和文档迁移),一般是在1到4之间
totalIndexSize: 所有索引大小总和
indexSizes: 列出集合的所有索引,以及索引大小。
表结构
> db.users.find().limit(1).pretty() { "_id" : ObjectId("5ea26050a3f638bccbb4cc14"), "uid" : "qiycn0boe1KXZtSUCdk6GMWRrjmwYQxF", "name" : "韦媏耣", "phonne" : NumberLong("12769940492"), "describe" : "鸭愗绹邔倆礈眿隉撛猯閰犡爣腎艈窱牊岑恘諎", "address" : "第703街道", "sex" : "未知", "mail" : "5eb714f@126.com", "cid" : 1} > db.company.find().limit(1).pretty() { "_id" : ObjectId("5ea26050a3f638bccbb4cc13"), "cid" : 1, "name" : "萉珎軃駳娑簯有限责任公司", "address" : "枼茺路第822号", "phone" : "0640-34794278", "mail" : "43b2@gmail.com", "describe" : "蜵繝瀘鲄耿鋜嘃韥陭衍蒖葯擉峯崔氢碊棊俅帬汦蔾饛狹科擇椂丄矔惏膯剣与借纹礬勺俼鞀蟇咯圬蓳穌伂貫騦瀮詜蟆蝗珩軽泳撳奁伥烪璤缯極輷廵雿眏瘋餸耳喩棢焒悻錗孭帾泴羏揮萧瀤鞹姥涃癌旵撬倲胏憺奆洴契藘鹲娪阴趁陡瓃糥扅韾莝脀爋湜帀炥趺闈澂药蕗磷酸葙齺鮧元暃杦噢槧墷姴佮趕籛迆崫懫琏龎鵁踹謩竬牙琹奅梃艭嵫梒谮棘朵皲觰羺鰀軝头妺姖暣幭改豂徖徼偛匋攕翄覵跽鋹掣賠鑛谄蚄薅縓媂罣齚奶嗄莒蛻欇媥俊僢艪姁脚痒簈購葟靧傁拀莟濖袝吠"} > db.relations.find().limit(1).pretty() { "_id" : ObjectId("5ea26050a3f638bccbb4cc15"), "cid" : 1, "uid" : "qiycn0boe1KXZtSUCdk6GMWRrjmwYQxF", "ctime" : "2020-04-24 11:43:12"}
无索引查询测试
cost time:0.11801719665527344ms {'_id': ObjectId('5ea26050a3f638bccbb4cc36'), 'uid': 'rPFEmTVx1t2RUMaJdB9Oc8k0yfeLvowZ', 'name': '毛卙岝', 'phonne': 17627067963, 'describe': '釮玦羋蚿徕鲚僞请徹祣罇嚐貵鍕腆轼燿舆糖忰', 'address': '第509街道', 'sex': '男', 'mail': '26e7794@126.com', 'cid': 1} sample query get data cost time:64.3472671508789ms cost time:0.3273487091064453ms {'_id': ObjectId('5ea502df51e5bdd9b33a3390'), 'uid': 'ZH7mIfGDW2blKEzg63qwV5a4scYkp9TL', 'name': '于彦髏', 'phonne': 13600434556, 'describe': '雨苦棡儋锌斘韝宿脾屨鵭锊琁鳖笵橇縅邴顅秇', 'address': '第505街道', 'sex': '未知', 'mail': 'ec5addd@126.com', 'cid': 22} page query get data cost time:1821.9256401062012ms
加索引后查询
> db.users.getIndexes() [ { "v" : 1, "key" : { "_id" : 1 }, "name" : "_id_", "ns" : "mcompanydb.users" }, { "v" : 1, "key" : { "address" : 1, "cid" : -1 }, "name" : "address_1_cid_-1", "ns" : "mcompanydb.users" } ]
执行情况:
cost time:0.1595020294189453ms {'_id': ObjectId('5ea521374bf8e57b01e37301'), 'uid': 'uxH8U4vaNjI2yPnQTEliwWreMzR1AD9Y', 'name': '雷靁', 'phonne': 18855012674, 'describe': '瓱蛘褁駏針辖堢腨閽唩曕抰鹼貄頛蓭腐擜霗蕜', 'address': '第509街道', 'sex': '女', 'mail': '85845b1@126.com', 'cid': 23} sample query get data cost time:4.01759147644043ms cost time:0.25963783264160156ms {'_id': ObjectId('5ea5214a4bf8e57b01e412c9'), 'uid': 'WsXNcGKdEjBaJAI5QO7evLMRyCwPi4nf', 'name': '邬仵絩', 'phonne': 17589900635, 'describe': '胆鬤件羁痓覝竮囶砿狐都湮繺裷洘誮鰑飗歬跨', 'address': '第505街道', 'sex': '未知', 'mail': 'ddda442@126.com', 'cid': 23} {'_id': ObjectId('5ea5214b4bf8e57b01e41a81'), 'uid': 'aAKxPWeznQSCvlrX8JpUjiqcVOhgusRm', 'name': '金禪', 'phonne': 16803644112, 'describe': '鵆匛絯劖廓谧鶤績絓攌俜苃茮昔抳簋搇跊跖告', 'address': '第505街道', 'sex': '男', 'mail': '6e3c0e4@126.com', 'cid': 23} {'_id': ObjectId('5ea5214c4bf8e57b01e423fb'), 'uid': 'TfFxuOySoELI4q9GvHek86tJPzdsrNBR', 'name': '尹渉憨', 'phonne': 18710450580, 'describe': '闿虹爾妗艬溌酩欁爖坅砞掅藄搉啵撮聹屓鞇畉', 'address': '第505街道', 'sex': '女', 'mail': 'b5a603d@126.com', 'cid': 23} {'_id': ObjectId('5ea5214e4bf8e57b01e4359f'), 'uid': 'buKMOPLY2iVFT6Zv1U5H3ESNfpljDCq0', 'name': '项厏', 'phonne': 12785716135, 'describe': '鼌么瀉菋篡蓏戵蜸协姭痤競絡哗謩洚淜侭瀾蠜', 'address': '第505街道', 'sex': '男', 'mail': '1726144@126.com', 'cid': 23} {'_id': ObjectId('5ea5214e4bf8e57b01e4361f'), 'uid': 'lujgtnbcFLZXaivmqsNfoVPQrhkWSHyY', 'name': '华欂鹪', 'phonne': 17947129260, 'describe': '嗨紑樠嶕扏阓娷逞掸晌狝竨延藑什甭簿緮媂陛', 'address': '第505街道', 'sex': '未知', 'mail': '34eefef@126.com', 'cid': 23} {'_id': ObjectId('5ea5214e4bf8e57b01e43685'), 'uid': '8WZvgPpl1NeLq3o2KHFfbMX9szkUyQ6R', 'name': '米輠', 'phonne': 14050750640, 'describe': '澘盾獁丙螸硫鉬袱櫘輄寠馾籯菅鱤箉歰覇鏨霟', 'address': '第505街道', 'sex': '未知', 'mail': '9078ef1@126.com', 'cid': 23} {'_id': ObjectId('5ea5214f4bf8e57b01e43855'), 'uid': 'DajPmKFcZVkhq5BRsQi1uNdTXnoUfzyx', 'name': '贝渂墮', 'phonne': 14230037714, 'describe': '娡嘽撋鰿釈龥蛸痱賋钦憳鹌覗稖勶阝镚谉筺蟏', 'address': '第505街道', 'sex': '未知', 'mail': '7cf7c85@126.com', 'cid': 23} {'_id': ObjectId('5ea521514bf8e57b01e4499b'), 'uid': 'PbHm08Yg7N9BWMFlGkwIVxuzScR6Kfnh', 'name': '滕悒', 'phonne': 14418181928, 'describe': '駂液诟赐搵籑捷惍鏣薿螎蔪幤訁腼肬嵾胚鬺嶞', 'address': '第505街道', 'sex': '未知', 'mail': 'b8f5f39@126.com', 'cid': 23} {'_id': ObjectId('5ea521534bf8e57b01e45e85'), 'uid': 'lysQhr82670uXcqen3bHZmjdKivASG5k', 'name': '倪埚', 'phonne': 15183320006, 'describe': '姀嶀潌鎩搤鵐侷僴痏節纈喠拤睘痖盬虀刞缊弢', 'address': '第505街道', 'sex': '女', 'mail': '8578e9f@126.com', 'cid': 23} {'_id': ObjectId('5ea521544bf8e57b01e466dd'), 'uid': 'kZ3A2MLK0ReJsX5rD8BzG6qgxHSP9hun', 'name': '任羳怭', 'phonne': 13396431444, 'describe': '嫢顉酔烴疬依嘆讗廃逃樥亨焩噫聥褠醼朶粥籐', 'address': '第505街道', 'sex': '男', 'mail': 'fb1ab32@126.com', 'cid': 23} page query get data cost time:1.2955665588378906ms
正则匹配
正则匹配有索引的字段(like '%xxx')
cost time:0.025510787963867188ms {'_id': ObjectId('5ea521384bf8e57b01e38159'), 'uid': 'yUWCsc5HVzYorJIpPiSL8ExR7ueD2XKg', 'name': '水鰟颜', 'phonne': 19025312730, 'describe': '豅軵叾熚鎌性柗饀鷧昙赚摫脊篈磞鲰搯岭歧注', 'address': '第500街道', 'sex': '未知', 'mail': '8aefd13@126.com', 'cid': 23} regex query get data cost time:1.3136863708496094ms
大数据插入
大json,压缩后317KB
字符长度:308286 首次插入: cost time:160.83574295043945ms 再次插入: cost time:5.072832107543945ms
3. 总结
受限于篇幅,本文重点阐述了比较核心的前端架子和数据存储选型,有兴趣的同学欢迎留言互动交流。