双链科技DaaS运行时架构说明

386 阅读14分钟

双链科技DaaS运行时架构说明

第一章概述

DaaS是成都双链科技的一款低代码平台,通过简单的易行的定义方式,能够生产前端,中台,后台等系统核心组件以及数据大屏等极具实用价值的衍生产品。 本文主要说明后台的运行架构,便于使用者理解DaaS的业务处理机制,更容易扩展DaaS,实现自身业务;同时理解DaaS提供的诸多基础资源,减少开发工作,提高效率,保证系统稳定性。

第二章DaaS的编程实践

表面上看,DaaS是一个通过代码生成实现的低码产品。 事实上,DaaS更多的是体现软件工程的两个重要实践: 1.最佳实践的持续化; 2.受控的可扩展性。

2.1 最佳实践的持续化

一个长期运行的系统,面临的一大挑战就是各个时期的开发风格不同,导致系统行为不一致,甚至互相抵触,带来性能和稳定性的问题,例如错误处理,接口风格等。

DaaS生产的代码,是大量实际项目的最佳实践的精华,开发人员在DaaS代码框架下开发,不用关心这些细节问题,不用担心模块间的耦合,系统间的交互标准等这些问题,可以集中精力在业务处理上。

2.2 受控的可扩展性

大部分市面上的低码平台,都不能提供自然顺畅的扩展手段。简单的业务还可以, 复杂一点的,例如需要和旧有系统集成,就无法支持或者需要大动干戈的改造。随着业务的发展,系统之间,系统内模块之间,逐渐产生了千丝万缕的关联,破坏了系统最初的设计原则,导致系统越来越难以维护,最后变成一个黑盒。

DaaS生产的代码,提供了架构的最佳实践,既预留了丰富的扩展点,让定制业务可以顺利的加入,也保证了业务之间的低耦合,可以保证很长一段时间内系统架构的稳定性。这是第一层保障。 同时,由于基础架构代码都是根据标准生产的,所以,基础设施本身是可以无缝升级的。 例如我们发现了远程调用更好的实施方式,那么只要使用升级后的DaaS重新生产代码就可以了,业务代码仍然是使用基础的Java编程方式,完全不受任何影响。这是第二层保障。

有了双层保障,使用者既可以放心的扩展业务逻辑,也不用担心日积月累的变化逐渐侵蚀系统。

第三章DaaS运行时架构

图中红色部分是DaaS生产的代码中,自动生成的标准部分; 图中黄色部分是预留的扩展点。可以看到每一处都预留了扩展点。 所有的核心业务,都是在UserContext的参与下完成的。

  • 1.请求处理层:将外部请求转化成对应模块的方法调用,作用类似于Controller层;
  • 2.UserContext: 所有的业务处理,都是在UserContext的参与下完成的。 UserContext由框架组装,它提供了众多的基础服务,如图所示, 有短信服务,通知服务,缓存服务等。后面会详细介绍。
  • 3.业务逻辑层:大部分定制化的业务逻辑在此处完成。 后面会详细介绍。
  • 4.基础功能层:DaaS为每一个模型都提供了基础的增删改查功能,业务层只需要使用Manager的各种接口就可以完成业务处理。 在必要的情况下,才需要扩展Manager。
  • 5.数据持久层:用于数据持久化。

基于DaaS提供的框架,可以轻松的构建实际所需的服务拓扑,例如:

3.1 UserContext与基础服务

用户上下文(UserContext)是整个业务处理过程中的一个核心对象。 顾名思义,它是指一次业务处理中的所有相关信息(上下文)的入口。

和业务处理相关的,有两大类信息: 一类是业务本身的信息,例如:是谁在处理什么事情?请求了什么资源? 另一类是基础服务,例如:我要发给短信通知下一步的负责人该怎么办?

3.1.1 业务上下文

对于第一类信息, 使用者可以扩展userContext, 增加所需的信息。 在DaaS生产的代码中, 已经支持以下几种信息: 1.当前用户及其APP; 2.手机号; 3.订单号; 4.微信openId; 5.地理位置信息(需要用户授权) 6.当前请求的Header,Cookie等;

此类信息通常和业务密切相关,需要根据业务需要进行扩展。在这里提供一些预定义信息的目的,主要是为了标准化相关接口。这也是最佳编程实践的一个体现。

3.1.2 基础服务

对于第二类,基础服务,DaaS全部通过接口提供的,这样方便用户根据实际情况,扩展或者替换具体实现。 DaaS已经提供了:

  • 1.缓存服务:默认提供Redis实现。 完成数据缓存,Session数据保持等。
  • 2.区块链服务:默认提供Fabric实现。完成数据上链,查询等;
  • 3.Elastic Search服务:默认提供7.6版本的客户端,实现搜索功能;
  • 4.电子邮件服务: 默认提供Java Mail的实现,实现电子邮件发送功能;
  • 5.短信服务:默认提供阿里云短信服务的实现,完成验证码发送等短信功能;
  • 6.位置服务:默认提供QQWRY的实现,完成IP地址到地理位置的转换功能;
  • 7.内容管理服务:默认提供了基于字典的敏感词过滤功能。用户可扩展字典。
  • 8.推送服务:默认提供了极光的实现,完成消息推送的功能
  • 9.消息中间件:默认提供了Kafak的客户端,完成消息发送和消费;
  • 10.对象存储:默认提供阿里云和七牛云的实现,用户可以通过配置选择。
  • 11.身份认证:默认提供:账号/密码,手机验证码,微信OpenID,企业微信认证。
  • 12.图数据库:默认不打开此功能。支持ArangoDB,TigerGraph。

此外,还提供了API:

  • 1.请求级别的数据缓存;
  • 2.Http 请求/响应的Header的相关功能;
  • 3.国际化支持
  • 4.其他模块的标准通讯方式 等基础功能接口。

3.2 业务逻辑层(service)层

Service层是DaaS对最佳实践的一个体现。遵循CQRS原则(命令查询的责任分离Command Query Responsibility Segregation )。通过DaaS的工具,会生成一套标准的业务请求处理代码框架。

请求到达DaaS的后端,首先会被附加一个UserContext,然后请求的标准处理流程如下图所示:

红色部分是DaaS自动生成,基本无需扩展的部分; 黄色部分是DaaS生成骨架,需要人工完成具体业务逻辑的部分。

3.2.1 前置处理

请求标记: 如果后续需要完成“重复提交”,“历史检索”等功能,需要在此处先进行必要的处理; 权限检查:确定当前用户是否有权限请求本次服务;

3.2.2 请求处理

日志记录:通过权限检查的请求,都会记录对应的日志,后续处理有据可查; 参数处理:将请求的输入,封装成统一的Java 数据类型,这样后续业务变更和升级时,无论是业务变化,还是基础设施本身的升级,都不会受到影响; 业务处理:普通的增删改查业务,DaaS自动生成的代码已经完成支持,这里是客户定制化业务的主要位置,后面会单独说明;

3.2.3 结果组装

DaaS的业务处理,是遵循CQRS原则的,“3.2.2 请求处理”就是 Command 对应的部分;‘结果组装’,就对应着Query的部分。 简单来说,根据处理结果的不同,组装不同内容的结果返回给请求的发起者。

3.2.4 后置处理

后置处理主要包括几个方面: 1.访问成功的结果,根据业务脚本(通过DaaS的工具)描述,是否需要做缓存; 2.‘重复提交’相关的后续处理; 3.有顺序的事务请求。例如,发表文章,需要发放奖励。假设两个业务是不同的事务,那么,就不能在记录文章的同时,开始发放奖励的事务,这样会很大概率的导致发放失败,因为‘发表文章’的事务尚未结束,此时‘发放奖励’抢先被调度,则无法查询到对应的文章,导致发放失败。 DaaS提供了6种标准的模块间通讯方式,此时可以采用“延迟请求”方式,在前一个事务完成后,再发起第二个事务。关于6种通讯方式,后面会说明。

3.3 基础功能(Manager)层

DaaS为业务模型中的每一个类型,都创建了对应的Manager。 Manager提供每种类型的基础服务,包括:

  • 1.创建(Create)
  • 2.更新(Update)
  • 3.删除(Delete)
  • 4.各种查询,候选值查询
  • 5.子对象添加、删除

3.4 数据持久(DAO)层

DaaS提供了标准的数据持久层实现。目前支持多种数据库,包括Oracle,PostgreSQL,H2等。默认为MySQL。

第四章请求处理与业务定制

DaaS的后台处理请求,大致分为3类:

第一种是普通的查询请求,基本上无需特殊处理,直接查询结果,组装数据即可(简明起见,图中忽略了通用的处理细节,例如权限,日志等);

第二种是简单的业务请求,例如“签到”,“完成浏览”。它们会对业务产生较小的‘变更’,(例如积分变化),本身也很简单,此时一般会调用/触发业务逻辑的处理(Business Processor的同/异步调用),然后组装返回数据;

第三种是重要的业务请求。例如“转账”,“审核通过”等。它们是重要的业务事件,对系统的核心功能流程有重大影响。DaaS定义此类请求,都必须通过ChangeRequest来完成。(ChangeRequest是一种具有特定数据结构的对象)。 因此它们需要先通过 ChangeRequest Processor 的处理,然后在提交时调用/触发业务逻辑处理。

4.1 Change Request

Change Request, 称为“变更请求”,它包含以下基本信息:

  • 1.谁在发起;
  • 2.发起何种请求;
  • 3.该请求包含哪些数据;

例如,分销人员提交一个‘推荐线索’时,会提交这样一个Change Request:

  • 1.分销员 D000001 提交此请求;
  • 2.这是一个 ‘建立推荐线索申请’ 的请求;
  • 3.包含信息:
    • i.2级类目 XXX
    • ii.联系人姓名及联系方式
    • iii.可能的数量
    • iv.其他说明

DaaS采用ChangeRequest 和普通的表单相比较,具备以下优点:

1.标准化。所有业务处理模块,需要提供的接口,都是标准java对象,不需要考虑请求的是Form还是Json之类的;

2.低耦合。举个例子,无论是Form还是REST接口,DaaS都会转换成标准的Change Request,请求方式和处理部分没有耦合的部分;

3.可追溯。因为标准化,所以可以方便的追溯任何业务变更的来源。

4.高可靠。类似于数据库的Bin-log,由于统一记录了所有的业务请求,那么就保证了重放业务的可能性,在容灾等可靠性场景中天然具备优势。

4.2 事务管理

DaaS使用Spring来管理事务,通过注解方式标注事务。 通常,一个公开的Service接口即一个本地事务。

对于分布式的事务,DaaS的策略是满足最终一致性。

4.3 扩展与定制

用户有两种方式定制自己的业务。

第一种,就是在DaaS预留的扩展点上直接定制。

DaaS生成的代码,包括各种Service,Manager, DAO 都是有对应的 CustomService, CustomManager, CustomDAO,开发人员直接在这里写代码完成业务即可。

第二种,是编写自己相对独立的业务模块,在Service中将请求中相关的业务,转交给对应的业务模块来处理。

对于第二种方式,为了满足各种业务场景,DaaS提供了6种模块间的交互接口。使用这些标准接口,开发者可以只编写标准的Java函数,无需考虑异步问题。

4.4 模块间的标准交互模式

软件系统内部耦合性出现的原因之一,就是各种模块之间的业务功能是互相依赖的,大部分耦合性的产生,就是一句简单的 “B.func(p1,p2,p3)”这样的调用。 当然,设计因素也是很重要的,DaaS在正确设计的前提下,提供了6种通讯方式,来尽可能的将各个模块的“你中有我,我中有你”的状况缓解。

4.4.1 立即处理

这个很好理解,就是 A 模块要求 B 模块处理一个请求,并且等待拿到结果以后,再继续。

4.4.2 立即处理,稍后检查

这个就是立即请求另外一个模块的处理,但是直到需要的时候,才检查处理结果是否已经完成。 DaaS将模块B的响应结果,封装到一个Future中,来实现异步执行。

4.4.3 立即处理,不再关心

这个就是完全异步执行,A,B之间没有后续的协作关系。

4.4.4 延迟处理

如下图所示:

这个方式是:

  • 1.首先模块A在业务处理的合适时机(例如一个分支判断成立时),请求模块B在本次事务结束后,接着处理后续事件;
  • 2.UserContext获得此请求,将其存入‘deferred’队列
  • 3.本次事务结束后,CAF启动后置处理
  • 4.在后置处理中,UserContext发送此前记录的请求,并等待处理结束
  • 5.所有deferred请求处理完毕,结束

注意:本场景是明确要等待deferred的请求同步处理完成后,才继续执行。 如果无需等待,请使用另外的请求模式。

4.4.5 延迟处理,最后检查

这个的意思就是:延迟到本事务结束后才开始处理,并且要保证最终都处理完了,才返回response。 和 “延迟处理” 不同的地方在于: 延迟处理是发起请求后,要等待该业务处理完毕后,才发起下一个请求; 而本模式是把所有能发的请求都发了,然后只要保证返回response前,这些请求都处理完毕即可。

4.4.6 延迟处理,不再关心

这个就是只要保证在本事务结束后发出请求即可,处理的结果不关心。

可以看到,在DaaS的编程框架中,业务模块只需关注业务实现,各种所需的基础服务,交互渠道以及方式,都有DaaS负责完成,可以避免大量的细节处理,同时最大限度的保证了高聚合,低耦合的最佳实践。

4.5 结果数据组装

DaaS后台处理的结果数据,会以JSON的格式序列化。 对于DaaS生产的标准中台,将会无缝的解析这些数据; 对于Restful的第三方接口,需要双方协商一致; 对于前端设备,DaaS默认的会组装成NiceRouter的组件。

附录

附录1:DaaS的外部依赖

DaaS提供全部的源代码,因此可以清晰的看到所有的外部依赖。 DaaS后台的所有依赖,都在bizcore/build.gradle 中。 截止目前,依赖包括:

1.JWT token
2.阿里云 SDK
3.阿里云短信服务
4.阿里云对象存储
5.微信SDK:wechat-group
6.Java mail
7.Mysql connector
8.H2 connector
9.Kafka
10.HikariCP
11.Elastic search
12.Spring boot 
13.七牛云 SDK
14.OK Http
15.Redis
16.Apache POI
17.QQWRY

附录2:参考文档

[1] DaaS 概要与建模: kdocs.cn/l/sS9sjXdPo…

[2] Daas-Start-Kit快速配置与开发准备: kdocs.cn/l/st71C0iyb…

[3] DaaS 服务端 Java二次开发指南: juejin.cn/post/684490…

[4] NiceRouter: github.com/doublechain…

[5] 最终一致性的实现方案: www.jianshu.com/p/fa225912e…