架构设计
- 文章作者: flytreeleft - flytreeleft@crazydan.org
- 文章链接: https://duzhou.crazydan.io/docs/development/arch
- 版权声明: 本文章采用许可协议《署名 4.0 国际 (CC BY 4.0)》。 转载或商用请注明来自渡舟平台!
采用自顶向下的设计模式,并仅声明要做什么,而不涉及如何做的问题。
自顶向下可以将整个平台划分为以下部分:
平台直接面向使用者,为用户提供访问入口,并将用户触发的请求转发给应用; 而应用是一类功能业务的集合,负责响应用户业务处理需求; 而服务为业务应用的功能集合,负责处理一组业务功能,为可独立运行的实体; 模块则是对业务功能的组织,一般为导航菜单。
也就是,一个或多个模块组成一个服务,一个或多个服务组成一个应用, 一个或多个应用组成一个平台,一个平台面向一个或多个用户。
<!-- 按照状态迁移的模式进行 DSL 设计 -->
<platform displayName="渡舟平台" domain="duzhou.crazydan.io">
<!--
@url 用于标识请求的路由,也就是平台将根据 url 将对应的请求路由到指定的应用,
再由应用路由到指定的服务
@domain 被托管应用的访问域名,该应用是被独立访问和管理的,
平台只负责对其运行资源的分配和管理。注:对其请求的路由还是得经过平台
service@type 用于标识服务类型,具有相同类型标识的服务实例将被视为同一个服务,
用于以共享模式为多个租户提供服务,因此,可自由对服务实例进行增减。
对于定制化的服务,则由服务实例向平台注册不同的类型标识,
再在定义 app 时引入该类型的 service 即可
-->
<app displayName="平台用户应用" url="/user">
<services>
<!-- 一个服务就是一套可运行代码,但实际运行的可能会有多个服务实例 -->
<service displayName="用户服务"
type="PlatformUser" version="1.0.0">
</service>
</services>
<web>
<site subTitle="用户管理" url="">
<resources>
<resource displayName="角色管理" url="/role">
</resource>
</resources>
</site>
</web>
</app>
<app displayName="平台管理应用" url="/management">
<services>
<service displayName="平台管理服务"
type="PlatformManagement" version="1.0.0">
</service>
<service displayName="平台网关服务"
type="PlatformGateway" version="1.0.0">
</service>
<!-- 用于与 Agent 对接以部署和管理包括平台管理应用服务在内的全部服务 -->
<service displayName="平台控制服务"
type="PlatformCtroller" version="1.0.0">
</service>
</services>
<web>...</web>
</app>
<app displayName="租户管理应用" url="/tenant">
<services>
<service displayName="租户管理服务" url="/management"
type="TenantManagement" version="1.0.0">
</service>
<service displayName="租户计费服务" url="/charging"
type="TenantCharging" version="1.0.0">
</service>
<service displayName="租户自服务" url="/self-service"
type="TenantSelfService" version="1.0.0">
</service>
</services>
<web>...</web>
</app>
<!--
租户应用,本质上可视为在数据中添加了租户标识的普通应用,
实际开发的应用中可对数据模型始终加上租户标识属性,
从而便于直接接入到多租户平台中。也可以通过 Delta 机制无缝实现对多租户的支持。
租户应用,对于平台而言属于托管应用,平台仅负责维护其正常运行,
并对未激活的租户应用做访问限制,其余的均由应用自身处理。
-->
<app displayName="租户应用 A" url="/a" domain="tenant.duzhou.crazydan.io">
<services>
<!-- 用户服务为通用服务 -->
<service displayName="用户服务" url="/user"
type="User" version="1.0.0">
</service>
<service displayName="组织机构服务" url="/org"
type="Organization" version="1.0.0">
</service>
</services>
<web>...</web>
</app>
<app displayName="租户应用 B" url="" domain="b.tenant.duzhou.crazydan.io">
<services>
<service displayName="组织机构服务" url="/org"
type="TenantB_Org" version="1.0.0">
</service>
</services>
<web>...</web>
</app>
</platform>
平台以最大化资源利用率为原则进行各类应用的服务部署, 没有定制化的服务均为共享服务模式,有定制化的且可适用于多个租户的,同样也是共享服务模式。
平台(Platform)和应用(App)均为抽象概念,二者只是用于对不同层面的服务进行分组, 以方便对服务职能和作用范围进行管理。
服务(Server)为最小的部署单元, 可以动态将选中的一个或多个模块放到一个服务中做独立部署(服务实例可多个), 并且原则上使用独立的数据库(通过服务的配置指定数据库连接信息), 跨服务调用的模块内的模型,自动采用 RPC 机制。 服务控制的是运行时环境,为程序提供配置和运行支持,包括代码的动态性支持。 在服务部署时,平台会将服务内所包含的模块发到目标 Agent 上, 再由 Agent 完成初始化并启动服务。
平台自身将提供如下组件或服务,用于部署、监控和管理包括其自身在内的所有服务:
Agent
:部署代理,其将被部署在任意可用的主机设备上,并主动接入到平台中, 平台将通过 agent 部署各类应用服务,并会动态下发相关配置, 以让其所部署的服务将日志、监控数据等发送到平台指定的服务中- 接入平台需要提供唯一的接入码,其由平台生成, 在通过平台下载 agent 安装包时生成,仅可使用一次,且有有效期
- 平台提供的 agent 将会内置 SSL 公钥,以加密平台与 agent 之间的交互数据
- 由服务确定下发的配置哪些可即时生效,对于不能即时生效的配置, 在平台侧由用户确定是否需要重启
- 需监控主机可用资源,以便于动态分配服务资源
Gateway
:服务网关,负责路由外部请求到平台内部服务及其被托管服务上- 每个应用都有一个网关,负责路由 web 资源和 api 请求, 而在平台处也会部署一个入口网关,负责路由应用的请求到应用的网关
- 根据 url 路径和域名路由请求,对租户应用,需在请求头中附加租户标识
在从零开始的环境中,平台部署的过程为:
- 在选定的主机上安装平台运行包并启动其服务
- 通过目标主机的 ip 和平台服务端口访问服务
- 根据指导步骤完成平台初始配置
- 从平台管理页面获取 agent 安装包和接入码
- 按照 agent 安装的指导步骤在其他主机上安装 agent。 注:也可在提供了 ssh 帐号的情况下由平台自主安装(仅安装 agent 时才需使用 ssh 帐号)
- 由用户触发平台的初始化,包括自动安装 agent、部署 gateway、扩充平台服务实例等
开发过程为:
- 从
platfrom
开始逐步定义app
、web
、service
等 DSL - 根据 DSL 自动创建
web
、service
等应用服务的 Maven 工程,其包含最基础的依赖和配置
状态迁移
初始化开发环境
DuZhou.bin
为使用 Go 编写和打包的二进制可执行文件,
主要负责 渡舟平台 的开发环境的初始化。
其内置一个 Web Server 以便于开发者通过浏览器进行相关的初始化配置。
Go 可以编译出单文件、无依赖、轻量级的二进制文件,而且还可以跨平台编译, 能够满足快速进入开发就绪状态的要求。
在启动 DuZhou.bin
后,程序将创建一个 Web 服务,
并检查其运行所在操作系统中的开发环境:
- 根据环境变量查找
mvn
、java
命令的位置,并获取其版本号 - 判断开发工具的版本号是否符号要求:必须高于最低版本要求
开发环境检查完毕后,将会向浏览器返回检查结果,并由浏览器展示开发环境配置页面:
- Web 服务创建后,便自动打开浏览器并访问该服务
- 在开发环境检查过程中,前端页面处于等待状态
- 等待动效为 在海浪中行进的小船,按实际情况显示进度,不加最小延迟
- 进度信息包括:进度百分比、正在进行的处理
- 以 WebSocket 机制实现对检查结果的推送
在开发环境配置页面包含以下内容:
- Maven 配置:当前版本号、安装位置、本地仓库目录位置、远程仓库列表及连接信息、
是否满足最低版本要求等
- 若不满足最低版本要求,则提供默认版本的下载地址, 由开发者确认是由程序自动下载,还是由其自行下载。 若为自行下载,则需填写安装包的绝对文件路径
- 本地仓库目录位置从现有配置读取,支持指定新的仓库目录位置
- 补充必要的远程仓库和连接信息,如 Nop 包的仓库、渡舟部件的公共仓库等
- Java 配置:当前版本号、安装位置、是否为 JDK
- 若不满足最低版本要求或不是 JDK,则提供默认的下载地址。 同样可由开发者自行下载并填写安装包的绝对文件路径
开发者完成以上配置后,点击 开始初始化 按钮,由
DuZhou.bin
进行初始化工作:
- 下载指定版本的 Maven 或 JDK
- 若需安装新版 Maven,则将获得的 Maven 安装到
$DUZHOU_HOME/tools/maven/<x.y.z>
中, 并配置其本地仓库位置为$DUZHOU_HOME/tools/maven/repository
(默认位置)- 生成新的配置文件到
$DUZHOU_HOME/tools/maven/config
中,在使用mvn
命令时显式指定该文件的位置
- 生成新的配置文件到
- 若需安装新版 JDK,则将获得的 JDK 安装到
$DUZHOU_HOME/tools/jdk/<x.y.z>
中 - 记录已确认的 Maven 和 JDK 的版本、安装目录和相关配置
- 准备指定版本的 开发服务 部署包:可以由用户下载并放置到
$DUZHOU_HOME
中,或者,自动从默认位置下载 - 启动开发服务
应用开发
项目演示与开发可以以上下布局方式同时展示。
- 通过开发服务创建项目:填写项目名称、标识、Git 仓库等
- 选择并安装 Delta 包
- 定制化开发
- 业务模型可视化设计
- 模型更新后自动生成代码并构建
- 可实时查看调整结果
- 先设计业务模型,然后自动生成增删改查 API, 再创建模块,并指定模块内包含的 API 和页面资源
- IDE 辅助开发
- 直接从
$DUZHOU_HOME/projects/<xxx>
目录中导入工程 - 监控文件变化,并自动构建
- 提供 VSCode 开发插件,在 VSCode 直接集成浏览器和开发能力, 支持直接从显示元素中关联并跳转到代码位置
- 直接从
- 一键提交开发变更代码:查看并验证修改结果无误后,点击提交变更按钮, 并在填写变更日志后,提交并推送到 Git 仓库
- 应用版本发布
- Delta 业务打包
- Delta 版本打包
- 以版本为 Delta 层,新版 Delta 必然基于某个已有版本实施差量
- 根据变更内容提取 Delta,并将其打包为新版本
- 应用 Delta 需按照版本继承关系,从当前版本开始按继承顺序依次应用 各个 Delta 版本层。也可以动态打包两个版本之间的所有版本
应用服务部署
- 向可用主机内部署服务
应用服务运维
- 监控
- 调用链
- 性能
- 日志
- 管理
- 升级